From 2c2d34d60d430a16c7f5a876328f2a9fbabad585 Mon Sep 17 00:00:00 2001 From: Johan Wassberg Date: Tue, 20 Oct 2026 10:42:16 +0200 Subject: [PATCH 1/2] No longer (directly) depend on setuptools pkg_resources has been depracated and removed for some time now. --- pyproject.toml | 1 - src/pyff/test/__init__.py | 6 ++---- src/pyff/utils.py | 23 +++++++++++++---------- uv.lock | 2 -- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a5a2565a..3b874345 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,6 @@ dependencies = [ "requests>=2.32.3", "requests-cache==1.2.1", "requests-file==2.1.0", - "setuptools>=78.1.1,<81", "str2bool>=1.1", "whoosh>=2.7.4", "wsgi-intercept>=1.13.1", diff --git a/src/pyff/test/__init__.py b/src/pyff/test/__init__.py index fb966601..c9e13c86 100644 --- a/src/pyff/test/__init__.py +++ b/src/pyff/test/__init__.py @@ -7,8 +7,6 @@ import tempfile from unittest import TestCase -from pyff import __version__ as pyffversion - # range of ports where available ports can be found PORT_RANGE = [33000, 60000] @@ -52,13 +50,13 @@ def run_cmdline(script, *args): import sys import coverage import os -from pkg_resources import load_entry_point +from importlib.metadata import distribution if __name__ == '__main__': cov = coverage.coverage(cover_pylib=False, source=['pyff'], omit=['test']) cov.start() rv = 0 try: - rv = load_entry_point('pyFF=={pyffversion}', 'console_scripts', '{script}')() + rv = distribution('pyFF').entry_points.select(group='console_scripts', name='{script}')['{script}'].load()() except Exception as ex: raise ex finally: diff --git a/src/pyff/utils.py b/src/pyff/utils.py index 36358aaf..34752375 100644 --- a/src/pyff/utils.py +++ b/src/pyff/utils.py @@ -22,12 +22,12 @@ from datetime import datetime, timedelta, timezone from email.utils import parsedate from itertools import chain +from pathlib import Path from threading import local from time import gmtime, strftime from typing import Any, BinaryIO, Callable, Optional, Union from urllib.parse import urlparse -import pkg_resources import pybergshamra import requests from apscheduler.executors.pool import ThreadPoolExecutor @@ -66,6 +66,9 @@ log = get_log(__name__) +# Directory holding the files distributed with the package (XSLT, XSD, ...). +PACKAGE_DIR = Path(__file__).resolve().parent + thread_data = local() @@ -119,10 +122,10 @@ def resource_string(name: str, pfx: Optional[str] = None) -> Optional[Union[str, elif pfx and os.path.exists(os.path.join(pfx, name)): with open(os.path.join(pfx, name)) as fd: data = fd.read() - elif pkg_resources.resource_exists(__name__, name): - data = pkg_resources.resource_string(__name__, name) - elif pfx and pkg_resources.resource_exists(__name__, f"{pfx}/{name}"): - data = pkg_resources.resource_string(__name__, f"{pfx}/{name}") + elif (PACKAGE_DIR / name).exists(): + data = (PACKAGE_DIR / name).read_bytes() + elif pfx and (PACKAGE_DIR / pfx / name).exists(): + data = (PACKAGE_DIR / pfx / name).read_bytes() return data @@ -148,10 +151,10 @@ def resource_filename(name, pfx=None): return name elif pfx and os.path.exists(os.path.join(pfx, name)): return os.path.join(pfx, name) - elif pkg_resources.resource_exists(__name__, name): - return pkg_resources.resource_filename(__name__, name) - elif pfx and pkg_resources.resource_exists(__name__, f"{pfx}/{name}"): - return pkg_resources.resource_filename(__name__, f"{pfx}/{name}") + elif (PACKAGE_DIR / name).exists(): + return str(PACKAGE_DIR / name) + elif pfx and (PACKAGE_DIR / pfx / name).exists(): + return str(PACKAGE_DIR / pfx / name) return None @@ -234,7 +237,7 @@ def schema(): # "geo:lat, lon", "mailto: user@host"). Strict/spec XSD rejects those # per RFC 3987, which would wrongly drop large numbers of otherwise # valid entities; lenient mode accepts them exactly as lxml did. - schema_path = pkg_resources.resource_filename(__name__, "schema/schema.xsd") + schema_path = str(PACKAGE_DIR / "schema" / "schema.xsd") thread_data.schema = etree.XMLSchema(file=schema_path, lenient=True) except etree.XMLSchemaParseError as ex: traceback.print_exc() diff --git a/uv.lock b/uv.lock index c363d6e1..2b6591fb 100644 --- a/uv.lock +++ b/uv.lock @@ -961,7 +961,6 @@ dependencies = [ { name = "requests" }, { name = "requests-cache" }, { name = "requests-file" }, - { name = "setuptools" }, { name = "str2bool" }, { name = "whoosh" }, { name = "wsgi-intercept" }, @@ -1007,7 +1006,6 @@ requires-dist = [ { name = "requests", specifier = ">=2.32.3" }, { name = "requests-cache", specifier = "==1.2.1" }, { name = "requests-file", specifier = "==2.1.0" }, - { name = "setuptools", specifier = ">=78.1.1,<81" }, { name = "str2bool", specifier = ">=1.1" }, { name = "whoosh", specifier = ">=2.7.4" }, { name = "wsgi-intercept", specifier = ">=1.13.1" }, From 4c286e51fffb67f7c301890621018e7b171ad59c Mon Sep 17 00:00:00 2001 From: Johan Wassberg Date: Tue, 20 Oct 2026 11:08:37 +0200 Subject: [PATCH 2/2] No longer constrained by python3.9 Bump pyconfig which used to relay on pkg_resources Closes #339 --- pyproject.toml | 2 +- uv.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3b874345..ea35794e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ dependencies = [ "cryptography>=42", "gunicorn>=25.2.0", "mako>=1.3.10", - "pyconfig>=3.2.3,<3.3.0", + "pyconfig>=3.3.0", "pydantic>=2.8", "pyramid>=2.0.2", "pytz>=2025.2", diff --git a/uv.lock b/uv.lock index 2b6591fb..0a3f677a 100644 --- a/uv.lock +++ b/uv.lock @@ -806,15 +806,15 @@ wheels = [ [[package]] name = "pyconfig" -version = "3.2.3" +version = "3.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytool" }, - { name = "six" }, + { name = "simplejson" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/50/70/8735b55844a482e65daf82827275d3d5867b77fb6413c99061c984dba226/pyconfig-3.2.3.tar.gz", hash = "sha256:89c7580a3111f0b3ab9fe0cac630b9297a7aeedbb4c7eb55e90320bfb90ac649", size = 23915, upload-time = "2017-08-18T06:26:03.067Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/ed/8dad88ac88034a5428a7432325720637a9e7b8423fb7f9b4447d35ce413b/pyconfig-3.3.0.tar.gz", hash = "sha256:197e5eb6e3bdb6dbd9fd944df7e0330af6b166cb558bd9ca41930f4495110e7e", size = 26392, upload-time = "2025-06-20T06:51:36.33Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/94/3a/e64558856c92d4689e20c3e914069f089801eb45b0862e04fbf3f300275f/pyconfig-3.2.3-py3-none-any.whl", hash = "sha256:797e250a2042927069a19085641bbbe7d975dff2b28dffd68116a0d0239d9c75", size = 17209, upload-time = "2018-08-02T09:40:53.674Z" }, + { url = "https://files.pythonhosted.org/packages/ef/28/3b93b9d53b5900de055063e7958f70424a9e2fcd21cae3fdd85c36d1f6e6/pyconfig-3.3.0-py3-none-any.whl", hash = "sha256:f056047f832defb4a828004298ec67b5d66303537c194c14a600f791047559e1", size = 18058, upload-time = "2025-06-20T06:51:34.974Z" }, ] [[package]] @@ -995,7 +995,7 @@ requires-dist = [ { name = "gunicorn", specifier = ">=25.2.0" }, { name = "mako", specifier = ">=1.3.10" }, { name = "pybergshamra", specifier = ">=0.11.0" }, - { name = "pyconfig", specifier = ">=3.2.3,<3.3.0" }, + { name = "pyconfig", specifier = ">=3.3.0" }, { name = "pydantic", specifier = ">=2.8" }, { name = "pyramid", specifier = ">=2.0.2" }, { name = "pytz", specifier = ">=2025.2" },