Replace METADATA stubtest key with stubtest_apt_packages (#6704)

This commit is contained in:
Sebastian Rittau
2021-12-27 17:28:59 +01:00
committed by GitHub
parent 975b3e901b
commit 14e5d16c3a
9 changed files with 38 additions and 15 deletions

View File

@@ -53,4 +53,4 @@ jobs:
- name: Install dependencies
run: pip install $(grep tomli== requirements-tests.txt)
- name: Run stubtest
run: python tests/stubtest_third_party.py --num-shards 4 --shard-index ${{ matrix.shard-index }}
run: python tests/stubtest_third_party.py --num-shards 4 --shard-index ${{ matrix.shard-index }} --sudo-install-apt

View File

@@ -131,7 +131,7 @@ jobs:
STUBS=$(git diff --name-only origin/${{ github.base_ref }} HEAD | egrep ^stubs/ | cut -d "/" -f 2 | sort -u | (while read stub; do [ -d stubs/$stub ] && echo $stub || true; done))
if test -n "$STUBS"; then
echo "Testing $STUBS..."
python tests/stubtest_third_party.py $STUBS
python tests/stubtest_third_party.py --sudo-install-apt $STUBS
else
echo "Nothing to test"
fi

View File

@@ -177,8 +177,9 @@ supported:
[removing obsolete third-party libraries](#third-party-library-removal-policy).
It contains the first version of the corresponding library that ships
its own `py.typed` file.
* `stubtest` (default: `true`): Whether stubtest should be run against this
package. Please avoid setting this to `false`, and add a comment if you have to.
* `stubtest_apt_dependencies` (default: `[]`): A list of Ubuntu APT packages
that need to be installed for stubtest to run successfully. These are
usually packages needed to pip install the implementation distribution.
The format of all `METADATA.toml` files can be checked by running
`python3 ./tests/check_consistent.py`.

View File

@@ -0,0 +1,2 @@
pyaudio.PaMacCoreStreamInfo
pyaudio.paMacCoreStreamInfo

View File

@@ -1,3 +1,3 @@
version = "0.2.*"
python2 = true
stubtest = false # install fails locally
stubtest_apt_dependencies = ["portaudio19-dev"]

View File

@@ -1 +1 @@
pycurl
pycurl.VERSION_FIRST

View File

@@ -1,2 +1,2 @@
version = "7.44.*"
stubtest = false # install failure, missing libcurl
stubtest_apt_dependencies = ["libcurl4-openssl-dev"]

View File

@@ -18,7 +18,7 @@ import re
import tomli
consistent_files = [{"stdlib/@python2/builtins.pyi", "stdlib/@python2/__builtin__.pyi"}]
metadata_keys = {"version", "python2", "requires", "extra_description", "obsolete_since", "stubtest"}
metadata_keys = {"version", "python2", "requires", "extra_description", "obsolete_since", "stubtest_apt_dependencies"}
allowed_files = {"README.md"}

View File

@@ -22,14 +22,17 @@ def get_mypy_req():
return next(line.strip() for line in f if "mypy" in line)
def run_stubtest(dist: Path) -> bool:
def run_stubtest(dist: Path, *, install_apt: bool = False) -> bool:
with open(dist / "METADATA.toml") as f:
metadata = dict(tomli.loads(f.read()))
if not run_stubtest_for(metadata, dist):
if not has_py3_stubs(dist):
print(f"Skipping stubtest for {dist.name}\n\n")
return True
if not install_apt_packages(dist, metadata, install_apt):
return False
with tempfile.TemporaryDirectory() as tmp:
venv_dir = Path(tmp)
venv.create(venv_dir, with_pip=True, clear=True)
@@ -109,19 +112,36 @@ def run_stubtest(dist: Path) -> bool:
return True
def run_stubtest_for(metadata: dict[str, Any], dist: Path) -> bool:
return has_py3_stubs(dist) and metadata.get("stubtest", True)
# Keep this in sync with mypy_test.py
def has_py3_stubs(dist: Path) -> bool:
return len(glob(f"{dist}/*.pyi")) > 0 or len(glob(f"{dist}/[!@]*/__init__.pyi")) > 0
def install_apt_packages(dist: Path, metadata: dict[str, Any], install: bool) -> bool:
apt_packages = metadata.get("stubtest_apt_dependencies", [])
if not apt_packages:
return True
if not install:
print(f"Ensure the following apt packages are installed for {dist.name}: {', '.join(apt_packages)}", file=sys.stderr)
return True
try:
apt_cmd = ["sudo", "apt", "install", "-y", *apt_packages]
print(" ".join(apt_cmd), file=sys.stderr)
subprocess.run(apt_cmd, check=True, capture_output=True)
except subprocess.CalledProcessError as e:
print(f"Failed to install APT packages for {dist.name}: {', '.join(apt_packages)}", file=sys.stderr)
print(e.stdout.decode(), file=sys.stderr)
print(e.stderr.decode(), file=sys.stderr)
return False
else:
return True
def main() -> NoReturn:
parser = argparse.ArgumentParser()
parser.add_argument("--num-shards", type=int, default=1)
parser.add_argument("--shard-index", type=int, default=0)
parser.add_argument("--sudo-install-apt", action="store_true")
parser.add_argument("dists", metavar="DISTRIBUTION", type=str, nargs=argparse.ZERO_OR_MORE)
args = parser.parse_args()
@@ -135,7 +155,7 @@ def main() -> NoReturn:
for i, dist in enumerate(dists):
if i % args.num_shards != args.shard_index:
continue
if not run_stubtest(dist):
if not run_stubtest(dist, install_apt=args.sudo_install_apt):
result = 1
sys.exit(result)