Skip to content

Split tool.stubtest.platforms metadata key #13746

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/daily.yml
Original file line number Diff line number Diff line change
@@ -96,7 +96,7 @@ jobs:
PYTHON_EXECUTABLE="python"
fi

$PYTHON_EXECUTABLE tests/stubtest_third_party.py --specified-platforms-only --num-shards 4 --shard-index ${{ matrix.shard-index }}
$PYTHON_EXECUTABLE tests/stubtest_third_party.py --ci-platforms-only --num-shards 4 --shard-index ${{ matrix.shard-index }}

stub-uploader:
name: stub_uploader tests
2 changes: 1 addition & 1 deletion .github/workflows/stubtest_third_party.yml
Original file line number Diff line number Diff line change
@@ -85,7 +85,7 @@ jobs:
PYTHON_EXECUTABLE="python"
fi

$PYTHON_EXECUTABLE tests/stubtest_third_party.py --specified-platforms-only $STUBS
$PYTHON_EXECUTABLE tests/stubtest_third_party.py --ci-platforms-only $STUBS
else
echo "Nothing to test"
fi
16 changes: 10 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -224,18 +224,22 @@ This has the following keys:
that need to be installed for stubtest to run successfully
* `choco_dependencies` (default: `[]`): A list of Windows Chocolatey packages
that need to be installed for stubtest to run successfully
* `platforms` (default: `["linux"]`): A list of OSes on which to run stubtest.
Can contain `win32`, `linux`, and `darwin` values.
If not specified, stubtest is run only on `linux`.
Only add extra OSes to the test
if there are platform-specific branches in a stubs package.
* `supported_platforms` (default: all platforms): A list of OSes on which
stubtest can be run. When a package is not platform-specific, this should
not be set. If the package is platform-specific, this should usually be set
to the supported platforms, unless stubtest is known to fail on a
specific platform.
* `ci_platforms` (default: `["linux"]`): A list of OSes on which to run
stubtest as part of our continuous integration (CI) tests. Can contain
`win32`, `linux`, and `darwin` values. If not specified, stubtest is run
only on `linux`. Only add extra OSes to the test if there are
platform-specific branches in a stubs package.
* `mypy_plugins` (default: `[]`): A list of Python modules to use as mypy plugins
when running stubtest. For example: `mypy_plugins = ["mypy_django_plugin.main"]`
* `mypy_plugins_config` (default: `{}`): A dictionary mapping plugin names to their
configuration dictionaries for use by mypy plugins. For example:
`mypy_plugins_config = {"django-stubs" = {"django_settings_module" = "@tests.django_settings"}}`


`*_dependencies` are usually packages needed to `pip install` the implementation
distribution.

27 changes: 19 additions & 8 deletions lib/ts_utils/metadata.py
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@
"read_stubtest_settings",
]

DEFAULT_STUBTEST_PLATFORMS = ["linux"]

_STUBTEST_PLATFORM_MAPPING: Final = {"linux": "apt_dependencies", "darwin": "brew_dependencies", "win32": "choco_dependencies"}
# Some older websites have a bad pattern of using query params for navigation.
@@ -73,7 +74,8 @@ class StubtestSettings:
choco_dependencies: list[str]
extras: list[str]
ignore_missing_stub: bool
platforms: list[str]
supported_platforms: list[str] | None # None means all platforms
ci_platforms: list[str]
stubtest_requirements: list[str]
mypy_plugins: list[str]
mypy_plugins_config: dict[str, dict[str, Any]]
@@ -97,7 +99,8 @@ def read_stubtest_settings(distribution: str) -> StubtestSettings:
choco_dependencies: object = data.get("choco_dependencies", [])
extras: object = data.get("extras", [])
ignore_missing_stub: object = data.get("ignore_missing_stub", False)
specified_platforms: object = data.get("platforms", ["linux"])
supported_platforms: object = data.get("supported_platforms")
ci_platforms: object = data.get("ci_platforms", DEFAULT_STUBTEST_PLATFORMS)
stubtest_requirements: object = data.get("stubtest_requirements", [])
mypy_plugins: object = data.get("mypy_plugins", [])
mypy_plugins_config: object = data.get("mypy_plugins_config", {})
@@ -106,7 +109,8 @@ def read_stubtest_settings(distribution: str) -> StubtestSettings:
assert type(ignore_missing_stub) is bool

# It doesn't work for type-narrowing if we use a for loop here...
assert _is_list_of_strings(specified_platforms)
assert supported_platforms is None or _is_list_of_strings(supported_platforms)
assert _is_list_of_strings(ci_platforms)
assert _is_list_of_strings(apt_dependencies)
assert _is_list_of_strings(brew_dependencies)
assert _is_list_of_strings(choco_dependencies)
@@ -115,11 +119,16 @@ def read_stubtest_settings(distribution: str) -> StubtestSettings:
assert _is_list_of_strings(mypy_plugins)
assert _is_nested_dict(mypy_plugins_config)

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

if supported_platforms is not None:
assert set(ci_platforms).issubset(
supported_platforms
), f"ci_platforms must be a subset of supported_platforms for {distribution!r}"

for platform, dep_key in _STUBTEST_PLATFORM_MAPPING.items():
if platform not in specified_platforms:
if platform not in ci_platforms:
assert dep_key not in data, (
f"Stubtest is not run on {platform} in CI for {distribution!r}, "
f"but {dep_key!r} are specified in METADATA.toml"
@@ -132,7 +141,8 @@ def read_stubtest_settings(distribution: str) -> StubtestSettings:
choco_dependencies=choco_dependencies,
extras=extras,
ignore_missing_stub=ignore_missing_stub,
platforms=specified_platforms,
supported_platforms=supported_platforms,
ci_platforms=ci_platforms,
stubtest_requirements=stubtest_requirements,
mypy_plugins=mypy_plugins,
mypy_plugins_config=mypy_plugins_config,
@@ -189,7 +199,8 @@ def is_obsolete(self) -> bool:
"choco_dependencies",
"extras",
"ignore_missing_stub",
"platforms",
"supported_platforms",
"ci_platforms",
"stubtest_requirements",
"mypy_plugins",
"mypy_plugins_config",
4 changes: 4 additions & 0 deletions lib/ts_utils/utils.py
Original file line number Diff line number Diff line change
@@ -50,6 +50,10 @@ def print_info(message: str) -> None:
print(colored(message, "blue"))


def print_warning(message: str) -> None:
print(colored(message), "yellow")


def print_error(error: str, end: str = "\n", fix_path: tuple[str, str] = ("", "")) -> None:
error_split = error.split("\n")
old, new = fix_path
2 changes: 1 addition & 1 deletion stubs/JACK-Client/METADATA.toml
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ requires = ["numpy>=1.20", "types-cffi"]

[tool.stubtest]
# darwin and win32 are equivalent
platforms = ["darwin", "linux"]
ci_platforms = ["darwin", "linux"]
apt_dependencies = ["libjack-dev"]
brew_dependencies = ["jack"]
# No need to install on the CI. Leaving here as information for Windows contributors.
2 changes: 1 addition & 1 deletion stubs/PyScreeze/METADATA.toml
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ requires = ["Pillow>=10.3.0"]

[tool.stubtest]
# Linux has extra constants, win32 has different definitions
platforms = ["linux", "win32"]
ci_platforms = ["linux", "win32"]
# PyScreeze has an odd setup.py file
# that doesn't list Pillow as a dependency for py312+ yet:
# https://github.com/asweigart/pyscreeze/blob/eeca245a135cf171c163b3691300138518efa64e/setup.py#L38-L46
8 changes: 5 additions & 3 deletions stubs/RPi.GPIO/METADATA.toml
Original file line number Diff line number Diff line change
@@ -2,7 +2,9 @@ version = "0.7.*"
upstream_repository = "https://sourceforge.net/p/raspberry-gpio-python/code/"

[tool.stubtest]
# When stubtest tries to import this module:
# error: RPi.GPIO failed to import. RuntimeError: This module can only be run on a Raspberry Pi!
# This package is only supported on Raspberry Pi hardware, which identifies
# itself as 'linux'. When run on other hardware, it raises a RuntimeError:
# RPi.GPIO failed to import. RuntimeError: This module can only be run on a Raspberry Pi!
# https://sourceforge.net/p/raspberry-gpio-python/code/ci/08048dd1894a6b09a104557b6eaa6bb68b6baac5/tree/source/py_gpio.c#l1008
skip = true
supported_platforms = []
ci_platforms = []
2 changes: 1 addition & 1 deletion stubs/aiofiles/METADATA.toml
Original file line number Diff line number Diff line change
@@ -3,4 +3,4 @@ upstream_repository = "https://github.com/Tinche/aiofiles"

[tool.stubtest]
# linux and darwin are equivalent
platforms = ["linux", "win32"]
ci_platforms = ["linux", "win32"]
2 changes: 1 addition & 1 deletion stubs/antlr4-python3-runtime/METADATA.toml
Original file line number Diff line number Diff line change
@@ -3,4 +3,4 @@ upstream_repository = "https://github.com/antlr/antlr4"

[tool.stubtest]
ignore_missing_stub = true
platforms = ["linux", "win32"]
ci_platforms = ["linux", "win32"]
2 changes: 1 addition & 1 deletion stubs/cffi/METADATA.toml
Original file line number Diff line number Diff line change
@@ -4,4 +4,4 @@ requires = ["types-setuptools"]

[tool.stubtest]
# linux and darwin are mostly equivalent, except for a single `RTLD_DEEPBIND` variable
platforms = ["linux", "win32"]
ci_platforms = ["linux", "win32"]
2 changes: 1 addition & 1 deletion stubs/colorama/METADATA.toml
Original file line number Diff line number Diff line change
@@ -2,4 +2,4 @@ version = "0.4.*"
upstream_repository = "https://github.com/tartley/colorama"

[tool.stubtest]
platforms = ["linux", "win32"]
ci_platforms = ["linux", "win32"]
2 changes: 1 addition & 1 deletion stubs/gdb/METADATA.toml
Original file line number Diff line number Diff line change
@@ -11,5 +11,5 @@ extra_description = """\
"""

[tool.stubtest]
platforms = ["linux"]
ci_platforms = ["linux"]
apt_dependencies = ["gdb"]
2 changes: 1 addition & 1 deletion stubs/gevent/METADATA.toml
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ requires = ["types-greenlet", "types-psutil"]
[tool.stubtest]
# Run stubtest on all platforms, since there is some platform specific stuff
# especially in the stdlib module replacement
platforms = ["linux", "darwin", "win32"]
ci_platforms = ["linux", "darwin", "win32"]
# for testing the ffi loop implementations on all platforms
stubtest_requirements = ["cffi", "dnspython"]
apt_dependencies = ["libev4", "libev-dev", "libuv1", "libuv1-dev"]
2 changes: 1 addition & 1 deletion stubs/keyboard/METADATA.toml
Original file line number Diff line number Diff line change
@@ -6,4 +6,4 @@ upstream_repository = "https://github.com/boppreh/keyboard"
# It's only by possible mouse buttons and event literal types.
# As well as returning a tuple of int/long from keyboard.mouse.get_position
# The "mouse" module is obsoleted by the "mouse" package.
# platforms =
# ci_platforms = ["linux"]
2 changes: 1 addition & 1 deletion stubs/paramiko/METADATA.toml
Original file line number Diff line number Diff line change
@@ -7,4 +7,4 @@ partial_stub = true
[tool.stubtest]
ignore_missing_stub = true
# linux and darwin are equivalent
platforms = ["linux", "win32"]
ci_platforms = ["linux", "win32"]
2 changes: 1 addition & 1 deletion stubs/psutil/METADATA.toml
Original file line number Diff line number Diff line change
@@ -2,4 +2,4 @@ version = "7.0.*"
upstream_repository = "https://github.com/giampaolo/psutil"

[tool.stubtest]
platforms = ["darwin", "linux", "win32"]
ci_platforms = ["darwin", "linux", "win32"]
2 changes: 1 addition & 1 deletion stubs/pyaudio/METADATA.toml
Original file line number Diff line number Diff line change
@@ -4,6 +4,6 @@ version = "0.2.*"

[tool.stubtest]
# linux and win32 are equivalent
platforms = ["darwin", "linux"]
ci_platforms = ["darwin", "linux"]
apt_dependencies = ["portaudio19-dev"]
brew_dependencies = ["portaudio"]
2 changes: 1 addition & 1 deletion stubs/pycurl/METADATA.toml
Original file line number Diff line number Diff line change
@@ -2,4 +2,4 @@ version = "7.45.6"
upstream_repository = "https://github.com/pycurl/pycurl"

[tool.stubtest]
platforms = ["darwin", "linux", "win32"]
ci_platforms = ["darwin", "linux", "win32"]
2 changes: 1 addition & 1 deletion stubs/pynput/METADATA.toml
Original file line number Diff line number Diff line change
@@ -2,4 +2,4 @@ version = "~=1.8.1"
upstream_repository = "https://github.com/moses-palmer/pynput"

[tool.stubtest]
platforms = ["darwin", "linux", "win32"]
ci_platforms = ["darwin", "linux", "win32"]
2 changes: 1 addition & 1 deletion stubs/pyperclip/METADATA.toml
Original file line number Diff line number Diff line change
@@ -2,5 +2,5 @@ version = "1.9.*"
upstream_repository = "https://github.com/asweigart/pyperclip"

[tool.stubtest]
platforms = ["win32", "linux", "darwin"]
ci_platforms = ["win32", "linux", "darwin"]
apt_dependencies = ["xclip"]
2 changes: 1 addition & 1 deletion stubs/pyserial/METADATA.toml
Original file line number Diff line number Diff line change
@@ -2,5 +2,5 @@ version = "3.5.*"
upstream_repository = "https://github.com/pyserial/pyserial"

[tool.stubtest]
platforms = ["darwin", "linux", "win32"]
ci_platforms = ["darwin", "linux", "win32"]
extras = ["cp2110"]
3 changes: 2 additions & 1 deletion stubs/pywin32/METADATA.toml
Original file line number Diff line number Diff line change
@@ -2,4 +2,5 @@ version = "310.*"
upstream_repository = "https://github.com/mhammond/pywin32"

[tool.stubtest]
platforms = ["win32"]
supported_platforms = ["win32"]
ci_platforms = ["win32"]
2 changes: 1 addition & 1 deletion stubs/setuptools/METADATA.toml
Original file line number Diff line number Diff line change
@@ -7,5 +7,5 @@ it is no longer included with `types-setuptools`.

[tool.stubtest]
# darwin is equivalent to linux for OS-specific methods
platforms = ["linux", "win32"]
ci_platforms = ["linux", "win32"]
stubtest_requirements = ["tomli"]
2 changes: 1 addition & 1 deletion stubs/uWSGI/METADATA.toml
Original file line number Diff line number Diff line change
@@ -12,4 +12,4 @@ extra_description = """\
# Run stubtest on MacOS as well, to check that the
# uWSGI-specific parts of stubtest_third_party.py
# also work there
platforms = ["linux", "darwin"]
ci_platforms = ["linux", "darwin"]
2 changes: 1 addition & 1 deletion stubs/waitress/METADATA.toml
Original file line number Diff line number Diff line change
@@ -3,4 +3,4 @@ upstream_repository = "https://github.com/Pylons/waitress"

[tool.stubtest]
# linux and darwin are equivalent
platforms = ["linux", "win32"]
ci_platforms = ["linux", "win32"]
30 changes: 18 additions & 12 deletions tests/stubtest_third_party.py
Original file line number Diff line number Diff line change
@@ -28,12 +28,11 @@
print_info,
print_success_msg,
print_time,
print_warning,
)


def run_stubtest(
dist: Path, *, verbose: bool = False, specified_platforms_only: bool = False, keep_tmp_dir: bool = False
) -> bool:
def run_stubtest(dist: Path, *, verbose: bool = False, ci_platforms_only: bool = False, keep_tmp_dir: bool = False) -> bool:
"""Run stubtest for a single distribution."""

dist_name = dist.name
@@ -44,14 +43,16 @@ def run_stubtest(

stubtest_settings = metadata.stubtest_settings
if stubtest_settings.skip:
print(colored("skipping", "yellow"))
print(colored("skipping (skip = true)", "yellow"))
return True

if sys.platform not in stubtest_settings.platforms:
if specified_platforms_only:
print(colored("skipping (platform not specified in METADATA.toml)", "yellow"))
return True
print(colored(f"Note: {dist_name} is not currently tested on {sys.platform} in typeshed's CI.", "yellow"))
if stubtest_settings.supported_platforms is not None and sys.platform not in stubtest_settings.supported_platforms:
print(colored("skipping (platform not supported)", "yellow"))
return True

if ci_platforms_only and sys.platform not in stubtest_settings.ci_platforms:
print(colored("skipping (platform skipped in CI)", "yellow"))
return True

if not metadata.requires_python.contains(PYTHON_VERSION):
print(colored(f"skipping (requires Python {metadata.requires_python})", "yellow"))
@@ -189,8 +190,13 @@ def run_stubtest(
else:
print_time(time() - t)
print_success_msg()

if sys.platform not in stubtest_settings.ci_platforms:
print_warning(f"Note: {dist_name} is not currently tested on {sys.platform} in typeshed's CI")

if keep_tmp_dir:
print_info(f"Virtual environment kept at: {venv_dir}")

finally:
if not keep_tmp_dir:
rmtree(venv_dir)
@@ -398,9 +404,9 @@ def main() -> NoReturn:
parser.add_argument("--num-shards", type=int, default=1)
parser.add_argument("--shard-index", type=int, default=0)
parser.add_argument(
"--specified-platforms-only",
"--ci-platforms-only",
action="store_true",
help="skip the test if the current platform is not specified in METADATA.toml/tool.stubtest.platforms",
help="skip the test if the current platform is not specified in METADATA.toml/tool.stubtest.ci-platforms",
)
parser.add_argument("--keep-tmp-dir", action="store_true", help="keep the temporary virtualenv")
parser.add_argument("dists", metavar="DISTRIBUTION", type=str, nargs=argparse.ZERO_OR_MORE)
@@ -417,7 +423,7 @@ def main() -> NoReturn:
continue
try:
if not run_stubtest(
dist, verbose=args.verbose, specified_platforms_only=args.specified_platforms_only, keep_tmp_dir=args.keep_tmp_dir
dist, verbose=args.verbose, ci_platforms_only=args.ci_platforms_only, keep_tmp_dir=args.keep_tmp_dir
):
result = 1
except NoSuchStubError as e: