[bumpversion]
-current_version = 67.5.1
+current_version = 67.6.0
commit = True
tag = True
+v67.6.0
+-------
+
+
+Changes
+^^^^^^^
+* #3804: Added caching for supported wheel tags.
+* #3846: Added pruning heuristics to ``PackageFinder`` based on ``exclude``.
+
+
v67.5.1
-------
.. attention::
Use of ``pkg_resources`` is deprecated in favor of
- `importlib.resources <https://docs.python.org/3/library/importlib.html#module-importlib.resources>`_,
- `importlib.metadata <https://docs.python.org/3/library/importlib.metadata.html>`_,
- and their backports (:pypi:`importlib_resources`,
- :pypi:`importlib_metadata`).
+ :mod:`importlib.resources`, :mod:`importlib.metadata`
+ and their backports (:pypi:`importlib_resources`, :pypi:`importlib_metadata`).
Users should refrain from new usage of ``pkg_resources`` and
should work to port to importlib-based solutions.
[metadata]
name = setuptools
-version = 67.5.1
+version = 67.6.0
author = Python Packaging Authority
author_email = distutils-sig@python.org
description = Easily download, build, install, upgrade, and uninstall Python packages
from pathlib import Path
from typing import (
TYPE_CHECKING,
- Callable,
Dict,
Iterable,
Iterator,
from distutils.util import convert_path
_Path = Union[str, os.PathLike]
-_Filter = Callable[[str], bool]
StrIter = Iterator[str]
chain_iter = itertools.chain.from_iterable
return os.path.basename(path).isidentifier()
+class _Filter:
+ """
+ Given a list of patterns, create a callable that will be true only if
+ the input matches at least one of the patterns.
+ """
+
+ def __init__(self, *patterns: str):
+ self._patterns = dict.fromkeys(patterns)
+
+ def __call__(self, item: str) -> bool:
+ return any(fnmatchcase(item, pat) for pat in self._patterns)
+
+ def __contains__(self, item: str) -> bool:
+ return item in self._patterns
+
+
class _Finder:
"""Base class that exposes functionality for module/package finders"""
return list(
cls._find_iter(
convert_path(str(where)),
- cls._build_filter(*cls.ALWAYS_EXCLUDE, *exclude),
- cls._build_filter(*include),
+ _Filter(*cls.ALWAYS_EXCLUDE, *exclude),
+ _Filter(*include),
)
)
def _find_iter(cls, where: _Path, exclude: _Filter, include: _Filter) -> StrIter:
raise NotImplementedError
- @staticmethod
- def _build_filter(*patterns: str) -> _Filter:
- """
- Given a list of patterns, return a callable that will be true only if
- the input matches at least one of the patterns.
- """
- return lambda name: any(fnmatchcase(name, pat) for pat in patterns)
-
class PackageFinder(_Finder):
"""
if include(package) and not exclude(package):
yield package
+ # Early pruning if there is nothing else to be scanned
+ if f"{package}*" in exclude or f"{package}.*" in exclude:
+ continue
+
# Keep searching subdirectories, as there may be more packages
# down there, even if the parent was excluded.
dirs.append(dir)
def test_wheel_is_compatible(monkeypatch):
def sys_tags():
- for t in parse_tag('cp36-cp36m-manylinux1_x86_64'):
- yield t
- monkeypatch.setattr('setuptools.wheel.sys_tags', sys_tags)
+ return {
+ (t.interpreter, t.abi, t.platform)
+ for t in parse_tag('cp36-cp36m-manylinux1_x86_64')
+ }
+ monkeypatch.setattr('setuptools.wheel._get_supported_tags', sys_tags)
assert Wheel(
'onnxruntime-0.1.2-cp36-cp36m-manylinux1_x86_64.whl').is_compatible()
import email
import itertools
+import functools
import os
import posixpath
import re
"__import__('pkg_resources').declare_namespace(__name__)\n"
+@functools.lru_cache(maxsize=None)
+def _get_supported_tags():
+ # We calculate the supported tags only once, otherwise calling
+ # this method on thousands of wheels takes seconds instead of
+ # milliseconds.
+ return {(t.interpreter, t.abi, t.platform) for t in sys_tags()}
+
+
def unpack(src_dir, dst_dir):
'''Move everything under `src_dir` to `dst_dir`, and delete the former.'''
for dirpath, dirnames, filenames in os.walk(src_dir):
)
def is_compatible(self):
- '''Is the wheel is compatible with the current platform?'''
- supported_tags = set(
- (t.interpreter, t.abi, t.platform) for t in sys_tags())
- return next((True for t in self.tags() if t in supported_tags), False)
+ '''Is the wheel compatible with the current platform?'''
+ return next((True for t in self.tags() if t in _get_supported_tags()), False)
def egg_name(self):
return _egg_basename(