diff --git a/newsfragments/4409.feature.rst b/newsfragments/4409.feature.rst new file mode 100644 index 0000000000..9dd157092c --- /dev/null +++ b/newsfragments/4409.feature.rst @@ -0,0 +1,3 @@ +Added return types to typed public functions -- by :user:`Avasam` + +Marked `pkg_resources` as ``py.typed`` -- by :user:`Avasam` diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py index c4ace5aa77..dbcce2671f 100644 --- a/pkg_resources/__init__.py +++ b/pkg_resources/__init__.py @@ -34,6 +34,7 @@ import types from typing import ( Any, + BinaryIO, Literal, Dict, Iterator, @@ -99,7 +100,7 @@ from pkg_resources.extern.platformdirs import user_cache_dir as _user_cache_dir if TYPE_CHECKING: - from _typeshed import BytesPath, StrPath, StrOrBytesPath + from _typeshed import StrPath, BytesPath, StrOrBytesPath from typing_extensions import Self warnings.warn( @@ -109,7 +110,6 @@ stacklevel=2, ) - _T = TypeVar("_T") _DistributionT = TypeVar("_DistributionT", bound="Distribution") # Type aliases @@ -153,7 +153,6 @@ class PEP440Warning(RuntimeWarning): parse_version = _packaging_version.Version - _state_vars: dict[str, str] = {} @@ -335,7 +334,9 @@ def req(self) -> Requirement: def report(self): return self._template.format(**locals()) - def with_context(self, required_by: set[Distribution | str]): + def with_context( + self, required_by: set[Distribution | str] + ) -> Self | ContextualVersionConflict: """ If required_by is non-empty, return a version of self that is a ContextualVersionConflict. @@ -404,7 +405,7 @@ class UnknownExtra(ResolutionError): def register_loader_type( loader_type: type[_ModuleLike], provider_factory: _ProviderFactoryType -): +) -> None: """Register `provider_factory` to make providers for `loader_type` `loader_type` is the type or class of a PEP 302 ``module.__loader__``, @@ -480,7 +481,7 @@ def get_build_platform(): get_platform = get_build_platform -def compatible_platforms(provided: str | None, required: str | None): +def compatible_platforms(provided: str | None, required: str | None) -> bool: """Can code for the `provided` platform run on the `required` platform? Returns true if either platform is ``None``, or the platforms are equal. @@ -561,7 +562,7 @@ def get_entry_map(dist: _EPDistType, group: str | None = None): return get_distribution(dist).get_entry_map(group) -def get_entry_info(dist: _EPDistType, group: str, name: str): +def get_entry_info(dist: _EPDistType, group: str, name: str) -> EntryPoint | None: """Return the EntryPoint object for `group`+`name`, or ``None``""" return get_distribution(dist).get_entry_info(group, name) @@ -682,7 +683,7 @@ def _build_from_requirements(cls, req_spec): sys.path[:] = ws.entries return ws - def add_entry(self, entry: str): + def add_entry(self, entry: str) -> None: """Add a path item to ``.entries``, finding any distributions on it ``find_distributions(entry, True)`` is used to find distributions @@ -725,7 +726,9 @@ def find(self, req: Requirement) -> Distribution | None: raise VersionConflict(dist, req) return dist - def iter_entry_points(self, group: str, name: str | None = None): + def iter_entry_points( + self, group: str, name: str | None = None + ) -> Iterator[EntryPoint]: """Yield entry point objects from `group` matching `name` If `name` is None, yields all entry points in `group` from all @@ -739,7 +742,7 @@ def iter_entry_points(self, group: str, name: str | None = None): if name is None or name == entry.name ) - def run_script(self, requires: str, script_name: str): + def run_script(self, requires: str, script_name: str) -> None: """Locate distribution for `requires` and run `script_name` script""" ns = sys._getframe(1).f_globals name = ns['__name__'] @@ -770,7 +773,7 @@ def add( entry: str | None = None, insert: bool = True, replace: bool = False, - ): + ) -> None: """Add `dist` to working set, associated with `entry` If `entry` is unspecified, it defaults to the ``.location`` of `dist`. @@ -1050,7 +1053,7 @@ def find_plugins( return sorted_distributions, error_info - def require(self, *requirements: _NestedStr): + def require(self, *requirements: _NestedStr) -> list[Distribution]: """Ensure that distributions matching `requirements` are activated `requirements` must be a string or a (possibly-nested) sequence @@ -1068,7 +1071,7 @@ def require(self, *requirements: _NestedStr): def subscribe( self, callback: Callable[[Distribution], object], existing: bool = True - ): + ) -> None: """Invoke `callback` for all distributions If `existing=True` (default), @@ -1154,7 +1157,7 @@ def __init__( self.python = python self.scan(search_path) - def can_add(self, dist: Distribution): + def can_add(self, dist: Distribution) -> bool: """Is distribution `dist` acceptable for this environment? The distribution must match the platform and python version @@ -1168,11 +1171,11 @@ def can_add(self, dist: Distribution): ) return py_compat and compatible_platforms(dist.platform, self.platform) - def remove(self, dist: Distribution): + def remove(self, dist: Distribution) -> None: """Remove `dist` from the environment""" self._distmap[dist.key].remove(dist) - def scan(self, search_path: Iterable[str] | None = None): + def scan(self, search_path: Iterable[str] | None = None) -> None: """Scan `search_path` for distributions usable in this environment Any distributions found are added to the environment. @@ -1198,7 +1201,7 @@ def __getitem__(self, project_name: str) -> list[Distribution]: distribution_key = project_name.lower() return self._distmap.get(distribution_key, []) - def add(self, dist: Distribution): + def add(self, dist: Distribution) -> None: """Add `dist` if we ``can_add()`` it and it has not already been added""" if self.can_add(dist) and dist.has_version(): dists = self._distmap.setdefault(dist.key, []) @@ -1349,23 +1352,29 @@ class ResourceManager: def __init__(self): self.cached_files = {} - def resource_exists(self, package_or_requirement: _PkgReqType, resource_name: str): + def resource_exists( + self, package_or_requirement: _PkgReqType, resource_name: str + ) -> bool: """Does the named resource exist?""" return get_provider(package_or_requirement).has_resource(resource_name) - def resource_isdir(self, package_or_requirement: _PkgReqType, resource_name: str): + def resource_isdir( + self, package_or_requirement: _PkgReqType, resource_name: str + ) -> bool: """Is the named resource an existing directory?""" return get_provider(package_or_requirement).resource_isdir(resource_name) def resource_filename( self, package_or_requirement: _PkgReqType, resource_name: str - ): + ) -> str: """Return a true filesystem path for specified resource""" return get_provider(package_or_requirement).get_resource_filename( self, resource_name ) - def resource_stream(self, package_or_requirement: _PkgReqType, resource_name: str): + def resource_stream( + self, package_or_requirement: _PkgReqType, resource_name: str + ) -> _ResourceStream: """Return a readable file-like object for specified resource""" return get_provider(package_or_requirement).get_resource_stream( self, resource_name @@ -1379,7 +1388,9 @@ def resource_string( self, resource_name ) - def resource_listdir(self, package_or_requirement: _PkgReqType, resource_name: str): + def resource_listdir( + self, package_or_requirement: _PkgReqType, resource_name: str + ) -> list[str]: """List the contents of the named resource directory""" return get_provider(package_or_requirement).resource_listdir(resource_name) @@ -1413,7 +1424,7 @@ def extraction_error(self) -> NoReturn: err.original_error = old_exc raise err - def get_cache_path(self, archive_name: str, names: Iterable[StrPath] = ()): + def get_cache_path(self, archive_name: str, names: Iterable[StrPath] = ()) -> str: """Return absolute location in cache for `archive_name` and `names` The parent directory of the resulting path will be created if it does @@ -1465,7 +1476,7 @@ def _warn_unsafe_extraction_path(path): ).format(**locals()) warnings.warn(msg, UserWarning) - def postprocess(self, tempname: StrOrBytesPath, filename: StrOrBytesPath): + def postprocess(self, tempname: StrOrBytesPath, filename: StrOrBytesPath) -> None: """Perform any platform-specific postprocessing of `tempname` This is where Mac header rewrites should be done; other platforms don't @@ -1485,7 +1496,7 @@ def postprocess(self, tempname: StrOrBytesPath, filename: StrOrBytesPath): mode = ((os.stat(tempname).st_mode) | 0o555) & 0o7777 os.chmod(tempname, mode) - def set_extraction_path(self, path: str): + def set_extraction_path(self, path: str) -> None: """Set the base path where resources will be extracted to, if needed. If you do not call this routine before any extractions take place, the @@ -1533,7 +1544,7 @@ def get_default_cache() -> str: return os.environ.get('PYTHON_EGG_CACHE') or _user_cache_dir(appname='Python-Eggs') -def safe_name(name: str): +def safe_name(name: str) -> str: """Convert an arbitrary string to a standard distribution name Any runs of non-alphanumeric/. characters are replaced with a single '-'. @@ -1541,7 +1552,7 @@ def safe_name(name: str): return re.sub('[^A-Za-z0-9.]+', '-', name) -def safe_version(version: str): +def safe_version(version: str) -> str: """ Convert an arbitrary string to a standard version string """ @@ -1585,7 +1596,7 @@ def _safe_segment(segment): return re.sub(r'\.[^A-Za-z0-9]+', '.', segment).strip(".-") -def safe_extra(extra: str): +def safe_extra(extra: str) -> str: """Convert an arbitrary string to a standard 'extra' name Any runs of non-alphanumeric characters are replaced with a single '_', @@ -1594,7 +1605,7 @@ def safe_extra(extra: str): return re.sub('[^A-Za-z0-9.-]+', '_', extra).lower() -def to_filename(name: str): +def to_filename(name: str) -> str: """Convert a project or version name to its filename-escaped form Any '-' characters are currently replaced with '_'. @@ -1602,7 +1613,7 @@ def to_filename(name: str): return name.replace('-', '_') -def invalid_marker(text: str): +def invalid_marker(text: str) -> SyntaxError | Literal[False]: """ Validate text as a PEP 508 environment marker; return an exception if invalid or False otherwise. @@ -1642,10 +1653,14 @@ def __init__(self, module: _ModuleLike): self.loader = getattr(module, '__loader__', None) self.module_path = os.path.dirname(getattr(module, '__file__', '')) - def get_resource_filename(self, manager: ResourceManager, resource_name: str): + def get_resource_filename( + self, manager: ResourceManager, resource_name: str + ) -> str: return self._fn(self.module_path, resource_name) - def get_resource_stream(self, manager: ResourceManager, resource_name: str): + def get_resource_stream( + self, manager: ResourceManager, resource_name: str + ) -> BinaryIO: return io.BytesIO(self.get_resource_string(manager, resource_name)) def get_resource_string( @@ -1653,7 +1668,7 @@ def get_resource_string( ) -> bytes: return self._get(self._fn(self.module_path, resource_name)) - def has_resource(self, resource_name: str): + def has_resource(self, resource_name: str) -> bool: return self._has(self._fn(self.module_path, resource_name)) def _get_metadata_path(self, name): @@ -1666,7 +1681,7 @@ def has_metadata(self, name: str) -> bool: path = self._get_metadata_path(name) return self._has(path) - def get_metadata(self, name: str): + def get_metadata(self, name: str) -> str: if not self.egg_info: return "" path = self._get_metadata_path(name) @@ -1682,13 +1697,13 @@ def get_metadata(self, name: str): def get_metadata_lines(self, name: str) -> Iterator[str]: return yield_lines(self.get_metadata(name)) - def resource_isdir(self, resource_name: str): + def resource_isdir(self, resource_name: str) -> bool: return self._isdir(self._fn(self.module_path, resource_name)) def metadata_isdir(self, name: str) -> bool: return bool(self.egg_info and self._isdir(self._fn(self.egg_info, name))) - def resource_listdir(self, resource_name: str): + def resource_listdir(self, resource_name: str) -> list[str]: return self._listdir(self._fn(self.module_path, resource_name)) def metadata_listdir(self, name: str) -> list[str]: @@ -1696,7 +1711,7 @@ def metadata_listdir(self, name: str) -> list[str]: return self._listdir(self._fn(self.egg_info, name)) return [] - def run_script(self, script_name: str, namespace: dict[str, Any]): + def run_script(self, script_name: str, namespace: dict[str, Any]) -> None: script = 'scripts/' + script_name if not self.has_metadata(script): raise ResolutionError( @@ -1880,7 +1895,9 @@ def _isdir(self, path) -> bool: def _listdir(self, path): return os.listdir(path) - def get_resource_stream(self, manager: object, resource_name: str): + def get_resource_stream( + self, manager: object, resource_name: str + ) -> io.BufferedReader: return open(self._fn(self.module_path, resource_name), 'rb') def _get(self, path) -> bytes: @@ -1929,7 +1946,7 @@ class ZipManifests(Dict[str, "MemoizedZipManifests.manifest_mod"]): # `path` could be `StrPath | IO[bytes]` but that violates the LSP for `MemoizedZipManifests.load` @classmethod - def build(cls, path: str): + def build(cls, path: str) -> dict[str, zipfile.ZipInfo]: """ Build a dictionary similar to the zipimport directory caches, except instead of tuples, store ZipInfo objects. @@ -2007,7 +2024,9 @@ def _parts(self, zip_path): def zipinfo(self): return self._zip_manifests.load(self.loader.archive) - def get_resource_filename(self, manager: ResourceManager, resource_name: str): + def get_resource_filename( + self, manager: ResourceManager, resource_name: str + ) -> str: if not self.egg_name: raise NotImplementedError( "resource_filename() only supported for .egg, not .zip" @@ -2167,7 +2186,7 @@ def _get_metadata_path(self, name): def has_metadata(self, name: str) -> bool: return name == 'PKG-INFO' and os.path.isfile(self.path) - def get_metadata(self, name: str): + def get_metadata(self, name: str) -> str: if name != 'PKG-INFO': raise KeyError("No metadata except PKG-INFO is available") @@ -2232,7 +2251,9 @@ def __init__(self, importer: zipimport.zipimporter): ) -def register_finder(importer_type: type[_T], distribution_finder: _DistFinderType[_T]): +def register_finder( + importer_type: type[_T], distribution_finder: _DistFinderType[_T] +) -> None: """Register `distribution_finder` to find distributions in sys.path items `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item @@ -2242,7 +2263,7 @@ def register_finder(importer_type: type[_T], distribution_finder: _DistFinderTyp _distribution_finders[importer_type] = distribution_finder -def find_distributions(path_item: str, only: bool = False): +def find_distributions(path_item: str, only: bool = False) -> Iterable[Distribution]: """Yield distributions accessible via `path_item`""" importer = get_importer(path_item) finder = _find_adapter(_distribution_finders, importer) @@ -2416,7 +2437,7 @@ def resolve_egg_link(path): def register_namespace_handler( importer_type: type[_T], namespace_handler: _NSHandlerType[_T] -): +) -> None: """Register `namespace_handler` to declare namespace packages `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item @@ -2505,7 +2526,7 @@ def position_in_sys_path(path): module.__path__ = new_path -def declare_namespace(packageName: str): +def declare_namespace(packageName: str) -> None: """Declare that package 'packageName' is a namespace package""" msg = ( @@ -2548,7 +2569,7 @@ def declare_namespace(packageName: str): _imp.release_lock() -def fixup_namespace_packages(path_item: str, parent: str | None = None): +def fixup_namespace_packages(path_item: str, parent: str | None = None) -> None: """Ensure that previously-declared namespace packages include path_item""" _imp.acquire_lock() try: @@ -2759,7 +2780,7 @@ def require( self, env: Environment | None = None, installer: _InstallerType | None = None, - ): + ) -> None: if not self.dist: error_cls = UnknownExtra if self.extras else AttributeError raise error_cls("Can't require() without a distribution", self) @@ -2783,7 +2804,7 @@ def require( ) @classmethod - def parse(cls, src: str, dist: Distribution | None = None): + def parse(cls, src: str, dist: Distribution | None = None) -> Self: """Parse a single entry point from string `src` Entry point syntax follows the form:: @@ -2817,7 +2838,7 @@ def parse_group( group: str, lines: _NestedStr, dist: Distribution | None = None, - ): + ) -> dict[str, Self]: """Parse an entry point group""" if not MODULE(group): raise ValueError("Invalid group name", group) @@ -2834,7 +2855,7 @@ def parse_map( cls, data: str | Iterable[str] | dict[str, str | Iterable[str]], dist: Distribution | None = None, - ): + ) -> dict[str, dict[str, Self]]: """Parse a map of entry point groups""" _data: Iterable[tuple[str | None, str | Iterable[str]]] if isinstance(data, dict): @@ -3039,7 +3060,9 @@ def _dep_map(self): return self.__dep_map @staticmethod - def _filter_extras(dm: dict[str | None, list[Requirement]]): + def _filter_extras( + dm: dict[str | None, list[Requirement]], + ) -> dict[str | None, list[Requirement]]: """ Given a mapping of extras to dependencies, strip off environment markers and filter out any dependencies @@ -3066,7 +3089,7 @@ def _build_dep_map(self): dm.setdefault(extra, []).extend(parse_requirements(reqs)) return dm - def requires(self, extras: Iterable[str] = ()): + def requires(self, extras: Iterable[str] = ()) -> list[Requirement]: """List of Requirements needed for this distro if `extras` are used""" dm = self._dep_map deps: list[Requirement] = [] @@ -3105,7 +3128,7 @@ def _get_version(self): lines = self._get_metadata(self.PKG_INFO) return _version_from_file(lines) - def activate(self, path: list[str] | None = None, replace: bool = False): + def activate(self, path: list[str] | None = None, replace: bool = False) -> None: """Ensure distribution is importable on `path` (default=sys.path)""" if path is None: path = sys.path @@ -3160,7 +3183,7 @@ def from_filename( filename: StrPath, metadata: _MetadataType = None, **kw: int, # We could set `precedence` explicitly, but keeping this as `**kw` for full backwards and subclassing compatibility - ): + ) -> Distribution: return cls.from_location( _normalize_cached(filename), os.path.basename(filename), metadata, **kw ) @@ -3195,7 +3218,7 @@ def get_entry_map(self, group: str | None = None): return self._ep_map.get(group, {}) return self._ep_map - def get_entry_info(self, group: str, name: str): + def get_entry_info(self, group: str, name: str) -> EntryPoint | None: """Return the EntryPoint object for `group`+`name`, or ``None``""" return self.get_entry_map(group).get(name) @@ -3205,7 +3228,7 @@ def insert_on( # noqa: C901 path: list[str], loc=None, replace: bool = False, - ): + ) -> None: """Ensure self.location is on path If replace=False (default): @@ -3310,7 +3333,7 @@ def has_version(self): return False return True - def clone(self, **kw: str | int | IResourceProvider | None): + def clone(self, **kw: str | int | IResourceProvider | None) -> Self: """Copy this distribution, substituting in any changed keyword args""" names = 'project_name version py_version platform location precedence' for attr in names.split(): @@ -3416,7 +3439,7 @@ def issue_warning(*args, **kw): warnings.warn(stacklevel=level + 1, *args, **kw) -def parse_requirements(strs: _NestedStr): +def parse_requirements(strs: _NestedStr) -> map[Requirement]: """ Yield ``Requirement`` objects for each specification in `strs`. @@ -3438,7 +3461,7 @@ def __init__(self, requirement_string: str): self.project_name, self.key = project_name, project_name.lower() self.specs = [(spec.operator, spec.version) for spec in self.specifier] # packaging.requirements.Requirement uses a set for its extras. We use a variable-length tuple - self.extras: tuple[str] = tuple(map(safe_extra, self.extras)) + self.extras: tuple[str, ...] = tuple(map(safe_extra, self.extras)) self.hashCmp = ( self.key, self.url, @@ -3473,7 +3496,7 @@ def __repr__(self): return "Requirement.parse(%r)" % str(self) @staticmethod - def parse(s: str | Iterable[str]): + def parse(s: str | Iterable[str]) -> Requirement: (req,) = parse_requirements(s) return req @@ -3499,7 +3522,7 @@ def _find_adapter(registry: Mapping[type, _AdapterT], ob: object) -> _AdapterT: raise TypeError(f"Could not find adapter for {registry} and {ob}") -def ensure_directory(path: StrOrBytesPath): +def ensure_directory(path: StrOrBytesPath) -> None: """Ensure that the parent directory of `path` exists""" dirname = os.path.dirname(path) os.makedirs(dirname, exist_ok=True) @@ -3575,6 +3598,7 @@ class PkgResourcesDeprecationWarning(Warning): _LOCALE_ENCODING = "locale" if sys.version_info >= (3, 10) else None +# This must go before calls to `_call_aside`. See https://github.com/pypa/setuptools/pull/4422 def _read_utf8_with_fallback(file: str, fallback_encoding=_LOCALE_ENCODING) -> str: """See setuptools.unicode_utils._read_utf8_with_fallback""" try: diff --git a/pkg_resources/extern/__init__.py b/pkg_resources/extern/__init__.py index 9b9ac10aa9..97b8a1f9a7 100644 --- a/pkg_resources/extern/__init__.py +++ b/pkg_resources/extern/__init__.py @@ -35,7 +35,7 @@ def _module_matches_namespace(self, fullname): root, base, target = fullname.partition(self.root_name + '.') return not root and any(map(target.startswith, self.vendored_names)) - def load_module(self, fullname: str): + def load_module(self, fullname: str) -> ModuleType: """ Iterate over the search path to locate and load fullname. """ @@ -57,10 +57,10 @@ def load_module(self, fullname: str): "distribution.".format(**locals()) ) - def create_module(self, spec: ModuleSpec): + def create_module(self, spec: ModuleSpec) -> ModuleType: return self.load_module(spec.name) - def exec_module(self, module: ModuleType): + def exec_module(self, module: ModuleType) -> None: pass def find_spec( @@ -68,7 +68,7 @@ def find_spec( fullname: str, path: Sequence[str] | None = None, target: ModuleType | None = None, - ): + ) -> ModuleSpec | None: """Return a module spec for vendored names.""" return ( # This should fix itself next mypy release https://github.com/python/typeshed/pull/11890 diff --git a/pkg_resources/py.typed b/pkg_resources/py.typed new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ruff.toml b/ruff.toml index 8828fe61a5..51aa1f8467 100644 --- a/ruff.toml +++ b/ruff.toml @@ -10,6 +10,7 @@ extend-select = [ "W", # local + "ANN2", # missing-return-type-* "FA", # flake8-future-annotations "F404", # late-future-import "PYI", # flake8-pyi @@ -22,6 +23,9 @@ ignore = [ "UP031", # temporarily disabled "UP032", # temporarily disabled "UP038", # Using `X | Y` in `isinstance` call is slower and more verbose https://github.com/astral-sh/ruff/issues/7871 + # Only enforcing return type annotations for public functions + "ANN202", # missing-return-type-private-function + "ANN204", # missing-return-type-special-method # https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules "W191", @@ -40,6 +44,14 @@ ignore = [ "ISC002", ] +[lint.per-file-ignores] +# Only enforcing return type annotations for public modules +"**/tests/**" = ["ANN2"] +"tools/**" = ["ANN2"] + +[lint.flake8-annotations] +ignore-fully-untyped = true + [format] # Enable preview to get hugged parenthesis unwrapping preview = true diff --git a/setuptools/command/bdist_wheel.py b/setuptools/command/bdist_wheel.py index a81187598a..97ce3f6a43 100644 --- a/setuptools/command/bdist_wheel.py +++ b/setuptools/command/bdist_wheel.py @@ -451,7 +451,7 @@ def run(self): def write_wheelfile( self, wheelfile_base: str, generator: str = f"setuptools ({__version__})" - ): + ) -> None: from email.message import Message msg = Message() @@ -525,7 +525,7 @@ def license_paths(self) -> Iterable[str]: return files - def egg2dist(self, egginfo_path: str, distinfo_path: str): + def egg2dist(self, egginfo_path: str, distinfo_path: str) -> None: """Convert an .egg-info directory into a .dist-info directory""" def adios(p: str) -> None: diff --git a/setuptools/command/install_lib.py b/setuptools/command/install_lib.py index 5e74be247e..598752143d 100644 --- a/setuptools/command/install_lib.py +++ b/setuptools/command/install_lib.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os import sys from itertools import product, starmap @@ -92,7 +93,7 @@ def copy_tree( preserve_times=True, preserve_symlinks=False, level=1, - ): + ) -> list[str]: assert preserve_mode and preserve_times and not preserve_symlinks exclude = self.get_exclusions() @@ -104,9 +105,9 @@ def copy_tree( from setuptools.archive_util import unpack_directory from distutils import log - outfiles = [] + outfiles: list[str] = [] - def pf(src, dst): + def pf(src: str, dst: str): if dst in exclude: log.warn("Skipping installation of %s (namespace package)", dst) return False diff --git a/setuptools/config/expand.py b/setuptools/config/expand.py index 6ea6cf6d0e..de8a1e6e2b 100644 --- a/setuptools/config/expand.py +++ b/setuptools/config/expand.py @@ -31,6 +31,7 @@ from itertools import chain from typing import ( TYPE_CHECKING, + Any, Callable, Iterable, Iterator, @@ -158,7 +159,7 @@ def read_attr( attr_desc: str, package_dir: Mapping[str, str] | None = None, root_dir: StrPath | None = None, -): +) -> Any: """Reads the value of an attribute from a module. This function will try to read the attributed statically first diff --git a/setuptools/config/pyprojecttoml.py b/setuptools/config/pyprojecttoml.py index c8dae5f751..3e8d47db8c 100644 --- a/setuptools/config/pyprojecttoml.py +++ b/setuptools/config/pyprojecttoml.py @@ -15,7 +15,7 @@ import os from contextlib import contextmanager from functools import partial -from typing import TYPE_CHECKING, Callable, Mapping +from typing import TYPE_CHECKING, Any, Callable, Mapping from .._path import StrPath from ..errors import FileError, InvalidConfigError @@ -76,7 +76,7 @@ def read_configuration( expand=True, ignore_option_errors=False, dist: Distribution | None = None, -): +) -> dict[str, Any]: """Read given configuration file and returns options from it as a dict. :param str|unicode filepath: Path to configuration file in the ``pyproject.toml`` diff --git a/setuptools/config/setupcfg.py b/setuptools/config/setupcfg.py index 0a7a42eb09..7e51450634 100644 --- a/setuptools/config/setupcfg.py +++ b/setuptools/config/setupcfg.py @@ -24,6 +24,7 @@ Dict, Generic, Iterable, + Iterator, Tuple, TypeVar, Union, @@ -260,7 +261,9 @@ def __init__( """ @classmethod - def _section_options(cls, options: AllCommandOptions): + def _section_options( + cls, options: AllCommandOptions + ) -> Iterator[tuple[str, SingleCommandOptions]]: for full_name, value in options.items(): pre, sep, name = full_name.partition(cls.section_prefix) if pre: diff --git a/setuptools/warnings.py b/setuptools/warnings.py index 5d9cca6c37..8c94bc96e6 100644 --- a/setuptools/warnings.py +++ b/setuptools/warnings.py @@ -32,7 +32,7 @@ def emit( see_url: str | None = None, stacklevel: int = 2, **kwargs, - ): + ) -> None: """Private: reserved for ``setuptools`` internal use only""" # Default values: summary_ = summary or getattr(cls, "_SUMMARY", None) or "" @@ -56,7 +56,7 @@ def _format( due_date: date | None = None, see_url: str | None = None, format_args: dict | None = None, - ): + ) -> str: """Private: reserved for ``setuptools`` internal use only""" today = date.today() summary = cleandoc(summary).format_map(format_args or {})