Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't ignore missing stubs in setuptools #10058

Merged
55 changes: 26 additions & 29 deletions stubs/setuptools/@tests/stubtest_allowlist.txt
Original file line number Diff line number Diff line change
@@ -1,27 +1,16 @@
pkg_resources.Distribution.__cmp__
pkg_resources.Distribution.activate
pkg_resources.Distribution.get_entry_map
pkg_resources.EggMetadata.__init__
pkg_resources.Environment.best_match
pkg_resources.Environment.obtain
pkg_resources.FileMetadata.__init__
# These are used like protocols, but forgot to specify "self" as the first method param
pkg_resources.IResourceProvider.get_resource_filename
pkg_resources.IResourceProvider.get_resource_stream
pkg_resources.IResourceProvider.get_resource_string
pkg_resources.IResourceProvider.has_resource
pkg_resources.IResourceProvider.resource_isdir
pkg_resources.IResourceProvider.resource_listdir
pkg_resources.IMetadataProvider.get_metadata
pkg_resources.IMetadataProvider.get_metadata_lines
pkg_resources.IMetadataProvider.has_metadata
pkg_resources.IMetadataProvider.metadata_isdir
pkg_resources.IMetadataProvider.metadata_listdir
pkg_resources.IMetadataProvider.run_script
pkg_resources.IResourceManager
pkg_resources.Requirement.__init__
pkg_resources.WorkingSet.find_plugins
pkg_resources.WorkingSet.resolve
pkg_resources.WorkingSet.subscribe
pkg_resources.declare_namespace
pkg_resources.fixup_namespace_packages
pkg_resources.get_entry_map
pkg_resources.get_provider
pkg_resources.split_sections
pkg_resources.to_filename

# Is always set in __init__
pkg_resources.PathMetadata.egg_info
Expand Down Expand Up @@ -53,16 +42,24 @@ setuptools._distutils.dist.Distribution.get_requires
setuptools._distutils.dist.Distribution.get_provides
setuptools._distutils.dist.Distribution.get_obsoletes

# Uncomment once ignore_missing_stub is turned off
# # Not supported by typeshed
# setuptools.py34compat
# Not supported by typeshed
setuptools.py34compat
setuptools.command.py36compat

# # Private modules
# setuptools.config._validate_pyproject.*
# setuptools.build_meta._BuildMetaBackend.*
# Private modules
setuptools.config._validate_pyproject.*
setuptools.command.build_py.build_py.existing_egg_info_dir

# # Vendored and modified version of stdlib's distutils. Basically implementation details
# setuptools._distutils.*
# # Other vendored code
# setuptools._vendor.*
# pkg_resources._vendor.*
# Loop variable leak
setuptools.sandbox.AbstractSandbox.name

# Vendored and modified version of stdlib's distutils. Basically implementation details
setuptools._distutils.*
# Other vendored code
setuptools._vendor.*
pkg_resources._vendor.*
# Deprecated in favor of importlib.resources, importlib.metadata and their backports
# So like distutils, we only add what we need to reference.
pkg_resources.AvailableDistributions
pkg_resources.ResourceManager
pkg_resources.extern
2 changes: 2 additions & 0 deletions stubs/setuptools/@tests/stubtest_allowlist_darwin.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Mock
setuptools.msvc.winreg
2 changes: 2 additions & 0 deletions stubs/setuptools/@tests/stubtest_allowlist_linux.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Mock
setuptools.msvc.winreg
54 changes: 54 additions & 0 deletions stubs/setuptools/@tests/test_cases/check_protocols.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from __future__ import annotations

from typing import Any

from pkg_resources import (
DefaultProvider,
EggMetadata,
EggProvider,
EmptyProvider,
FileMetadata,
IMetadataProvider,
IResourceProvider,
NullProvider,
PathMetadata,
ZipProvider,
)
from setuptools.command.editable_wheel import EditableStrategy, _LinkTree, _StaticPth, _TopLevelFinder
from setuptools.config.expand import EnsurePackagesDiscovered
from setuptools.config.pyprojecttoml import _EnsurePackagesDiscovered

# We don't care about the __init__ methods, only about if an instance respects the Protocol
_: Any = object()

# Test IMetadataProvider Protocol implementers
metadata_provider: IMetadataProvider
metadata_provider = NullProvider(_)
metadata_provider = EggProvider(_)
metadata_provider = EmptyProvider()
metadata_provider = DefaultProvider(_)
metadata_provider = ZipProvider(_)
metadata_provider = FileMetadata(_)
metadata_provider = PathMetadata(_, _)
metadata_provider = EggMetadata(_)

# Test IResourceProvider Protocol implementers
resource_provider: IResourceProvider
resource_provider = NullProvider(_)
resource_provider = EggProvider(_)
resource_provider = EmptyProvider()
resource_provider = DefaultProvider(_)
resource_provider = ZipProvider(_)
resource_provider = FileMetadata(_)
resource_provider = PathMetadata(_, _)
resource_provider = EggMetadata(_)


# Test EditableStrategy Protocol implementers
editable_strategy: EditableStrategy
editable_strategy = _StaticPth(_, _, _)
editable_strategy = _LinkTree(_, _, _, _)
editable_strategy = _TopLevelFinder(_, _)
# Not EditableStrategy due to incompatible __call__ method
editable_strategy = EnsurePackagesDiscovered(_) # type: ignore
editable_strategy = _EnsurePackagesDiscovered(_, _, _) # type: ignore
3 changes: 2 additions & 1 deletion stubs/setuptools/METADATA.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ version = "67.7.*"
partial_stub = true

[tool.stubtest]
ignore_missing_stub = true
# darwin is equivalent to linux for OS-specific methods
platforms = ["linux", "win32"]
97 changes: 67 additions & 30 deletions stubs/setuptools/pkg_resources/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ from abc import ABCMeta
from collections.abc import Callable, Generator, Iterable, Sequence
from io import BytesIO
from re import Pattern
from typing import IO, Any, ClassVar, TypeVar, overload
from typing import IO, Any, ClassVar, Protocol, TypeVar, overload, type_check_only
from typing_extensions import Literal, Self, TypeAlias

_Version: TypeAlias = Incomplete # from packaging.version
Expand All @@ -21,8 +21,8 @@ _PkgReqType: TypeAlias = str | Requirement
_DistFinderType: TypeAlias = Callable[[_Importer, str, bool], Generator[Distribution, None, None]]
_NSHandlerType: TypeAlias = Callable[[_Importer, str, str, types.ModuleType], str]

def declare_namespace(name: str) -> None: ...
def fixup_namespace_packages(path_item: str) -> None: ...
def declare_namespace(packageName: str) -> None: ...
def fixup_namespace_packages(path_item: str, parent=None) -> None: ...

class WorkingSet:
entries: list[str]
Expand All @@ -35,18 +35,24 @@ class WorkingSet:
def __iter__(self) -> Generator[Distribution, None, None]: ...
def find(self, req: Requirement) -> Distribution | None: ...
def resolve(
self, requirements: Iterable[Requirement], env: Environment | None = None, installer: _InstallerType | None = None
self,
requirements: Iterable[Requirement],
env: Environment | None = None,
installer: _InstallerType | None = None,
replace_conflicting: bool = False,
extras=None,
) -> list[Distribution]: ...
def add(self, dist: Distribution, entry: str | None = None, insert: bool = True, replace: bool = False) -> None: ...
def subscribe(self, callback: Callable[[Distribution], object]) -> None: ...
def subscribe(self, callback: Callable[[Distribution], object], existing: bool = True) -> None: ...
def find_plugins(
self, plugin_env: Environment, full_env: Environment | None = None, fallback: bool = True
self, plugin_env: Environment, full_env: Environment | None = None, installer=None, fallback: bool = True
) -> tuple[list[Distribution], dict[Distribution, Exception]]: ...

working_set: WorkingSet

require = working_set.require
run_script = working_set.run_script
run_main = run_script
iter_entry_points = working_set.iter_entry_points
add_activation_listener = working_set.subscribe

Expand All @@ -62,13 +68,15 @@ class Environment:
def __add__(self, other: Distribution | Environment) -> Environment: ...
def __iadd__(self, other: Distribution | Environment) -> Self: ...
@overload
def best_match(self, req: Requirement, working_set: WorkingSet, *, replace_conflicting: bool = False) -> Distribution: ...
def best_match(
self, req: Requirement, working_set: WorkingSet, installer: None = None, replace_conflicting: bool = False
) -> Distribution: ...
@overload
def best_match(
self, req: Requirement, working_set: WorkingSet, installer: Callable[[Requirement], _T], replace_conflicting: bool = False
) -> _T: ...
@overload
def obtain(self, requirement: Requirement) -> None: ...
def obtain(self, requirement: Requirement, installer: None = None) -> None: ...
@overload
def obtain(self, requirement: Requirement, installer: Callable[[Requirement], _T]) -> _T: ...
def scan(self, search_path: Sequence[str] | None = None) -> None: ...
Expand All @@ -85,6 +93,7 @@ class Requirement:
# TODO: change this to packaging.markers.Marker | None once we can import
# packaging.markers
marker: Incomplete | None
def __init__(self, requirement_string: str) -> None: ...
@staticmethod
def parse(s: str | Iterable[str]) -> Requirement: ...
def __contains__(self, item: Distribution | str | tuple[str, ...]) -> bool: ...
Expand All @@ -93,11 +102,12 @@ class Requirement:
def load_entry_point(dist: _EPDistType, group: str, name: str) -> Any: ...
def get_entry_info(dist: _EPDistType, group: str, name: str) -> EntryPoint | None: ...
@overload
def get_entry_map(dist: _EPDistType) -> dict[str, dict[str, EntryPoint]]: ...
def get_entry_map(dist: _EPDistType, group: None = None) -> dict[str, dict[str, EntryPoint]]: ...
@overload
def get_entry_map(dist: _EPDistType, group: str) -> dict[str, EntryPoint]: ...

class EntryPoint:
pattern: ClassVar[Pattern[str]]
name: str
module_name: str
attrs: tuple[str, ...]
Expand Down Expand Up @@ -143,8 +153,8 @@ def resource_listdir(package_or_requirement: _PkgReqType, resource_name: str) ->
def resource_filename(package_or_requirement: _PkgReqType, resource_name: str) -> str: ...
def set_extraction_path(path: str) -> None: ...
def cleanup_resources(force: bool = False) -> list[str]: ...

class IResourceManager:
@type_check_only
class _IResourceManager(Protocol):
def resource_exists(self, package_or_requirement: _PkgReqType, resource_name: str) -> bool: ...
def resource_stream(self, package_or_requirement: _PkgReqType, resource_name: str) -> IO[bytes]: ...
def resource_string(self, package_or_requirement: _PkgReqType, resource_name: str) -> bytes: ...
Expand All @@ -158,11 +168,11 @@ class IResourceManager:
def postprocess(self, tempname: str, filename: str) -> None: ...

@overload
def get_provider(package_or_requirement: str) -> IResourceProvider: ...
def get_provider(moduleOrReq: str) -> IResourceProvider: ...
@overload
def get_provider(package_or_requirement: Requirement) -> Distribution: ...
def get_provider(moduleOrReq: Requirement) -> Distribution: ...

class IMetadataProvider:
class IMetadataProvider(Protocol):
def has_metadata(self, name: str) -> bool | None: ...
def metadata_isdir(self, name: str) -> bool: ...
def metadata_listdir(self, name: str) -> list[str]: ...
Expand Down Expand Up @@ -196,7 +206,7 @@ class ContextualVersionConflict(VersionConflict):
class UnknownExtra(ResolutionError): ...

class ExtractionError(Exception):
manager: IResourceManager
manager: _IResourceManager
cache_path: str
original_error: Exception

Expand All @@ -206,7 +216,16 @@ def register_finder(importer_type: type, distribution_finder: _DistFinderType) -
def register_loader_type(loader_type: type, provider_factory: Callable[[types.ModuleType], IResourceProvider]) -> None: ...
def register_namespace_handler(importer_type: type, namespace_handler: _NSHandlerType) -> None: ...

class IResourceProvider(IMetadataProvider): ...
class IResourceProvider(IMetadataProvider, Protocol):
def get_resource_filename(self, manager: _IResourceManager, resource_name): ...
def get_resource_stream(self, manager: _IResourceManager, resource_name): ...
def get_resource_string(self, manager: _IResourceManager, resource_name): ...
def has_resource(self, resource_name): ...
def resource_isdir(self, resource_name): ...
def resource_listdir(self, resource_name): ...

def invalid_marker(text) -> SyntaxError | Literal[False]: ...
def evaluate_marker(text, extra: Incomplete | None = None): ...

class NullProvider:
egg_name: str | None
Expand All @@ -215,9 +234,9 @@ class NullProvider:
module_path: str | None

def __init__(self, module) -> None: ...
def get_resource_filename(self, manager, resource_name) -> str: ...
def get_resource_stream(self, manager, resource_name) -> BytesIO: ...
def get_resource_string(self, manager, resource_name): ...
def get_resource_filename(self, manager: _IResourceManager, resource_name) -> str: ...
def get_resource_stream(self, manager: _IResourceManager, resource_name) -> BytesIO: ...
def get_resource_string(self, manager: _IResourceManager, resource_name): ...
def has_resource(self, resource_name) -> bool: ...
def has_metadata(self, name: str) -> bool | None: ...
def get_metadata(self, name: str) -> str: ...
Expand All @@ -228,11 +247,21 @@ class NullProvider:
def metadata_listdir(self, name: str) -> list[str]: ...
def run_script(self, script_name: str, namespace: dict[str, Any]) -> None: ...

class Distribution(NullProvider, IResourceProvider, IMetadataProvider):
# Doesn't actually extend NullProvider
class Distribution(NullProvider):
PKG_INFO: ClassVar[str]
location: str
project_name: str
@property
def hashcmp(self) -> tuple[Incomplete, int, str, Incomplete | None, str, str]: ...
def __hash__(self) -> int: ...
def __lt__(self, other: Distribution) -> bool: ...
def __le__(self, other: Distribution) -> bool: ...
def __gt__(self, other: Distribution) -> bool: ...
def __ge__(self, other: Distribution) -> bool: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
@property
def key(self) -> str: ...
@property
def extras(self) -> list[str]: ...
Expand All @@ -259,15 +288,17 @@ class Distribution(NullProvider, IResourceProvider, IMetadataProvider):
) -> Distribution: ...
@classmethod
def from_filename(cls, filename: str, metadata: _MetadataType = None, **kw: str | None | int) -> Distribution: ...
def activate(self, path: list[str] | None = None) -> None: ...
def activate(self, path: list[str] | None = None, replace: bool = False) -> None: ...
def as_requirement(self) -> Requirement: ...
def requires(self, extras: tuple[str, ...] = ()) -> list[Requirement]: ...
def check_version_conflict(self) -> None: ...
def has_version(self) -> bool: ...
def clone(self, **kw: str | int | None) -> Requirement: ...
def egg_name(self) -> str: ... # type: ignore[override] # supertype's egg_name is a variable, not a method
def __cmp__(self, other: Any) -> bool: ...
def get_entry_info(self, group: str, name: str) -> EntryPoint | None: ...
def insert_on(self, path, loc: Incomplete | None = None, replace: bool = False) -> None: ...
@overload
def get_entry_map(self) -> dict[str, dict[str, EntryPoint]]: ...
def get_entry_map(self, group: None = None) -> dict[str, dict[str, EntryPoint]]: ...
@overload
def get_entry_map(self, group: str) -> dict[str, EntryPoint]: ...
def load_entry_point(self, group: str, name: str) -> Any: ...
Expand All @@ -281,37 +312,41 @@ class EggProvider(NullProvider):

class DefaultProvider(EggProvider): ...

class PathMetadata(DefaultProvider, IResourceProvider):
class PathMetadata(DefaultProvider):
egg_info: str
module_path: str
def __init__(self, path: str, egg_info: str) -> None: ...

class ZipProvider(EggProvider):
eagers: list[str] | None
zip_pre: str
@property
def zipinfo(self): ...

class EggMetadata(ZipProvider, IResourceProvider):
class EggMetadata(ZipProvider):
JelleZijlstra marked this conversation as resolved.
Show resolved Hide resolved
loader: zipimport.zipimporter
module_path: str
def __init__(self, zipimporter: zipimport.zipimporter) -> None: ...
def __init__(self, importer: zipimport.zipimporter) -> None: ...

class EmptyProvider(NullProvider):
module_path: None
def __init__(self) -> None: ...

empty_provider: EmptyProvider

class FileMetadata(EmptyProvider, IResourceProvider):
def __init__(self, path_to_pkg_info: str) -> None: ...
class FileMetadata(EmptyProvider):
def __init__(self, path: str) -> None: ...

class PEP440Warning(RuntimeWarning): ...

parse_version = _Version

def yield_lines(iterable: _NestedStr) -> Generator[str, None, None]: ...
def split_sections(strs: _NestedStr) -> Generator[tuple[str | None, list[str]], None, None]: ...
def split_sections(s: _NestedStr) -> Generator[tuple[str | None, list[str]], None, None]: ...
def safe_name(name: str) -> str: ...
def safe_version(version: str) -> str: ...
def safe_extra(extra: str) -> str: ...
def to_filename(name_or_version: str) -> str: ...
def to_filename(name: str) -> str: ...
def get_build_platform() -> str: ...
def get_platform() -> str: ...
def get_supported_platform() -> str: ...
Expand All @@ -320,3 +355,5 @@ def get_default_cache() -> str: ...
def get_importer(path_item: str) -> _Importer: ...
def ensure_directory(path: str) -> None: ...
def normalize_path(filename: str) -> str: ...

class PkgResourcesDeprecationWarning(Warning): ...
Loading