Skip to content

Commit 26163e5

Browse files
authored
Support optional-dependencies for third party packages (#15706)
1 parent 0634d4c commit 26163e5

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

CONTRIBUTING.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ supported:
169169
be listed here, for security reasons. See
170170
[this issue](https://github.com/typeshed-internal/stub_uploader/issues/90)
171171
for more information about what external dependencies are allowed.
172+
* `optional-dependencies` (optional): A list of other stub packages or packages
173+
with type information that are imported by some stubs in this package. This
174+
is often used for packages that provide optional features that require extra
175+
dependencies. The same limitations apply to this field as to `dependencies`.
172176
* `extra-description` (optional): Can be used to add a custom description to
173177
the package's long description. It should be a multi-line string in
174178
Markdown format.
@@ -204,7 +208,8 @@ This has the following keys:
204208
this field should be identical to `partial-stub`.
205209
* `stubtest-dependencies` (default: `[]`): A list of Python packages that need
206210
to be installed for stubtest to run successfully. These packages are installed
207-
in addition to the dependencies in the `dependencies` field.
211+
in addition to the dependencies in the `dependencies` and
212+
`optional-dependencies` fields.
208213
* `apt-dependencies` (default: `[]`): A list of Ubuntu APT packages
209214
that need to be installed for stubtest to run successfully.
210215
* `brew-dependencies` (default: `[]`): A list of MacOS Homebrew packages

lib/ts_utils/metadata.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ class StubMetadata:
173173
distribution: Annotated[str, "The name of the distribution on PyPI"]
174174
version_spec: Annotated[Specifier, "Upstream versions that the stubs are compatible with"]
175175
dependencies: Annotated[list[Requirement], "The parsed dependencies as listed in METADATA.toml"]
176+
optional_dependencies: Annotated[list[Requirement], "The parsed optional dependencies as listed in METADATA.toml"]
176177
extra_description: str | None
177178
stub_distribution: Annotated[str, "The name under which the distribution is uploaded to PyPI"]
178179
upstream_repository: Annotated[str, "The URL of the upstream repository"] | None
@@ -187,11 +188,20 @@ class StubMetadata:
187188
def is_obsolete(self) -> bool:
188189
return self.obsolete is not None
189190

191+
@property
192+
def all_dependencies(self) -> list[Requirement]:
193+
"""The dependencies and optional dependencies of this stubs package.
194+
195+
Does not include the stubtest dependencies.
196+
"""
197+
return self.dependencies + self.optional_dependencies
198+
190199

191200
_KNOWN_METADATA_FIELDS: Final = frozenset(
192201
{
193202
"version",
194203
"dependencies",
204+
"optional-dependencies",
195205
"extra-description",
196206
"stub-distribution",
197207
"upstream-repository",
@@ -262,6 +272,10 @@ def read_metadata(distribution: str) -> StubMetadata:
262272
assert isinstance(dependencies_s, list)
263273
dependencies = [parse_dependencies(distribution, dep) for dep in dependencies_s]
264274

275+
optional_dependencies_s = data.get("optional-dependencies", [])
276+
assert isinstance(optional_dependencies_s, list)
277+
optional_dependencies = [parse_dependencies(distribution, dep) for dep in optional_dependencies_s]
278+
265279
extra_description = data.get("extra-description")
266280
assert isinstance(extra_description, (str, type(None)))
267281

@@ -343,6 +357,7 @@ def read_metadata(distribution: str) -> StubMetadata:
343357
distribution=distribution,
344358
version_spec=version_spec,
345359
dependencies=dependencies,
360+
optional_dependencies=optional_dependencies,
346361
extra_description=extra_description,
347362
stub_distribution=stub_distribution,
348363
upstream_repository=upstream_repository,
@@ -412,7 +427,7 @@ def read_dependencies(distribution: str) -> PackageDependencies:
412427
pypi_name_to_typeshed_name_mapping = get_pypi_name_to_typeshed_name_mapping()
413428
typeshed: list[Requirement] = []
414429
external: list[Requirement] = []
415-
for dependency in read_metadata(distribution).dependencies:
430+
for dependency in read_metadata(distribution).all_dependencies:
416431
if dependency.name in pypi_name_to_typeshed_name_mapping:
417432
req = Requirement(str(dependency)) # copy the requirement
418433
req.name = pypi_name_to_typeshed_name_mapping[dependency.name]

0 commit comments

Comments
 (0)