Skip to content
Merged
Show file tree
Hide file tree
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/publish_to_pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
pip install build setuptools wheel twine
- name: Determine version from git tag
id: version
run: echo "tag=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,5 @@ tests/approved_files/VerifyTests.test_verify_automatic_approval.approved.txt
junit-reports/TEST-results.xml

.ignore/

/setup.py
1 change: 1 addition & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ exclude = (?x)(
^build/ |
^dist/ |
^setup/ |
^setup\.py$ |
^\.tox/ |
^\.venv/ |
^venv.*/
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
1 change: 1 addition & 0 deletions requirements.dev.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
-r requirements.prod.txt
-r requirements.test.txt
build
ruff
setuptools
mypy
Expand Down
4 changes: 3 additions & 1 deletion setup/publish_approval_utilities.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/bin/sh

python setup/setup.approval_utilities.py sdist bdist_wheel
cp setup/setup.approval_utilities.py setup.py
python -m build .
rm setup.py
twine upload --repository-url ${TWINE_REPOSITORY_URL} dist/*
rm -r dist
6 changes: 4 additions & 2 deletions setup/publish_approvaltests.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#! /bin/sh
#!/bin/sh

python setup/setup.publish.py sdist bdist_wheel
cp setup/setup.publish.py setup.py
python -m build .
rm setup.py
twine upload --repository-url ${TWINE_REPOSITORY_URL} dist/*
rm -r dist
6 changes: 4 additions & 2 deletions setup/publish_minimal.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#! /bin/sh
#!/bin/sh

python setup/setup.minimal.py sdist bdist_wheel
cp setup/setup.minimal.py setup.py
python -m build .
rm setup.py
twine upload --repository-url ${TWINE_REPOSITORY_URL} dist/*
rm -r dist
9 changes: 7 additions & 2 deletions setup/setup.approval_utilities.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import sys
from pathlib import Path
from typing import Any, Dict

from setup_utils import get_version
from setuptools import find_packages, setup

_setup_dir = Path(__file__).resolve().parent / "setup"
if _setup_dir.is_dir():
sys.path.insert(0, str(_setup_dir))
from setup_utils import get_version # pylint: disable=wrong-import-position

requires: Dict[str, Any] = {}
setup(
name="approval_utilities",
Expand Down
6 changes: 6 additions & 0 deletions setup/setup.minimal.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import sys
from pathlib import Path

_setup_dir = Path(__file__).resolve().parent / "setup"
if _setup_dir.is_dir():
sys.path.insert(0, str(_setup_dir))
from setup_utils import do_the_setup, get_requirements_from_file

required = get_requirements_from_file("../requirements.prod.required.txt")
Expand Down
8 changes: 6 additions & 2 deletions setup/setup.publish.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from setup_utils import get_requirements_from_file, get_version
import sys
from pathlib import Path

from setup import do_the_setup
_setup_dir = Path(__file__).resolve().parent / "setup"
if _setup_dir.is_dir():
sys.path.insert(0, str(_setup_dir))
from setup_utils import do_the_setup, get_requirements_from_file, get_version

required = get_requirements_from_file("../requirements.prod.required.txt")
required += get_requirements_from_file("../requirements.prod.extras.txt")
Expand Down
11 changes: 0 additions & 11 deletions setup/setup.py

This file was deleted.

51 changes: 36 additions & 15 deletions test__mypy_accepts_our_packages.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,38 @@
import glob
import pathlib
import shutil
import subprocess
import sys
import tempfile
import time
import typing

from version import version_number


def main() -> None:
for package_name, setup_file in [
("approval_utilities", "setup/setup.approval_utilities.py"),
("approvaltests", "setup/setup.py"),
("approvaltests", "setup/setup.publish.py"),
]:
build_number = str(int(time.time()))
_run_python_checked(
[
setup_file,
"--quiet",
"bdist_wheel",
"--build-number",
build_number,
]
)
print(f"Testing build {package_name} ...")
dist_dir = pathlib.Path("dist")
if dist_dir.exists():
shutil.rmtree(dist_dir)

shutil.copy2(setup_file, "setup.py")
try:
_run_python_checked(["-m", "build", "--wheel", "."], quiet=True)
finally:
_unlink_with_retry(pathlib.Path("setup.py"))

wheel_files = glob.glob("dist/*.whl")
assert len(wheel_files) == 1, f"Expected 1 wheel, found {wheel_files}"
Comment on lines +27 to +28
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Also assert that the wheel belongs to the expected package, not just that there is exactly one wheel.

As written, this will pass as long as there’s exactly one wheel in dist/, even if it’s for a different package. To make the test safer, also assert that the wheel filename matches the expected package name, e.g. Path(wheel_files[0]).name.startswith(f"{package_name}-"), so mismatches between the built wheel and the package under test are caught.

_run_python_checked(
[
"-m",
"pip",
"install",
"--force-reinstall",
f"dist/{package_name}-{version_number}-{build_number}-py3-none-any.whl",
wheel_files[0],
"--quiet",
"--no-warn-script-location",
]
Expand All @@ -47,14 +50,32 @@ def main() -> None:


def _run_python_checked(
args: typing.List[str], cwd: typing.Optional[pathlib.Path] = None
args: typing.List[str],
cwd: typing.Optional[pathlib.Path] = None,
quiet: bool = False,
) -> None:
subprocess.run(
[sys.executable, *args],
check=True,
cwd=cwd,
stdout=subprocess.DEVNULL if quiet else None,
Comment on lines 52 to +61
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Quiet mode hides build output, which can make diagnosing failing packaging tests difficult.

Using quiet=True here suppresses both stdout and stderr, so if the build fails in CI you lose the error details needed to debug packaging issues. Consider keeping stderr visible (or redirecting it to a log file) when quiet is enabled, or only applying quiet to the subsequent pip install step so failures remain diagnosable.

Suggested implementation:

        # Suppress only stdout in quiet mode so build / packaging errors remain visible
        stdout=subprocess.DEVNULL if quiet else None,
        stderr=None,

If any callers relied on stderr being suppressed by quiet=True, they may need to be updated to handle visible error output now (for example, by explicitly redirecting or capturing stderr at the call site if necessary).

stderr=subprocess.DEVNULL if quiet else None,
)


def _unlink_with_retry(
path: pathlib.Path, retries: int = 5, delay: float = 1.0
) -> None:
for attempt in range(retries):
try:
path.unlink(missing_ok=True)
return
except PermissionError:
if attempt < retries - 1:
time.sleep(delay)
else:
raise


if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions tidy_code.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
set -euo pipefail

mise task --quiet run tidy_code
git add --renormalize .
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Be cautious about staging all files from within a tidy script.

git add --renormalize . will stage all tracked files, not just those affected by this tidy run, which can lead to accidentally committing unrelated changes (e.g., widespread line-ending updates). If you only want to normalize a subset of paths, consider limiting the command to specific directories or omitting git add here and leaving staging to the caller.