| import argparse |
| import re |
| import sys |
| import tomllib |
| from pathlib import Path |
| |
| |
| class ValidationError(Exception): |
| pass |
| |
| |
| def check(github_ref: str | None) -> None: |
| pyproject = Path(__file__).parent.parent / "pyproject.toml" |
| if not pyproject.exists(): |
| raise ValidationError("pyproject.toml not found") |
| with pyproject.open("rb") as f: |
| data = tomllib.load(f) |
| pyproject_version = data["project"]["version"] |
| |
| if github_ref is not None and github_ref.startswith("refs/tags/"): |
| version = github_ref.removeprefix("refs/tags/") |
| if version != pyproject_version: |
| raise ValidationError( |
| f"Version mismatch: GitHub ref is {version}, " |
| f"but pyproject.toml is {pyproject_version}" |
| ) |
| |
| requires_python = data["project"]["requires-python"] |
| assert sys.version_info[0] == 3, "Rewrite this script when Python 4 comes out" |
| match = re.fullmatch(r">=3\.(\d+)", requires_python) |
| if not match: |
| raise ValidationError(f"Invalid requires-python: {requires_python!r}") |
| lowest_minor = int(match.group(1)) |
| |
| description = data["project"]["description"] |
| if not description.endswith(f"3.{lowest_minor}+"): |
| raise ValidationError(f"Description should mention Python 3.{lowest_minor}+") |
| |
| classifiers = set(data["project"]["classifiers"]) |
| for should_be_supported in range(lowest_minor, sys.version_info[1] + 1): |
| if ( |
| f"Programming Language :: Python :: 3.{should_be_supported}" |
| not in classifiers |
| ): |
| raise ValidationError( |
| f"Missing classifier for Python 3.{should_be_supported}" |
| ) |
| |
| |
| if __name__ == "__main__": |
| parser = argparse.ArgumentParser("Script to check the package metadata") |
| parser.add_argument( |
| "github_ref", type=str, help="The current GitHub ref", nargs="?" |
| ) |
| args = parser.parse_args() |
| try: |
| check(args.github_ref) |
| except ValidationError as e: |
| print(e) |
| sys.exit(1) |