From 4118e34761c6f4136b13e12cc91a34481342922b Mon Sep 17 00:00:00 2001 From: Pulkit Goyal Date: Tue, 28 Oct 2025 20:01:06 +0100 Subject: [PATCH 1/5] Replace pkg_resources usage in mongo observer with importlib.resources fallback --- sacred/observers/mongo.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/sacred/observers/mongo.py b/sacred/observers/mongo.py index 7c6a90e9..204a4f1b 100644 --- a/sacred/observers/mongo.py +++ b/sacred/observers/mongo.py @@ -15,14 +15,28 @@ from sacred.observers.queue import QueueObserver from sacred.serializer import flatten from sacred.utils import ObserverError, PathType -import pkg_resources -DEFAULT_MONGO_PRIORITY = 30 +# Prefer stdlib importlib.resources for accessing package data files. +# Fall back to pkg_resources only if importlib.resources isn't available +try: + # Python 3.9+: importlib.resources.files is available + import importlib.resources as importlib_resources # type: ignore +except Exception: + import importlib_resources # type: ignore # backport if installed, otherwise fallback later # This ensures consistent mimetype detection across platforms. -mimetype_detector = mimetypes.MimeTypes( - filenames=[pkg_resources.resource_filename("sacred", "data/mime.types")] -) +# Use importlib.resources to locate the bundled data/mime.types file; if that fails +# fall back to pkg_resources.resource_filename for older environments. +try: + # The files() API returns a Traversable; convert to str to get a filesystem path. + mime_types_path = str(importlib_resources.files("sacred").joinpath("data", "mime.types")) +except Exception: + # final fallback + import pkg_resources + + mime_types_path = pkg_resources.resource_filename("sacred", "data/mime.types") + +mimetype_detector = mimetypes.MimeTypes(filenames=[mime_types_path]) def force_valid_bson_key(key): @@ -662,4 +676,4 @@ def __init__( ), interval=interval, retry_interval=retry_interval, - ) + ) \ No newline at end of file From 78b49fd022f912ae3df56a1e1d48fcbd5b590891 Mon Sep 17 00:00:00 2001 From: Pulkit Goyal Date: Fri, 31 Oct 2025 13:19:46 +0100 Subject: [PATCH 2/5] Readd missing DEFAULT_MONGO_PRIORITY --- sacred/observers/mongo.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sacred/observers/mongo.py b/sacred/observers/mongo.py index 204a4f1b..315fd4d6 100644 --- a/sacred/observers/mongo.py +++ b/sacred/observers/mongo.py @@ -24,6 +24,8 @@ except Exception: import importlib_resources # type: ignore # backport if installed, otherwise fallback later +DEFAULT_MONGO_PRIORITY = 30 + # This ensures consistent mimetype detection across platforms. # Use importlib.resources to locate the bundled data/mime.types file; if that fails # fall back to pkg_resources.resource_filename for older environments. From cba1921d68c99a48f9a3929e796537a0985a9d79 Mon Sep 17 00:00:00 2001 From: Pulkit Goyal Date: Mon, 3 Nov 2025 11:29:36 +0100 Subject: [PATCH 3/5] Use importlib without fallbacks --- sacred/dependencies.py | 13 ++++++++----- sacred/observers/mongo.py | 25 ++++--------------------- 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/sacred/dependencies.py b/sacred/dependencies.py index 8470c048..34e31269 100644 --- a/sacred/dependencies.py +++ b/sacred/dependencies.py @@ -8,7 +8,7 @@ import sys from pathlib import Path -import pkg_resources +from importlib.metadata import distribution, distributions import sacred.optional as opt from sacred import SETTINGS @@ -226,7 +226,7 @@ "pickletools", "pip", "pipes", - "pkg_resources", + "importlib", "pkgutil", "platform", "plistlib", @@ -498,8 +498,11 @@ def __init__(self, name, version): def fill_missing_version(self): if self.version is not None: return - dist = pkg_resources.working_set.by_key.get(self.name) - self.version = dist.version if dist else None + try: + dist = distribution(self.name) + self.version = dist.version + except Exception: + self.version = None def to_json(self): return "{}=={}".format(self.name, self.version or "") @@ -701,7 +704,7 @@ def get_dependencies_from_imported_modules(globs, base_path): def get_dependencies_from_pkg(globs, base_path): dependencies = set() - for dist in pkg_resources.working_set: + for dist in distributions(): if dist.version == "0.0.0": continue # ugly hack to deal with pkg-resource version bug dependencies.add(PackageDependency(dist.project_name, dist.version)) diff --git a/sacred/observers/mongo.py b/sacred/observers/mongo.py index 315fd4d6..018276dd 100644 --- a/sacred/observers/mongo.py +++ b/sacred/observers/mongo.py @@ -16,30 +16,13 @@ from sacred.serializer import flatten from sacred.utils import ObserverError, PathType -# Prefer stdlib importlib.resources for accessing package data files. -# Fall back to pkg_resources only if importlib.resources isn't available -try: - # Python 3.9+: importlib.resources.files is available - import importlib.resources as importlib_resources # type: ignore -except Exception: - import importlib_resources # type: ignore # backport if installed, otherwise fallback later +import importlib.resources as importlib_resources # type: ignore DEFAULT_MONGO_PRIORITY = 30 -# This ensures consistent mimetype detection across platforms. -# Use importlib.resources to locate the bundled data/mime.types file; if that fails -# fall back to pkg_resources.resource_filename for older environments. -try: - # The files() API returns a Traversable; convert to str to get a filesystem path. - mime_types_path = str(importlib_resources.files("sacred").joinpath("data", "mime.types")) -except Exception: - # final fallback - import pkg_resources - - mime_types_path = pkg_resources.resource_filename("sacred", "data/mime.types") - -mimetype_detector = mimetypes.MimeTypes(filenames=[mime_types_path]) - +mimetype_detector = mimetypes.MimeTypes( + filenames=[importlib_resources.files("sacred").joinpath("data", "mime.types")] +) def force_valid_bson_key(key): key = str(key) From 0b0ee6226cf850c4e79d226ee15b30650d58512b Mon Sep 17 00:00:00 2001 From: Pulkit Goyal Date: Mon, 3 Nov 2025 12:54:58 +0100 Subject: [PATCH 4/5] Rewrite pkg_resources based code --- sacred/dependencies.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/sacred/dependencies.py b/sacred/dependencies.py index 34e31269..42eaa284 100644 --- a/sacred/dependencies.py +++ b/sacred/dependencies.py @@ -527,11 +527,17 @@ def create(cls, mod): if not cls.modname_to_dist: # some packagenames don't match the module names (e.g. PyYAML) # so we set up a dict to map from module name to package name - for dist in pkg_resources.working_set: + for dist in distributions(): try: - toplevel_names = dist._get_metadata("top_level.txt") - for tln in toplevel_names: - cls.modname_to_dist[tln] = dist.project_name, dist.version + # Use read_text to get top_level.txt content + if dist.files: + for file in dist.files: + if str(file).endswith("top_level.txt"): + top_level_txt = file.read_text() + for tln in top_level_txt.strip().split("\n"): + if tln: + cls.modname_to_dist[tln] = (dist.name, dist.version) + break except Exception: pass From 531daf34d4aa0c1b40aa9805c3a5c0a4c1f8ab3d Mon Sep 17 00:00:00 2001 From: Pulkit Goyal Date: Mon, 3 Nov 2025 13:27:30 +0100 Subject: [PATCH 5/5] Deprecate Python 3.8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit + add Python 3.12–13 --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 405e68df..5582084f 100755 --- a/setup.py +++ b/setup.py @@ -8,10 +8,11 @@ Intended Audience :: Science/Research Natural Language :: English Operating System :: OS Independent -Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 +Programming Language :: Python :: 3.12 +Programming Language :: Python :: 3.13 Topic :: Utilities Topic :: Scientific/Engineering Topic :: Scientific/Engineering :: Artificial Intelligence