Skip to content

Commit 14e5d16

Browse files
authored
Replace METADATA stubtest key with stubtest_apt_packages (#6704)
1 parent 975b3e9 commit 14e5d16

File tree

9 files changed

+38
-15
lines changed

9 files changed

+38
-15
lines changed

.github/workflows/stubtest.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,4 @@ jobs:
5353
- name: Install dependencies
5454
run: pip install $(grep tomli== requirements-tests.txt)
5555
- name: Run stubtest
56-
run: python tests/stubtest_third_party.py --num-shards 4 --shard-index ${{ matrix.shard-index }}
56+
run: python tests/stubtest_third_party.py --num-shards 4 --shard-index ${{ matrix.shard-index }} --sudo-install-apt

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ jobs:
131131
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))
132132
if test -n "$STUBS"; then
133133
echo "Testing $STUBS..."
134-
python tests/stubtest_third_party.py $STUBS
134+
python tests/stubtest_third_party.py --sudo-install-apt $STUBS
135135
else
136136
echo "Nothing to test"
137137
fi

CONTRIBUTING.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,9 @@ supported:
177177
[removing obsolete third-party libraries](#third-party-library-removal-policy).
178178
It contains the first version of the corresponding library that ships
179179
its own `py.typed` file.
180-
* `stubtest` (default: `true`): Whether stubtest should be run against this
181-
package. Please avoid setting this to `false`, and add a comment if you have to.
180+
* `stubtest_apt_dependencies` (default: `[]`): A list of Ubuntu APT packages
181+
that need to be installed for stubtest to run successfully. These are
182+
usually packages needed to pip install the implementation distribution.
182183

183184
The format of all `METADATA.toml` files can be checked by running
184185
`python3 ./tests/check_consistent.py`.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pyaudio.PaMacCoreStreamInfo
2+
pyaudio.paMacCoreStreamInfo

stubs/pyaudio/METADATA.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version = "0.2.*"
22
python2 = true
3-
stubtest = false # install fails locally
3+
stubtest_apt_dependencies = ["portaudio19-dev"]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
pycurl
1+
pycurl.VERSION_FIRST

stubs/pycurl/METADATA.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
version = "7.44.*"
2-
stubtest = false # install failure, missing libcurl
2+
stubtest_apt_dependencies = ["libcurl4-openssl-dev"]

tests/check_consistent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import tomli
1919

2020
consistent_files = [{"stdlib/@python2/builtins.pyi", "stdlib/@python2/__builtin__.pyi"}]
21-
metadata_keys = {"version", "python2", "requires", "extra_description", "obsolete_since", "stubtest"}
21+
metadata_keys = {"version", "python2", "requires", "extra_description", "obsolete_since", "stubtest_apt_dependencies"}
2222
allowed_files = {"README.md"}
2323

2424

tests/stubtest_third_party.py

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,17 @@ def get_mypy_req():
2222
return next(line.strip() for line in f if "mypy" in line)
2323

2424

25-
def run_stubtest(dist: Path) -> bool:
25+
def run_stubtest(dist: Path, *, install_apt: bool = False) -> bool:
2626
with open(dist / "METADATA.toml") as f:
2727
metadata = dict(tomli.loads(f.read()))
2828

29-
if not run_stubtest_for(metadata, dist):
29+
if not has_py3_stubs(dist):
3030
print(f"Skipping stubtest for {dist.name}\n\n")
3131
return True
3232

33+
if not install_apt_packages(dist, metadata, install_apt):
34+
return False
35+
3336
with tempfile.TemporaryDirectory() as tmp:
3437
venv_dir = Path(tmp)
3538
venv.create(venv_dir, with_pip=True, clear=True)
@@ -109,19 +112,36 @@ def run_stubtest(dist: Path) -> bool:
109112
return True
110113

111114

112-
def run_stubtest_for(metadata: dict[str, Any], dist: Path) -> bool:
113-
return has_py3_stubs(dist) and metadata.get("stubtest", True)
114-
115-
116115
# Keep this in sync with mypy_test.py
117116
def has_py3_stubs(dist: Path) -> bool:
118117
return len(glob(f"{dist}/*.pyi")) > 0 or len(glob(f"{dist}/[!@]*/__init__.pyi")) > 0
119118

120119

120+
def install_apt_packages(dist: Path, metadata: dict[str, Any], install: bool) -> bool:
121+
apt_packages = metadata.get("stubtest_apt_dependencies", [])
122+
if not apt_packages:
123+
return True
124+
if not install:
125+
print(f"Ensure the following apt packages are installed for {dist.name}: {', '.join(apt_packages)}", file=sys.stderr)
126+
return True
127+
try:
128+
apt_cmd = ["sudo", "apt", "install", "-y", *apt_packages]
129+
print(" ".join(apt_cmd), file=sys.stderr)
130+
subprocess.run(apt_cmd, check=True, capture_output=True)
131+
except subprocess.CalledProcessError as e:
132+
print(f"Failed to install APT packages for {dist.name}: {', '.join(apt_packages)}", file=sys.stderr)
133+
print(e.stdout.decode(), file=sys.stderr)
134+
print(e.stderr.decode(), file=sys.stderr)
135+
return False
136+
else:
137+
return True
138+
139+
121140
def main() -> NoReturn:
122141
parser = argparse.ArgumentParser()
123142
parser.add_argument("--num-shards", type=int, default=1)
124143
parser.add_argument("--shard-index", type=int, default=0)
144+
parser.add_argument("--sudo-install-apt", action="store_true")
125145
parser.add_argument("dists", metavar="DISTRIBUTION", type=str, nargs=argparse.ZERO_OR_MORE)
126146
args = parser.parse_args()
127147

@@ -135,7 +155,7 @@ def main() -> NoReturn:
135155
for i, dist in enumerate(dists):
136156
if i % args.num_shards != args.shard_index:
137157
continue
138-
if not run_stubtest(dist):
158+
if not run_stubtest(dist, install_apt=args.sudo_install_apt):
139159
result = 1
140160
sys.exit(result)
141161

0 commit comments

Comments
 (0)