diff options
author | Anderson Bravalheri <andersonbravalheri@gmail.com> | 2023-03-07 09:46:16 +0000 |
---|---|---|
committer | Anderson Bravalheri <andersonbravalheri@gmail.com> | 2023-03-07 10:13:20 +0000 |
commit | d30dcf5296ecf93046abd46d4039f24704679734 (patch) | |
tree | 982001e5fbc4a4e344a95c6b14a3202a11002a10 | |
parent | f51eccd769cab0297c64e4d007bef42544326431 (diff) | |
download | python-setuptools-git-d30dcf5296ecf93046abd46d4039f24704679734.tar.gz |
Add pruning heuristics to PackageFinder based on exclude
-rw-r--r-- | setuptools/discovery.py | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/setuptools/discovery.py b/setuptools/discovery.py index f053dba8..3110b727 100644 --- a/setuptools/discovery.py +++ b/setuptools/discovery.py @@ -44,7 +44,6 @@ from glob import glob from pathlib import Path from typing import ( TYPE_CHECKING, - Callable, Dict, Iterable, Iterator, @@ -61,7 +60,6 @@ from distutils import log from distutils.util import convert_path _Path = Union[str, os.PathLike] -_Filter = Callable[[str], bool] StrIter = Iterator[str] chain_iter = itertools.chain.from_iterable @@ -75,6 +73,22 @@ def _valid_name(path: _Path) -> bool: 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""" @@ -111,8 +125,8 @@ class _Finder: 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), ) ) @@ -120,14 +134,6 @@ class _Finder: 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): """ @@ -160,6 +166,10 @@ 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) |