diff --git a/.github/workflows/publish_to_pypi.yml b/.github/workflows/publish_to_pypi.yml index 09b2c0e2..01a0a846 100644 --- a/.github/workflows/publish_to_pypi.yml +++ b/.github/workflows/publish_to_pypi.yml @@ -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 diff --git a/.gitignore b/.gitignore index 91d94902..cb13f8bf 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,5 @@ tests/approved_files/VerifyTests.test_verify_automatic_approval.approved.txt junit-reports/TEST-results.xml .ignore/ + +/setup.py diff --git a/mypy.ini b/mypy.ini index 1e082493..ef1a27ff 100644 --- a/mypy.ini +++ b/mypy.ini @@ -15,6 +15,7 @@ exclude = (?x)( ^build/ | ^dist/ | ^setup/ | + ^setup\.py$ | ^\.tox/ | ^\.venv/ | ^venv.*/ diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..9787c3bd --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" diff --git a/requirements.dev.txt b/requirements.dev.txt index 91eb4796..fd282d51 100644 --- a/requirements.dev.txt +++ b/requirements.dev.txt @@ -1,5 +1,6 @@ -r requirements.prod.txt -r requirements.test.txt +build ruff setuptools mypy diff --git a/setup/publish_approval_utilities.sh b/setup/publish_approval_utilities.sh index 4711d4a9..96a1a42f 100755 --- a/setup/publish_approval_utilities.sh +++ b/setup/publish_approval_utilities.sh @@ -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 diff --git a/setup/publish_approvaltests.sh b/setup/publish_approvaltests.sh index e3bf217e..82b931f6 100755 --- a/setup/publish_approvaltests.sh +++ b/setup/publish_approvaltests.sh @@ -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 diff --git a/setup/publish_minimal.sh b/setup/publish_minimal.sh index 28ddee00..60897c41 100755 --- a/setup/publish_minimal.sh +++ b/setup/publish_minimal.sh @@ -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 diff --git a/setup/setup.approval_utilities.py b/setup/setup.approval_utilities.py index ac16bf75..948ccd0a 100644 --- a/setup/setup.approval_utilities.py +++ b/setup/setup.approval_utilities.py @@ -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", diff --git a/setup/setup.minimal.py b/setup/setup.minimal.py index 920b4542..497d69f1 100644 --- a/setup/setup.minimal.py +++ b/setup/setup.minimal.py @@ -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") diff --git a/setup/setup.publish.py b/setup/setup.publish.py index 12255b2d..74d25e35 100644 --- a/setup/setup.publish.py +++ b/setup/setup.publish.py @@ -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") diff --git a/setup/setup.py b/setup/setup.py deleted file mode 100644 index 898b464f..00000000 --- a/setup/setup.py +++ /dev/null @@ -1,11 +0,0 @@ -from setup_utils import do_the_setup, get_requirements_from_file - -required = get_requirements_from_file("../requirements.prod.required.txt") -required += get_requirements_from_file("../requirements.prod.extras.txt") - -do_the_setup( - package_name="approvaltests", - package_description="Assertion/verification library to aid testing", - required=required, - extra_requires={}, -) diff --git a/test__mypy_accepts_our_packages.py b/test__mypy_accepts_our_packages.py index 8d01e931..ec46ddb7 100644 --- a/test__mypy_accepts_our_packages.py +++ b/test__mypy_accepts_our_packages.py @@ -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}" _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", ] @@ -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, + 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() diff --git a/tidy_code.sh b/tidy_code.sh index b040afdf..aba3c914 100755 --- a/tidy_code.sh +++ b/tidy_code.sh @@ -2,3 +2,4 @@ set -euo pipefail mise task --quiet run tidy_code +git add --renormalize .