diff options
| author | Daniel Schadt <kingdread@gmx.de> | 2025-12-27 14:52:41 +0100 |
|---|---|---|
| committer | Daniel Schadt <kingdread@gmx.de> | 2025-12-27 14:52:41 +0100 |
| commit | 7f5a499ccc63a10302fcc8021dcfae90ee97866f (patch) | |
| tree | eb94bd3b5e67e4c91614853c9de20b76dc1d7dc2 /src | |
| parent | 33a7811d24ea88c558ec03acf5e016e7c84ddefa (diff) | |
| download | pyramid-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.py | 124 | ||||
| -rw-r--r-- | src/pyramid/config/views.py | 1 | ||||
| -rw-r--r-- | src/pyramid/path.py | 36 | ||||
| -rw-r--r-- | src/pyramid/static.py | 13 |
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 |
