summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2025-12-27 14:52:41 +0100
committerDaniel Schadt <kingdread@gmx.de>2025-12-27 14:52:41 +0100
commit7f5a499ccc63a10302fcc8021dcfae90ee97866f (patch)
treeeb94bd3b5e67e4c91614853c9de20b76dc1d7dc2 /src
parent33a7811d24ea88c558ec03acf5e016e7c84ddefa (diff)
downloadpyramid-main.tar.gz
pyramid-main.tar.bz2
pyramid-main.zip
remove pkg_resources callsmain
This is mostly based on work by luhn. From a quick test with my pyramid project, it seems to work fine, but I haven't tested more complex setups. At least my template renderings and static files didn't break, and I checked a single asset override which also worked.
Diffstat (limited to 'src')
-rw-r--r--src/pyramid/config/assets.py124
-rw-r--r--src/pyramid/config/views.py1
-rw-r--r--src/pyramid/path.py36
-rw-r--r--src/pyramid/static.py13
4 files changed, 65 insertions, 109 deletions
diff --git a/src/pyramid/config/assets.py b/src/pyramid/config/assets.py
index 3c6a8d360..66a532853 100644
--- a/src/pyramid/config/assets.py
+++ b/src/pyramid/config/assets.py
@@ -1,93 +1,17 @@
+import importlib.resources
import os
-import pkg_resources
import sys
from zope.interface import implementer
from pyramid.config.actions import action_method
from pyramid.exceptions import ConfigurationError
from pyramid.interfaces import PHASE1_CONFIG, IPackageOverrides
-from pyramid.threadlocal import get_current_registry
-
-
-class OverrideProvider(pkg_resources.DefaultProvider):
- def __init__(self, module):
- pkg_resources.DefaultProvider.__init__(self, module)
- self.module_name = module.__name__
-
- def _get_overrides(self):
- reg = get_current_registry()
- overrides = reg.queryUtility(IPackageOverrides, self.module_name)
- return overrides
-
- def get_resource_filename(self, manager, resource_name):
- """Return a true filesystem path for resource_name,
- co-ordinating the extraction with manager, if the resource
- must be unpacked to the filesystem.
- """
- overrides = self._get_overrides()
- if overrides is not None:
- filename = overrides.get_filename(resource_name)
- if filename is not None:
- return filename
- return pkg_resources.DefaultProvider.get_resource_filename(
- self, manager, resource_name
- )
-
- def get_resource_stream(self, manager, resource_name):
- """Return a readable file-like object for resource_name."""
- overrides = self._get_overrides()
- if overrides is not None:
- stream = overrides.get_stream(resource_name)
- if stream is not None:
- return stream
- return pkg_resources.DefaultProvider.get_resource_stream(
- self, manager, resource_name
- )
-
- def get_resource_string(self, manager, resource_name):
- """Return a string containing the contents of resource_name."""
- overrides = self._get_overrides()
- if overrides is not None:
- string = overrides.get_string(resource_name)
- if string is not None:
- return string
- return pkg_resources.DefaultProvider.get_resource_string(
- self, manager, resource_name
- )
-
- def has_resource(self, resource_name):
- overrides = self._get_overrides()
- if overrides is not None:
- result = overrides.has_resource(resource_name)
- if result is not None:
- return result
- return pkg_resources.DefaultProvider.has_resource(self, resource_name)
-
- def resource_isdir(self, resource_name):
- overrides = self._get_overrides()
- if overrides is not None:
- result = overrides.isdir(resource_name)
- if result is not None:
- return result
- return pkg_resources.DefaultProvider.resource_isdir(
- self, resource_name
- )
-
- def resource_listdir(self, resource_name):
- overrides = self._get_overrides()
- if overrides is not None:
- result = overrides.listdir(resource_name)
- if result is not None:
- return result
- return pkg_resources.DefaultProvider.resource_listdir(
- self, resource_name
- )
@implementer(IPackageOverrides)
class PackageOverrides:
# pkg_resources arg in kw args below for testing
- def __init__(self, package, pkg_resources=pkg_resources):
+ def __init__(self, package):
loader = self._real_loader = getattr(package, '__loader__', None)
if isinstance(loader, self.__class__):
self._real_loader = None
@@ -102,9 +26,6 @@ class PackageOverrides:
# A __loader__ attribute is basically metadata, and setuptools
# uses it as such.
package.__loader__ = self
- # we call register_loader_type for every instantiation of this
- # class; that's OK, it's idempotent to do it more than once.
- pkg_resources.register_loader_type(self.__class__, OverrideProvider)
self.overrides = []
self.overridden_package_name = package.__name__
@@ -226,43 +147,60 @@ class PackageAssetSource:
self.pkg_name = package
self.prefix = prefix
+ def _exists(self, path):
+ res = importlib.resources.files(self.pkg_name).joinpath(path)
+ return res.is_dir() or res.is_file()
+
def get_path(self, resource_name):
return f'{self.prefix}{resource_name}'
def get_spec(self, resource_name):
path = self.get_path(resource_name)
- if pkg_resources.resource_exists(self.pkg_name, path):
+ if self._exists(path):
return f'{self.pkg_name}:{path}'
def get_filename(self, resource_name):
path = self.get_path(resource_name)
- if pkg_resources.resource_exists(self.pkg_name, path):
- return pkg_resources.resource_filename(self.pkg_name, path)
+ # resource_filename doesn't work for .zip files, so it's fine to not
+ # mimic it
+ if self._exists(path):
+ with importlib.resources.path(self.pkg_name, path) as fname:
+ return str(fname)
def get_stream(self, resource_name):
path = self.get_path(resource_name)
- if pkg_resources.resource_exists(self.pkg_name, path):
- return pkg_resources.resource_stream(self.pkg_name, path)
+ if self._exists(path):
+ return importlib.resources.open_binary(self.pkg_name, path)
def get_string(self, resource_name):
path = self.get_path(resource_name)
- if pkg_resources.resource_exists(self.pkg_name, path):
- return pkg_resources.resource_string(self.pkg_name, path)
+ if self._exists(path):
+ return importlib.resources.read_binary(self.pkg_name, path)
def exists(self, resource_name):
path = self.get_path(resource_name)
- if pkg_resources.resource_exists(self.pkg_name, path):
+ # exists() returns True or None, not True or False
+ if self._exists(path):
return True
def isdir(self, resource_name):
path = self.get_path(resource_name)
- if pkg_resources.resource_exists(self.pkg_name, path):
- return pkg_resources.resource_isdir(self.pkg_name, path)
+ res = importlib.resources.files(self.pkg_name).joinpath(path)
+ if res.is_dir():
+ return True
+ elif res.is_file():
+ return False
+ return None
def listdir(self, resource_name):
path = self.get_path(resource_name)
- if pkg_resources.resource_exists(self.pkg_name, path):
- return pkg_resources.resource_listdir(self.pkg_name, path)
+ if self._exists(path):
+ return [
+ resource.name
+ for resource in importlib.resources.files(self.pkg_name)
+ .joinpath(path)
+ .iterdir()
+ ]
class FSAssetSource:
diff --git a/src/pyramid/config/views.py b/src/pyramid/config/views.py
index 302704c3e..7769ceef9 100644
--- a/src/pyramid/config/views.py
+++ b/src/pyramid/config/views.py
@@ -2,7 +2,6 @@ import functools
import inspect
import operator
import os
-import posixpath
from urllib.parse import quote, urljoin, urlparse, urlunparse
import warnings
from webob.acceptparse import Accept
diff --git a/src/pyramid/path.py b/src/pyramid/path.py
index 3bc87b5f3..b3568748d 100644
--- a/src/pyramid/path.py
+++ b/src/pyramid/path.py
@@ -4,8 +4,8 @@ import functools
from importlib.machinery import SOURCE_SUFFIXES
import importlib.resources
import os
-import pkg_resources
import sys
+import zipfile
from zope.interface import implementer
from pyramid.interfaces import IAssetDescriptor
@@ -118,8 +118,6 @@ CALLER_PACKAGE = _CALLER_PACKAGE()
@implementer(IAssetDescriptor)
class PkgResourcesAssetDescriptor:
- pkg_resources = pkg_resources
-
def __init__(self, pkg_name, path, overrides=None):
self.pkg_name = pkg_name
self.path = path
@@ -134,10 +132,14 @@ class PkgResourcesAssetDescriptor:
else:
filename = None
if filename is None:
- filename = self.pkg_resources.resource_filename(
- self.pkg_name,
- self.path,
- )
+ # pkg_resources.resource_filename is not supported for .zip files,
+ # so we don't need to provide a workaround here.
+ files = importlib.resources.files(self.pkg_name)
+ if isinstance(files, zipfile.Path):
+ raise NotImplementedError("abspath() not supported for .zip")
+ res = files.joinpath(self.path)
+ with importlib.resources.as_file(res) as path:
+ filename = str(path)
return os.path.abspath(filename)
def stream(self):
@@ -145,28 +147,40 @@ class PkgResourcesAssetDescriptor:
stream = self.overrides.get_stream(self.path)
if stream is not None:
return stream
- return self.pkg_resources.resource_stream(self.pkg_name, self.path)
+ return importlib.resources.open_binary(self.pkg_name, self.path)
def isdir(self):
if self.overrides is not None:
result = self.overrides.isdir(self.path)
if result is not None:
return result
- return self.pkg_resources.resource_isdir(self.pkg_name, self.path)
+ return (
+ importlib.resources.files(self.pkg_name)
+ .joinpath(self.path)
+ .is_dir()
+ )
def listdir(self):
if self.overrides is not None:
result = self.overrides.listdir(self.path)
if result is not None:
return result
- return self.pkg_resources.resource_listdir(self.pkg_name, self.path)
+ return [
+ resource.name
+ for resource in importlib.resources.files(self.pkg_name)
+ .joinpath(self.path)
+ .iterdir()
+ ]
def exists(self):
if self.overrides is not None:
result = self.overrides.exists(self.path)
if result is not None:
return result
- return self.pkg_resources.resource_exists(self.pkg_name, self.path)
+ # Cannot use importlib.resources.is_resource because it does not
+ # consider directories to be resources.
+ resource = importlib.resources.files(self.pkg_name).joinpath(self.path)
+ return resource.is_file() or resource.is_dir()
@implementer(IAssetDescriptor)
diff --git a/src/pyramid/static.py b/src/pyramid/static.py
index 4091bbfbc..e19fcf654 100644
--- a/src/pyramid/static.py
+++ b/src/pyramid/static.py
@@ -1,9 +1,9 @@
from functools import lru_cache
+import importlib.resources
import json
import mimetypes
import os
from os.path import exists, getmtime, getsize, isdir, join, normcase, normpath
-from pkg_resources import resource_exists, resource_filename, resource_isdir
import warnings
from pyramid.asset import abspath_from_asset_spec, resolve_asset_spec
@@ -153,7 +153,10 @@ class static_view:
# normalize asset spec or fs path into resource_path
if self.package_name: # package resource
resource_path = '{}/{}'.format(self.docroot.rstrip('/'), path)
- if resource_isdir(self.package_name, resource_path):
+ res = importlib.resources.files(self.package_name).joinpath(
+ resource_path
+ )
+ if res.is_dir():
if not request.path_url.endswith('/'):
raise self.add_slash_redirect(request)
resource_path = '{}/{}'.format(
@@ -178,8 +181,10 @@ class static_view:
"""
if self.package_name:
- if resource_exists(self.package_name, name):
- return resource_filename(self.package_name, name)
+ res = importlib.resources.files(self.package_name).joinpath(name)
+ if res.is_file():
+ with importlib.resources.as_file(res) as fname:
+ return str(fname)
elif exists(name):
return name