Skip to content

Commit 3bbb589

Browse files
author
GitHub Copilot
committed
test: guard regenerated packages emit pyproject.toml; reset pygen globals
Add tests/unit/test_generated_packaging_files.py which walks all regenerated packages under tests/generated/ and asserts each one contains pyproject.toml (and not setup.py), except the explicit keep-setup-py opt-in package setuppy-authentication-union. Also reset pygen.codegen.serializers._PACKAGE_FILES and _REGENERATE_FILES at the start of each spec in run_batch.py. JinjaSerializer._regenerate_setup_py appends to these module-level globals, and ProcessPoolExecutor reuses worker processes across specs, so once a worker handled a spec with keep-setup-py=true, every subsequent spec on that worker would emit BOTH setup.py and pyproject.toml.
1 parent edc40cf commit 3bbb589

2 files changed

Lines changed: 82 additions & 0 deletions

File tree

packages/http-client-python/eng/scripts/setup/run_batch.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,23 @@ def _coerce(value):
5555
k: _coerce(v) for k, v in command_args.items() if k not in ["emit-yaml-only"]
5656
}
5757

58+
# Reset pygen's module-level _PACKAGE_FILES / _REGENERATE_FILES before each spec.
59+
# JinjaSerializer._regenerate_setup_py appends to these globals, and ProcessPoolExecutor
60+
# reuses worker processes across specs. Without this reset, once a worker handles a
61+
# spec with keep-setup-py=true, every subsequent spec on that worker emits BOTH
62+
# setup.py and pyproject.toml.
63+
from pygen.codegen import serializers as _serializers
64+
65+
_serializers._PACKAGE_FILES[:] = [
66+
"CHANGELOG.md.jinja2",
67+
"dev_requirements.txt.jinja2",
68+
"LICENSE.jinja2",
69+
"MANIFEST.in.jinja2",
70+
"README.md.jinja2",
71+
]
72+
_serializers._REGENERATE_FILES.clear()
73+
_serializers._REGENERATE_FILES.add("MANIFEST.in")
74+
5875
# Run preprocess and codegen (black is batched at the end for performance)
5976
preprocess.PreProcessPlugin(output_folder=output_dir, tsp_file=yaml_path, **pygen_args).process()
6077

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# -------------------------------------------------------------------------
2+
# Copyright (c) Microsoft Corporation. All rights reserved.
3+
# Licensed under the MIT License. See License.txt in the project root for
4+
# license information.
5+
# --------------------------------------------------------------------------
6+
"""Verify regenerated test packages emit pyproject.toml, not setup.py.
7+
8+
The Python emitter passes options to pygen via JSON config files. Boolean
9+
flags arrive as the strings "true"/"false". If those strings are not coerced
10+
to real booleans before being unpacked as kwargs to pygen, a value like
11+
keep-setup-py="false" is treated as truthy in Python and pygen emits
12+
setup.py instead of pyproject.toml. This test guards against that
13+
regression by walking the regenerated test fixtures.
14+
"""
15+
from pathlib import Path
16+
17+
import pytest
18+
19+
# Packages that intentionally opt into setup.py via keep-setup-py=true in
20+
# eng/scripts/ci/regenerate.ts. They should have setup.py and no pyproject.toml.
21+
KEEP_SETUP_PY_PACKAGES = {"setuppy-authentication-union"}
22+
23+
_GENERATED_ROOT = Path(__file__).resolve().parents[1] / "generated"
24+
25+
26+
def _iter_generated_packages():
27+
if not _GENERATED_ROOT.is_dir():
28+
return
29+
for flavor_dir in sorted(_GENERATED_ROOT.iterdir()):
30+
if not flavor_dir.is_dir():
31+
continue
32+
for pkg_dir in sorted(flavor_dir.iterdir()):
33+
if not pkg_dir.is_dir():
34+
continue
35+
yield flavor_dir.name, pkg_dir
36+
37+
38+
@pytest.mark.parametrize(
39+
"flavor,pkg_dir",
40+
list(_iter_generated_packages()),
41+
ids=lambda v: v.name if isinstance(v, Path) else v,
42+
)
43+
def test_generated_package_uses_pyproject_toml(flavor, pkg_dir):
44+
has_setup_py = (pkg_dir / "setup.py").is_file()
45+
has_pyproject = (pkg_dir / "pyproject.toml").is_file()
46+
47+
if pkg_dir.name in KEEP_SETUP_PY_PACKAGES:
48+
assert has_setup_py, f"{flavor}/{pkg_dir.name} should have setup.py (keep-setup-py=true)"
49+
assert not has_pyproject, (
50+
f"{flavor}/{pkg_dir.name} should NOT have pyproject.toml (keep-setup-py=true)"
51+
)
52+
return
53+
54+
assert has_pyproject, (
55+
f"{flavor}/{pkg_dir.name} is missing pyproject.toml. "
56+
f"This usually means string boolean args (e.g. keep-setup-py=\"false\") "
57+
f"were not coerced to real booleans before being passed to pygen. "
58+
f"See eng/scripts/setup/run_batch.py."
59+
)
60+
assert not has_setup_py, (
61+
f"{flavor}/{pkg_dir.name} has setup.py but should use pyproject.toml. "
62+
f"This usually means string boolean args (e.g. keep-setup-py=\"false\") "
63+
f"were not coerced to real booleans before being passed to pygen. "
64+
f"See eng/scripts/setup/run_batch.py."
65+
)

0 commit comments

Comments
 (0)