diff --git a/changelog.d/20240202_153925_danyal.faheem_remove_pkg_resources.md b/changelog.d/20240202_153925_danyal.faheem_remove_pkg_resources.md new file mode 100644 index 0000000000..d7cd4d9b8a --- /dev/null +++ b/changelog.d/20240202_153925_danyal.faheem_remove_pkg_resources.md @@ -0,0 +1 @@ +[Depreciation] Replace pkg_resources with importlib_metadata and importlib_resources. (by @Danyal-Faheem) \ No newline at end of file diff --git a/requirements/base.in b/requirements/base.in index eb60ad6912..21e5098ba9 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -6,3 +6,5 @@ mypy pycryptodome>=3.17.0 pyyaml>=6.0 typing-extensions>=4.4.0 +importlib-metadata>=7.0.1 +importlib-resources>=6.1.1 diff --git a/requirements/base.txt b/requirements/base.txt index 53ea28465e..4008e2e7d5 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -20,6 +20,10 @@ google-auth==2.23.3 # via kubernetes idna==3.4 # via requests +importlib-metadata==7.0.1 + # via -r requirements/base.in +importlib-resources==6.1.1 + # via -r requirements/base.in jinja2==3.1.2 # via -r requirements/base.in kubernetes==28.1.0 @@ -72,3 +76,7 @@ urllib3==1.26.18 # requests websocket-client==1.6.4 # via kubernetes +zipp==3.17.0 + # via + # importlib-metadata + # importlib-resources diff --git a/requirements/dev.txt b/requirements/dev.txt index fd7ba3e747..06aefd22b0 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -5,7 +5,9 @@ # pip-compile requirements/dev.in # altgraph==0.17.4 - # via pyinstaller + # via + # macholib + # pyinstaller appdirs==1.4.4 # via -r requirements/base.txt astroid==3.0.1 @@ -25,8 +27,6 @@ certifi==2023.7.22 # -r requirements/base.txt # kubernetes # requests -cffi==1.16.0 - # via cryptography charset-normalizer==3.3.1 # via # -r requirements/base.txt @@ -42,8 +42,6 @@ click-log==0.4.0 # via scriv coverage==7.3.2 # via -r requirements/dev.in -cryptography==41.0.7 - # via secretstorage dill==0.3.7 # via pylint docutils==0.18.1 @@ -58,22 +56,21 @@ idna==3.4 # via # -r requirements/base.txt # requests -importlib-metadata==6.8.0 +importlib-metadata==7.0.1 # via + # -r requirements/base.txt # build # keyring # pyinstaller # twine importlib-resources==6.1.1 - # via keyring + # via + # -r requirements/base.txt + # keyring isort==5.12.0 # via pylint jaraco-classes==3.3.0 # via keyring -jeepney==0.8.0 - # via - # keyring - # secretstorage jinja2==3.1.2 # via # -r requirements/base.txt @@ -82,6 +79,8 @@ keyring==24.2.0 # via twine kubernetes==28.1.0 # via -r requirements/base.txt +macholib==1.16.3 + # via pyinstaller markdown-it-py==3.0.0 # via # rich @@ -134,8 +133,6 @@ pyasn1-modules==0.3.0 # via # -r requirements/base.txt # google-auth -pycparser==2.21 - # via cffi pycryptodome==3.19.0 # via -r requirements/base.txt pygments==2.16.1 @@ -184,8 +181,6 @@ rsa==4.9 # google-auth scriv==1.5.0 # via -r requirements/dev.in -secretstorage==3.3.3 - # via keyring six==1.16.0 # via # -r requirements/base.txt @@ -232,6 +227,7 @@ wheel==0.41.2 # via pip-tools zipp==3.17.0 # via + # -r requirements/base.txt # importlib-metadata # importlib-resources diff --git a/requirements/docs.txt b/requirements/docs.txt index c4f5c6e9c2..3312f225bd 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -42,8 +42,12 @@ idna==3.4 # requests imagesize==1.4.1 # via sphinx -importlib-metadata==6.8.0 - # via sphinx +importlib-metadata==7.0.1 + # via + # -r requirements/base.txt + # sphinx +importlib-resources==6.1.1 + # via -r requirements/base.txt jinja2==3.1.2 # via # -r requirements/base.txt @@ -84,7 +88,7 @@ python-dateutil==2.8.2 # via # -r requirements/base.txt # kubernetes -pytz==2023.3.post1 +pytz==2024.1 # via babel pyyaml==6.0.1 # via @@ -153,4 +157,7 @@ websocket-client==1.6.4 # -r requirements/base.txt # kubernetes zipp==3.17.0 - # via importlib-metadata + # via + # -r requirements/base.txt + # importlib-metadata + # importlib-resources diff --git a/tutor.spec b/tutor.spec index f68c7c08f6..1e6f591924 100644 --- a/tutor.spec +++ b/tutor.spec @@ -1,7 +1,7 @@ # -*- mode: python -*- import importlib import os -import pkg_resources +from importlib_metadata block_cipher = None @@ -10,10 +10,10 @@ hidden_imports = [] # Auto-discover plugins and include patches & templates folders for entrypoint_version in ["tutor.plugin.v0", "tutor.plugin.v1"]: - for entrypoint in pkg_resources.iter_entry_points(entrypoint_version): + for entrypoint in importlib_metadata.entry_points(group=entrypoint_version): plugin_name = entrypoint.name try: - plugin = entrypoint.load() + plugin = importlib.import_module(entrypoint.value) except Exception as e: print(f"ERROR Failed to load plugin {plugin_name}: {e}") continue diff --git a/tutor/env.py b/tutor/env.py index cccce94d0d..ef2590d6ce 100644 --- a/tutor/env.py +++ b/tutor/env.py @@ -7,13 +7,13 @@ from copy import deepcopy import jinja2 -import pkg_resources +import importlib_resources from tutor import exceptions, fmt, hooks, plugins, utils from tutor.__about__ import __app__, __version__ from tutor.types import Config, ConfigValue -TEMPLATES_ROOT = pkg_resources.resource_filename("tutor", "templates") +TEMPLATES_ROOT = str(importlib_resources.files("tutor") / "templates") VERSION_FILENAME = "version" BIN_FILE_EXTENSIONS = [".ico", ".jpg", ".patch", ".png", ".ttf", ".woff", ".woff2"] JinjaFilter = t.Callable[..., t.Any] diff --git a/tutor/plugins/v0.py b/tutor/plugins/v0.py index 16e67704e0..b1cf0f76d5 100644 --- a/tutor/plugins/v0.py +++ b/tutor/plugins/v0.py @@ -5,7 +5,7 @@ from glob import glob import click -import pkg_resources +import importlib_metadata from tutor import env, exceptions, fmt, hooks, serialize from tutor.__about__ import __app__ @@ -246,12 +246,12 @@ class EntrypointPlugin(BasePlugin): ENTRYPOINT = "tutor.plugin.v0" - def __init__(self, entrypoint: pkg_resources.EntryPoint) -> None: - self.loader: pkg_resources.EntryPoint + def __init__(self, entrypoint: importlib_metadata.EntryPoint) -> None: + self.loader: importlib_metadata.EntryPoint = entrypoint super().__init__(entrypoint.name, entrypoint) def _load_obj(self) -> None: - self.obj = self.loader.load() + self.obj = importlib.import_module(self.loader.value) def _version(self) -> t.Optional[str]: if not self.loader.dist: @@ -260,12 +260,11 @@ def _version(self) -> t.Optional[str]: @classmethod def discover_all(cls) -> None: - for entrypoint in pkg_resources.iter_entry_points(cls.ENTRYPOINT): + entrypoints = importlib_metadata.entry_points(group=cls.ENTRYPOINT) + for entrypoint in entrypoints: try: error: t.Optional[str] = None cls(entrypoint) - except pkg_resources.VersionConflict as e: - error = e.report() except Exception as e: # pylint: disable=broad-except error = str(e) if error: diff --git a/tutor/plugins/v1.py b/tutor/plugins/v1.py index cf24bf0f00..88982b6f67 100644 --- a/tutor/plugins/v1.py +++ b/tutor/plugins/v1.py @@ -2,7 +2,7 @@ import os from glob import glob -import pkg_resources +import importlib_metadata from tutor import hooks @@ -26,7 +26,7 @@ def _discover_entrypoint_plugins() -> None: """ with hooks.Contexts.PLUGINS.enter(): if "TUTOR_IGNORE_ENTRYPOINT_PLUGINS" not in os.environ: - for entrypoint in pkg_resources.iter_entry_points("tutor.plugin.v1"): + for entrypoint in importlib_metadata.entry_points(group="tutor.plugin.v1"): discover_package(entrypoint) @@ -56,7 +56,7 @@ def load(plugin_name: str) -> None: spec.loader.exec_module(module) -def discover_package(entrypoint: pkg_resources.EntryPoint) -> None: +def discover_package(entrypoint: importlib_metadata.EntryPoint) -> None: """ Install a plugin from a python package. """ @@ -68,10 +68,11 @@ def discover_package(entrypoint: pkg_resources.EntryPoint) -> None: # Add plugin information if entrypoint.dist is None: raise ValueError(f"Could not read plugin version: {name}") - hooks.Filters.PLUGINS_INFO.add_item((name, entrypoint.dist.version)) + dist_version = entrypoint.dist.version if entrypoint.dist else "Unknown" + hooks.Filters.PLUGINS_INFO.add_item((name, dist_version)) # Import module on enable @hooks.Actions.PLUGIN_LOADED.add() def load(plugin_name: str) -> None: if name == plugin_name: - entrypoint.load() + importlib.import_module(entrypoint.value)