From 7989cac274a8451dce05e9ff8f258d6da992a032 Mon Sep 17 00:00:00 2001 From: Min RK Date: Tue, 2 Jul 2024 14:09:42 +0200 Subject: [PATCH] trade entrypoints for importlib_metadata --- ipyparallel/cluster/app.py | 11 ++++++----- ipyparallel/cluster/launcher.py | 16 ++++++++-------- ipyparallel/tests/test_launcher.py | 7 ++++--- ipyparallel/traitlets.py | 20 ++++++++++++-------- pyproject.toml | 2 +- 5 files changed, 31 insertions(+), 25 deletions(-) diff --git a/ipyparallel/cluster/app.py b/ipyparallel/cluster/app.py index 9549562a..13c92b3f 100755 --- a/ipyparallel/cluster/app.py +++ b/ipyparallel/cluster/app.py @@ -11,7 +11,6 @@ import sys from functools import partial -import entrypoints import zmq from IPython.core.profiledir import ProfileDir from traitlets import Bool, CaselessStrEnum, Dict, Integer, List, default @@ -20,6 +19,7 @@ from ipyparallel._version import __version__ from ipyparallel.apps.baseapp import BaseParallelApplication, base_aliases, base_flags from ipyparallel.cluster import Cluster, ClusterManager, clean_cluster_files +from ipyparallel.traitlets import entry_points from ipyparallel.util import abbreviate_profile_dir # ----------------------------------------------------------------------------- @@ -339,13 +339,14 @@ def _classes_default(self): launcher_classes = [] for kind in ('controller', 'engine'): group_name = f'ipyparallel.{kind}_launchers' - group = entrypoints.get_group_named(group_name) - for key, value in group.items(): + group = entry_points(group=group_name) + for entrypoint in group: + key = entrypoint.name try: - cls = value.load() + cls = entrypoint.load() except Exception as e: self.log.error( - f"Failed to load entrypoint {group_name}: {key} = {value}\n{e}" + f"Failed to load entrypoint {group_name}: {key} = {entrypoint.value}\n{e}" ) else: launcher_classes.append(cls) diff --git a/ipyparallel/cluster/launcher.py b/ipyparallel/cluster/launcher.py index 407435d6..23fa5ebe 100644 --- a/ipyparallel/cluster/launcher.py +++ b/ipyparallel/cluster/launcher.py @@ -23,7 +23,6 @@ from tempfile import TemporaryDirectory from textwrap import indent -import entrypoints import psutil from IPython.utils.path import ensure_dir_exists, get_home_dir from IPython.utils.text import EvalFormatter @@ -42,6 +41,7 @@ ) from traitlets.config.configurable import LoggingConfigurable +from ..traitlets import entry_points from ..util import shlex_join from ._winhpcjob import IPControllerJob, IPControllerTask, IPEngineSetJob, IPEngineTask from .shellcmd import ShellCommandSend @@ -2505,16 +2505,16 @@ def find_launcher_class(name, kind): group_name = 'ipyparallel.controller_launchers' else: raise ValueError(f"kind must be 'engine' or 'controller', not {kind!r}") - group = entrypoints.get_group_named(group_name) + group = entry_points(group=group_name) # make it case-insensitive - registry = {key.lower(): value for key, value in group.items()} + registry = {entrypoint.name.lower(): entrypoint for entrypoint in group} return registry[name.lower()].load() @lru_cache def abbreviate_launcher_class(cls): """Abbreviate a launcher class back to its entrypoint name""" - cls_key = f"{cls.__module__}.{cls.__name__}" + cls_key = f"{cls.__module__}:{cls.__name__}" # allow entrypoint_name attribute in case the definition module # is not the same as the 'import' module if getattr(cls, 'entrypoint_name', None): @@ -2522,8 +2522,8 @@ def abbreviate_launcher_class(cls): for kind in ('controller', 'engine'): group_name = f'ipyparallel.{kind}_launchers' - group = entrypoints.get_group_named(group_name) - for key, value in group.items(): - if f"{value.module_name}.{value.object_name}" == cls_key: - return key.lower() + group = entry_points(group=group_name) + for entrypoint in group: + if entrypoint.value == cls_key: + return entrypoint.name.lower() return cls_key diff --git a/ipyparallel/tests/test_launcher.py b/ipyparallel/tests/test_launcher.py index f0ec2d6b..2c658dfc 100644 --- a/ipyparallel/tests/test_launcher.py +++ b/ipyparallel/tests/test_launcher.py @@ -10,11 +10,11 @@ import time from subprocess import Popen -import entrypoints import pytest from traitlets.config import Config from ipyparallel.cluster import launcher as launcher_mod +from ipyparallel.traitlets import entry_points # ------------------------------------------------------------------------------- # TestCase Mixins @@ -156,9 +156,10 @@ def _wait_one(timeout): @pytest.mark.parametrize("kind", ("controller", "engine")) def test_entrypoints(kind): group_name = f"ipyparallel.{kind}_launchers" - group = entrypoints.get_group_named(group_name) + group = entry_points(group=group_name) assert len(group) > 2 - for key, entrypoint in group.items(): + for entrypoint in group: + key = entrypoint.name # verify entrypoints are valid cls = entrypoint.load() diff --git a/ipyparallel/traitlets.py b/ipyparallel/traitlets.py index 69fa64e0..5bd007c0 100644 --- a/ipyparallel/traitlets.py +++ b/ipyparallel/traitlets.py @@ -1,6 +1,12 @@ """Custom ipyparallel trait types""" -import entrypoints +import sys + +if sys.version_info < (3, 10): + from importlib_metadata import entry_points +else: + from importlib.metadata import entry_points + from traitlets import List, TraitError, Type @@ -24,9 +30,7 @@ def help(self): chunks = [self._original_help] chunks.append("Currently installed: ") for key, entry_point in self.load_entry_points().items(): - chunks.append( - f" - {key}: {entry_point.module_name}.{entry_point.object_name}" - ) + chunks.append(f" - {key}: {entry_point.value}") return '\n'.join(chunks) @help.setter @@ -35,10 +39,10 @@ def help(self, value): def load_entry_points(self): """Load my entry point group""" - # load the group - group = entrypoints.get_group_named(self.entry_point_group) - # make it case-insensitive - return {key.lower(): value for key, value in group.items()} + return { + entry_point.name.lower(): entry_point + for entry_point in entry_points(group=self.entry_point_group) + } def validate(self, obj, value): if isinstance(value, str): diff --git a/pyproject.toml b/pyproject.toml index b9865729..c965bc69 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,7 @@ classifiers = [ urls = {Homepage = "https://ipython.org"} requires-python = ">=3.8" dependencies = [ - "entrypoints", + "importlib_metadata>=3.6; python_version < '3.10'", "decorator", "pyzmq>=25", "traitlets>=5",