Skip to content

Commit 5632132

Browse files
authored
Use dashes instead of underscores for METADATA.toml field names (#15614)
1 parent 7eb0ddd commit 5632132

File tree

204 files changed

+365
-362
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

204 files changed

+365
-362
lines changed

CONTRIBUTING.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -169,27 +169,27 @@ 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-
* `extra_description` (optional): Can be used to add a custom description to
172+
* `extra-description` (optional): Can be used to add a custom description to
173173
the package's long description. It should be a multi-line string in
174174
Markdown format.
175-
* `stub_distribution` (optional): Distribution name to be uploaded to PyPI.
175+
* `stub-distribution` (optional): Distribution name to be uploaded to PyPI.
176176
This defaults to `types-<distribution>` and should only be set in special
177177
cases.
178-
* `upstream_repository` (recommended): The URL of the upstream repository.
179-
* `obsolete_since` (optional): This field is part of our process for
178+
* `upstream-repository` (recommended): The URL of the upstream repository.
179+
* `obsolete-since` (optional): This field is part of our process for
180180
[removing obsolete third-party libraries](#third-party-library-removal-policy).
181181
It contains the first version of the corresponding library that ships
182182
its own `py.typed` file.
183-
* `no_longer_updated` (optional): This field is set to `true` before removing
183+
* `no-longer-updated` (optional): This field is set to `true` before removing
184184
stubs for other reasons than the upstream library shipping with type
185185
information.
186186
* `upload` (optional): This field is set to `false` to prevent automatic
187187
uploads to PyPI. This should only be used in special cases, e.g. when the stubs
188188
break the upload.
189-
* `partial_stub` (optional): This field marks the type stub package as
189+
* `partial-stub` (optional): This field marks the type stub package as
190190
[partial](https://peps.python.org/pep-0561/#partial-stub-packages). This is for
191191
3rd-party stubs that don't cover the entirety of the package's public API.
192-
* `requires_python` (optional): The minimum version of Python required to install
192+
* `requires-python` (optional): The minimum version of Python required to install
193193
the type stub package. It must be in the form `>=3.*`. If omitted, the oldest
194194
Python version supported by typeshed is used.
195195

@@ -198,36 +198,36 @@ This has the following keys:
198198
* `skip` (default: `false`): Whether stubtest should be run against this
199199
package. Please avoid setting this to `true`, and add a comment if you have
200200
to.
201-
* `ignore_missing_stub`: When set to `true`, this will add the
202-
`--ignore_missing_stub` option to the stubtest call. See
201+
* `ignore-missing-stub`: When set to `true`, this will add the
202+
`--ignore-missing-stub` option to the stubtest call. See
203203
[tests/README.md](./tests/README.md) for more information. In most cases,
204-
this field should be identical to `partial_stub`.
205-
* `stubtest_dependencies` (default: `[]`): A list of Python packages that need
204+
this field should be identical to `partial-stub`.
205+
* `stubtest-dependencies` (default: `[]`): A list of Python packages that need
206206
to be installed for stubtest to run successfully. These packages are installed
207207
in addition to the dependencies in the `dependencies` field.
208-
* `apt_dependencies` (default: `[]`): A list of Ubuntu APT packages
208+
* `apt-dependencies` (default: `[]`): A list of Ubuntu APT packages
209209
that need to be installed for stubtest to run successfully.
210-
* `brew_dependencies` (default: `[]`): A list of MacOS Homebrew packages
210+
* `brew-dependencies` (default: `[]`): A list of MacOS Homebrew packages
211211
that need to be installed for stubtest to run successfully
212-
* `choco_dependencies` (default: `[]`): A list of Windows Chocolatey packages
212+
* `choco-dependencies` (default: `[]`): A list of Windows Chocolatey packages
213213
that need to be installed for stubtest to run successfully
214-
* `supported_platforms` (default: all platforms): A list of OSes on which
214+
* `supported-platforms` (default: all platforms): A list of OSes on which
215215
stubtest can be run. When a package is not platform-specific, this should
216216
not be set. If the package is platform-specific, this should usually be set
217217
to the supported platforms, unless stubtest is known to fail on a
218218
specific platform.
219-
* `ci_platforms` (default: `["linux"]`): A list of OSes on which to run
219+
* `ci-platforms` (default: `["linux"]`): A list of OSes on which to run
220220
stubtest as part of our continuous integration (CI) tests. Can contain
221221
`win32`, `linux`, and `darwin` values. If not specified, stubtest is run
222222
only on `linux`. Only add extra OSes to the test if there are
223223
platform-specific branches in a stubs package.
224-
* `mypy_plugins` (default: `[]`): A list of Python modules to use as mypy plugins
225-
when running stubtest. For example: `mypy_plugins = ["mypy_django_plugin.main"]`
226-
* `mypy_plugins_config` (default: `{}`): A dictionary mapping plugin names to their
224+
* `mypy-plugins` (default: `[]`): A list of Python modules to use as mypy plugins
225+
when running stubtest. For example: `mypy-plugins = ["mypy_django_plugin.main"]`
226+
* `mypy-plugins-config` (default: `{}`): A dictionary mapping plugin names to their
227227
configuration dictionaries for use by mypy plugins. For example:
228-
`mypy_plugins_config = {"django-stubs" = {"django_settings_module" = "@tests.django_settings"}}`
228+
`mypy-plugins-config = {"django-stubs" = {"django_settings_module" = "@tests.django_settings"}}`
229229

230-
`*_dependencies` are usually packages needed to `pip install` the implementation
230+
`*-dependencies` are usually packages needed to `pip install` the implementation
231231
distribution.
232232

233233
The format of all `METADATA.toml` files can be checked by running
@@ -436,7 +436,7 @@ following criteria is met:
436436

437437
Case 1: If a package ships its own `py.typed` file, please follow these steps:
438438

439-
1. Make sure **stubsabot** open a PR that sets the `obsolete_since` field in the
439+
1. Make sure **stubsabot** open a PR that sets the `obsolete-since` field in the
440440
`METADATA.toml` file to the first version of the package that shipped `py.typed`.
441441
2. After at least six months, make sure **stubsabot** open a PR to remove the stubs.
442442

@@ -446,7 +446,7 @@ these steps:
446446
1. Open an issue explaining why the stubs should be removed.
447447
2. A maintainer will add the
448448
["stubs: removal" label](https://github.com/python/typeshed/labels/%22stubs%3A%20removal%22).
449-
3. Open a PR that sets the `no_longer_updated` field in the `METADATA.toml`
449+
3. Open a PR that sets the `no-longer-updated` field in the `METADATA.toml`
450450
file to `true`.
451451
4. When a new version of the package was automatically uploaded to PyPI (which
452452
can take up to a day), make sure **stubsabot** open a PR to remove the stubs.

lib/ts_utils/metadata.py

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def _is_nested_dict(obj: object) -> TypeGuard[dict[str, dict[str, Any]]]:
5858
@functools.cache
5959
def get_oldest_supported_python() -> str:
6060
with PYPROJECT_PATH.open("rb") as config:
61-
val = tomllib.load(config)["tool"]["typeshed"]["oldest_supported_python"]
61+
val = tomllib.load(config)["tool"]["typeshed"]["oldest-supported-python"]
6262
assert type(val) is str
6363
return val
6464

@@ -102,16 +102,16 @@ def read_stubtest_settings(distribution: str) -> StubtestSettings:
102102
data: dict[str, object] = tomllib.load(f).get("tool", {}).get("stubtest", {})
103103

104104
skip: object = data.get("skip", False)
105-
apt_dependencies: object = data.get("apt_dependencies", [])
106-
brew_dependencies: object = data.get("brew_dependencies", [])
107-
choco_dependencies: object = data.get("choco_dependencies", [])
105+
apt_dependencies: object = data.get("apt-dependencies", [])
106+
brew_dependencies: object = data.get("brew-dependencies", [])
107+
choco_dependencies: object = data.get("choco-dependencies", [])
108108
extras: object = data.get("extras", [])
109-
ignore_missing_stub: object = data.get("ignore_missing_stub", False)
110-
supported_platforms: object = data.get("supported_platforms")
111-
ci_platforms: object = data.get("ci_platforms", DEFAULT_STUBTEST_PLATFORMS)
112-
stubtest_dependencies: object = data.get("stubtest_dependencies", [])
113-
mypy_plugins: object = data.get("mypy_plugins", [])
114-
mypy_plugins_config: object = data.get("mypy_plugins_config", {})
109+
ignore_missing_stub: object = data.get("ignore-missing-stub", False)
110+
supported_platforms: object = data.get("supported-platforms")
111+
ci_platforms: object = data.get("ci-platforms", DEFAULT_STUBTEST_PLATFORMS)
112+
stubtest_dependencies: object = data.get("stubtest-dependencies", [])
113+
mypy_plugins: object = data.get("mypy-plugins", [])
114+
mypy_plugins_config: object = data.get("mypy-plugins-config", {})
115115

116116
assert type(skip) is bool
117117
assert type(ignore_missing_stub) is bool
@@ -128,12 +128,12 @@ def read_stubtest_settings(distribution: str) -> StubtestSettings:
128128
assert _is_nested_dict(mypy_plugins_config)
129129

130130
unrecognised_platforms = set(ci_platforms) - _STUBTEST_PLATFORM_MAPPING.keys()
131-
assert not unrecognised_platforms, f"Unrecognised ci_platforms specified for {distribution!r}: {unrecognised_platforms}"
131+
assert not unrecognised_platforms, f"Unrecognised ci-platforms specified for {distribution!r}: {unrecognised_platforms}"
132132

133133
if supported_platforms is not None:
134134
assert set(ci_platforms).issubset(
135135
supported_platforms
136-
), f"ci_platforms must be a subset of supported_platforms for {distribution!r}"
136+
), f"ci-platforms must be a subset of supported-platforms for {distribution!r}"
137137

138138
for platform, dep_key in _STUBTEST_PLATFORM_MAPPING.items():
139139
if platform not in ci_platforms:
@@ -194,31 +194,31 @@ def is_obsolete(self) -> bool:
194194
{
195195
"version",
196196
"dependencies",
197-
"extra_description",
198-
"stub_distribution",
199-
"upstream_repository",
200-
"obsolete_since",
201-
"no_longer_updated",
197+
"extra-description",
198+
"stub-distribution",
199+
"upstream-repository",
200+
"obsolete-since",
201+
"no-longer-updated",
202202
"upload",
203203
"tool",
204-
"partial_stub",
205-
"requires_python",
204+
"partial-stub",
205+
"requires-python",
206206
"mypy-tests",
207207
}
208208
)
209209
_KNOWN_METADATA_TOOL_FIELDS: Final = {
210210
"stubtest": {
211211
"skip",
212-
"apt_dependencies",
213-
"brew_dependencies",
214-
"choco_dependencies",
212+
"apt-dependencies",
213+
"brew-dependencies",
214+
"choco-dependencies",
215215
"extras",
216-
"ignore_missing_stub",
217-
"supported_platforms",
218-
"ci_platforms",
219-
"stubtest_dependencies",
220-
"mypy_plugins",
221-
"mypy_plugins_config",
216+
"ignore-missing-stub",
217+
"supported-platforms",
218+
"ci-platforms",
219+
"stubtest-dependencies",
220+
"mypy-plugins",
221+
"mypy-plugins-config",
222222
}
223223
}
224224
_DIST_NAME_RE: Final = re.compile(r"^[a-z0-9]([a-z0-9._-]*[a-z0-9])?$", re.IGNORECASE)
@@ -259,41 +259,41 @@ def read_metadata(distribution: str) -> StubMetadata:
259259
assert isinstance(dependencies_s, list)
260260
dependencies = [parse_dependencies(distribution, dep) for dep in dependencies_s]
261261

262-
extra_description: object = data.get("extra_description") # pyright: ignore[reportUnknownMemberType]
262+
extra_description: object = data.get("extra-description") # pyright: ignore[reportUnknownMemberType]
263263
assert isinstance(extra_description, (str, type(None)))
264264

265-
if "stub_distribution" in data:
266-
stub_distribution = data["stub_distribution"]
265+
if "stub-distribution" in data:
266+
stub_distribution = data["stub-distribution"]
267267
assert isinstance(stub_distribution, str)
268-
assert _DIST_NAME_RE.fullmatch(stub_distribution), f"Invalid 'stub_distribution' value for {distribution!r}"
268+
assert _DIST_NAME_RE.fullmatch(stub_distribution), f"Invalid 'stub-distribution' value for {distribution!r}"
269269
else:
270270
stub_distribution = f"types-{distribution}"
271271

272-
upstream_repository: object = data.get("upstream_repository") # pyright: ignore[reportUnknownMemberType]
272+
upstream_repository: object = data.get("upstream-repository") # pyright: ignore[reportUnknownMemberType]
273273
assert isinstance(upstream_repository, (str, type(None)))
274274
if isinstance(upstream_repository, str):
275275
parsed_url = urllib.parse.urlsplit(upstream_repository)
276-
assert parsed_url.scheme == "https", f"{distribution}: URLs in the upstream_repository field should use https"
276+
assert parsed_url.scheme == "https", f"{distribution}: URLs in the upstream-repository field should use https"
277277
no_www_please = (
278-
f"{distribution}: `World Wide Web` subdomain (`www.`) should be removed from URLs in the upstream_repository field"
278+
f"{distribution}: `World Wide Web` subdomain (`www.`) should be removed from URLs in the upstream-repository field"
279279
)
280280
assert not parsed_url.netloc.startswith("www."), no_www_please
281281
no_query_params_please = (
282-
f"{distribution}: Query params (`?`) should be removed from URLs in the upstream_repository field"
282+
f"{distribution}: Query params (`?`) should be removed from URLs in the upstream-repository field"
283283
)
284284
assert parsed_url.hostname in _QUERY_URL_ALLOWLIST or (not parsed_url.query), no_query_params_please
285-
no_fragments_please = f"{distribution}: Fragments (`#`) should be removed from URLs in the upstream_repository field"
285+
no_fragments_please = f"{distribution}: Fragments (`#`) should be removed from URLs in the upstream-repository field"
286286
assert not parsed_url.fragment, no_fragments_please
287287
if parsed_url.netloc == "github.com":
288288
cleaned_url_path = parsed_url.path.strip("/")
289289
num_url_path_parts = len(Path(cleaned_url_path).parts)
290290
bad_github_url_msg = (
291-
f"Invalid upstream_repository for {distribution!r}: "
291+
f"Invalid upstream-repository for {distribution!r}: "
292292
"URLs for GitHub repositories always have two parts in their paths"
293293
)
294294
assert num_url_path_parts == 2, bad_github_url_msg
295295

296-
obsolete_since: object = data.get("obsolete_since") # pyright: ignore[reportUnknownMemberType]
296+
obsolete_since: object = data.get("obsolete-since") # pyright: ignore[reportUnknownMemberType]
297297
assert isinstance(obsolete_since, (String, type(None)))
298298
if obsolete_since:
299299
comment = obsolete_since.trivia.comment
@@ -302,26 +302,26 @@ def read_metadata(distribution: str) -> StubMetadata:
302302
obsolete = ObsoleteMetadata(since_version=obsolete_since, since_date=since_date)
303303
else:
304304
obsolete = None
305-
no_longer_updated: object = data.get("no_longer_updated", False) # pyright: ignore[reportUnknownMemberType]
305+
no_longer_updated: object = data.get("no-longer-updated", False) # pyright: ignore[reportUnknownMemberType]
306306
assert type(no_longer_updated) is bool
307307
uploaded_to_pypi: object = data.get("upload", True) # pyright: ignore[reportUnknownMemberType]
308308
assert type(uploaded_to_pypi) is bool
309-
partial_stub: object = data.get("partial_stub", True) # pyright: ignore[reportUnknownMemberType]
309+
partial_stub: object = data.get("partial-stub", True) # pyright: ignore[reportUnknownMemberType]
310310
assert type(partial_stub) is bool
311-
requires_python_str: object = data.get("requires_python") # pyright: ignore[reportUnknownMemberType]
311+
requires_python_str: object = data.get("requires-python") # pyright: ignore[reportUnknownMemberType]
312312
oldest_supported_python = get_oldest_supported_python()
313313
oldest_supported_python_specifier = Specifier(f">={oldest_supported_python}")
314314
if requires_python_str is None:
315315
requires_python = oldest_supported_python_specifier
316316
else:
317317
assert isinstance(requires_python_str, str)
318318
requires_python = Specifier(requires_python_str)
319-
assert requires_python != oldest_supported_python_specifier, f'requires_python="{requires_python}" is redundant'
319+
assert requires_python != oldest_supported_python_specifier, f'requires-python="{requires_python}" is redundant'
320320
# Check minimum Python version is not less than the oldest version of Python supported by typeshed
321321
assert oldest_supported_python_specifier.contains(
322322
requires_python.version
323-
), f"'requires_python' contains versions lower than typeshed's oldest supported Python ({oldest_supported_python})"
324-
assert requires_python.operator == ">=", "'requires_python' should be a minimum version specifier, use '>=3.x'"
323+
), f"'requires-python' contains versions lower than typeshed's oldest supported Python ({oldest_supported_python})"
324+
assert requires_python.operator == ">=", "'requires-python' should be a minimum version specifier, use '>=3.x'"
325325

326326
empty_tools: dict[object, object] = {}
327327
tools_settings: object = data.get("tool", empty_tools) # pyright: ignore[reportUnknownMemberType]
@@ -361,6 +361,9 @@ def update_metadata(distribution: str, **new_values: object) -> tomlkit.TOMLDocu
361361
except FileNotFoundError:
362362
raise NoSuchStubError(f"Typeshed has no stubs for {distribution!r}!") from None
363363
data.update(new_values) # pyright: ignore[reportUnknownMemberType] # tomlkit.TOMLDocument.update is partially typed
364+
for key in list(data.keys()):
365+
new_key = key.replace("_", "-") # pyright: ignore[reportUnknownMemberType] # tomlkit.TOMLDocument.keys is partially typed
366+
data[new_key] = data.pop(key) # pyright: ignore[reportUnknownMemberType] # tomlkit.TOMLDocument.pop is partially typed
364367
with path.open("w", encoding="UTF-8") as file:
365368
tomlkit.dump(data, file) # pyright: ignore[reportUnknownMemberType] # tomlkit.dump has partially unknown Mapping type
366369
return data

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,4 +265,4 @@ extra-standard-library = [
265265
known-first-party = ["_utils", "ts_utils"]
266266

267267
[tool.typeshed]
268-
oldest_supported_python = "3.10"
268+
oldest-supported-python = "3.10"

scripts/create_baseline_stubs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,11 @@ def create_metadata(project: str, stub_dir: Path, version: str) -> None:
134134
if upstream_repo_url is None:
135135
warning = (
136136
f"\nCould not find a URL pointing to the source code for {project!r}.\n"
137-
f"Please add it as `upstream_repository` to `stubs/{project}/METADATA.toml`, if possible!\n"
137+
f"Please add it as `upstream-repository` to `stubs/{project}/METADATA.toml`, if possible!\n"
138138
)
139139
print(termcolor.colored(warning, "red"))
140140
else:
141-
metadata += f'upstream_repository = "{upstream_repo_url}"\n'
141+
metadata += f'upstream-repository = "{upstream_repo_url}"\n'
142142
print(f"Writing {filename}")
143143
filename.write_text(metadata, encoding="UTF-8")
144144

scripts/stubsabot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ def parse_no_longer_updated_from_archive(source: zipfile.ZipFile | tarfile.TarFi
607607
with file as f:
608608
toml_data: dict[str, object] = tomllib.load(f)
609609

610-
no_longer_updated = toml_data.get("no_longer_updated", False)
610+
no_longer_updated = toml_data.get("no-longer-updated", False)
611611
assert type(no_longer_updated) is bool
612612
return bool(no_longer_updated)
613613

stubs/Authlib/METADATA.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version = "1.6.9"
2-
upstream_repository = "https://github.com/authlib/authlib"
2+
upstream-repository = "https://github.com/authlib/authlib"
33
dependencies = ["cryptography"]

stubs/Deprecated/METADATA.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version = "~=1.3.1"
2-
upstream_repository = "https://github.com/laurent-laporte-pro/deprecated"
2+
upstream-repository = "https://github.com/laurent-laporte-pro/deprecated"
33
dependencies = []

stubs/Flask-Cors/METADATA.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
version = "6.0.*"
2-
upstream_repository = "https://github.com/corydolphin/flask-cors"
2+
upstream-repository = "https://github.com/corydolphin/flask-cors"
33
# Requires a version of flask with a `py.typed` file
44
dependencies = ["Flask>=2.0.0"]

stubs/Flask-Migrate/METADATA.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
version = "4.1.*"
2-
upstream_repository = "https://github.com/miguelgrinberg/Flask-Migrate"
2+
upstream-repository = "https://github.com/miguelgrinberg/Flask-Migrate"
33
# Requires versions of flask and Flask-SQLAlchemy with `py.typed` files
44
dependencies = ["Flask-SQLAlchemy>=3.0.1", "Flask>=2.0.0"]

stubs/Flask-SocketIO/METADATA.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version = "5.6.*"
22
dependencies = ["Flask>=0.9"]
3-
upstream_repository = "https://github.com/miguelgrinberg/flask-socketio"
3+
upstream-repository = "https://github.com/miguelgrinberg/flask-socketio"

0 commit comments

Comments
 (0)