diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f8263498c4da..f8f4809825b3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -169,6 +169,10 @@ supported: be listed here, for security reasons. See [this issue](https://github.com/typeshed-internal/stub_uploader/issues/90) for more information about what external dependencies are allowed. +* `optional-dependencies` (optional): A list of other stub packages or packages + with type information that are imported by some stubs in this package. This + is often used for packages that provide optional features that require extra + dependencies. The same limitations apply to this field as to `dependencies`. * `extra-description` (optional): Can be used to add a custom description to the package's long description. It should be a multi-line string in Markdown format. @@ -204,7 +208,8 @@ This has the following keys: this field should be identical to `partial-stub`. * `stubtest-dependencies` (default: `[]`): A list of Python packages that need to be installed for stubtest to run successfully. These packages are installed - in addition to the dependencies in the `dependencies` field. + in addition to the dependencies in the `dependencies` and + `optional-dependencies` fields. * `apt-dependencies` (default: `[]`): A list of Ubuntu APT packages that need to be installed for stubtest to run successfully. * `brew-dependencies` (default: `[]`): A list of MacOS Homebrew packages diff --git a/lib/ts_utils/metadata.py b/lib/ts_utils/metadata.py index 4243129b64a7..0135077164ce 100644 --- a/lib/ts_utils/metadata.py +++ b/lib/ts_utils/metadata.py @@ -175,6 +175,7 @@ class StubMetadata: distribution: Annotated[str, "The name of the distribution on PyPI"] version_spec: Annotated[Specifier, "Upstream versions that the stubs are compatible with"] dependencies: Annotated[list[Requirement], "The parsed dependencies as listed in METADATA.toml"] + optional_dependencies: Annotated[list[Requirement], "The parsed optional dependencies as listed in METADATA.toml"] extra_description: str | None stub_distribution: Annotated[str, "The name under which the distribution is uploaded to PyPI"] upstream_repository: Annotated[str, "The URL of the upstream repository"] | None @@ -189,11 +190,20 @@ class StubMetadata: def is_obsolete(self) -> bool: return self.obsolete is not None + @property + def all_dependencies(self) -> list[Requirement]: + """The dependencies and optional dependencies of this stubs package. + + Does not include the stubtest dependencies. + """ + return self.dependencies + self.optional_dependencies + _KNOWN_METADATA_FIELDS: Final = frozenset( { "version", "dependencies", + "optional-dependencies", "extra-description", "stub-distribution", "upstream-repository", @@ -264,6 +274,10 @@ def read_metadata(distribution: str) -> StubMetadata: assert isinstance(dependencies_s, list) dependencies = [parse_dependencies(distribution, dep) for dep in dependencies_s] + optional_dependencies_s = data.get("optional-dependencies", []) + assert isinstance(optional_dependencies_s, list) + optional_dependencies = [parse_dependencies(distribution, dep) for dep in optional_dependencies_s] + extra_description = data.get("extra-description") assert isinstance(extra_description, (str, type(None))) @@ -342,6 +356,7 @@ def read_metadata(distribution: str) -> StubMetadata: distribution=distribution, version_spec=version_spec, dependencies=dependencies, + optional_dependencies=optional_dependencies, extra_description=extra_description, stub_distribution=stub_distribution, upstream_repository=upstream_repository, @@ -411,7 +426,7 @@ def read_dependencies(distribution: str) -> PackageDependencies: pypi_name_to_typeshed_name_mapping = get_pypi_name_to_typeshed_name_mapping() typeshed: list[Requirement] = [] external: list[Requirement] = [] - for dependency in read_metadata(distribution).dependencies: + for dependency in read_metadata(distribution).all_dependencies: if dependency.name in pypi_name_to_typeshed_name_mapping: req = Requirement(str(dependency)) # copy the requirement req.name = pypi_name_to_typeshed_name_mapping[dependency.name]