chore: import upstream snapshot with attribution
build container image / cpu (push) Waiting to run
build container image / cuda (push) Waiting to run
build container image / rocm (push) Waiting to run
frontend tests / frontend-tests (push) Waiting to run
openapi checks / openapi-checks (push) Waiting to run
python tests / py3.12: macos-default (push) Waiting to run
python tests / py3.11: windows-cpu (push) Waiting to run
python tests / py3.12: windows-cpu (push) Waiting to run
python tests / py3.11: linux-cpu (push) Waiting to run
python tests / py3.12: linux-cpu (push) Waiting to run
typegen checks / typegen-checks (push) Waiting to run
uv lock checks / uv-lock-checks (push) Waiting to run
frontend checks / frontend-checks (push) Waiting to run
lfs checks / lfs-check (push) Waiting to run
python checks / python-checks (push) Waiting to run
python tests / py3.11: macos-default (push) Waiting to run
docs / deploy (push) Has been cancelled
docs / changes (push) Has been cancelled
docs / check-and-build (push) Has been cancelled
build container image / cpu (push) Waiting to run
build container image / cuda (push) Waiting to run
build container image / rocm (push) Waiting to run
frontend tests / frontend-tests (push) Waiting to run
openapi checks / openapi-checks (push) Waiting to run
python tests / py3.12: macos-default (push) Waiting to run
python tests / py3.11: windows-cpu (push) Waiting to run
python tests / py3.12: windows-cpu (push) Waiting to run
python tests / py3.11: linux-cpu (push) Waiting to run
python tests / py3.12: linux-cpu (push) Waiting to run
typegen checks / typegen-checks (push) Waiting to run
uv lock checks / uv-lock-checks (push) Waiting to run
frontend checks / frontend-checks (push) Waiting to run
lfs checks / lfs-check (push) Waiting to run
python checks / python-checks (push) Waiting to run
python tests / py3.11: macos-default (push) Waiting to run
docs / deploy (push) Has been cancelled
docs / changes (push) Has been cancelled
docs / check-and-build (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import re
|
||||
import sys
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
# This script checks the classifiers in a pyproject.toml file against the official Trove classifier list.
|
||||
# If the classifiers are invalid, PyPI will reject the package upload.
|
||||
|
||||
# Step 1: Get pyproject.toml path from args
|
||||
if len(sys.argv) != 2:
|
||||
print(f"Usage: {sys.argv[0]} path/to/pyproject.toml", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
pyproject_path = Path(sys.argv[1])
|
||||
if not pyproject_path.is_file():
|
||||
print(f"File not found: {pyproject_path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Step 1: Download the official Trove classifier list
|
||||
url = "https://pypi.org/pypi?%3Aaction=list_classifiers"
|
||||
with urllib.request.urlopen(url) as response:
|
||||
trove_classifiers = {line.decode("utf-8").strip() for line in response}
|
||||
|
||||
# Step 2: Extract classifiers from pyproject.toml
|
||||
with open(pyproject_path) as f:
|
||||
content = f.read()
|
||||
|
||||
match = re.search(r"classifiers\s*=\s*\[([^\]]*)\]", content, re.MULTILINE | re.DOTALL)
|
||||
if not match:
|
||||
print("No 'classifiers' block found in pyproject.toml", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
raw_block = match.group(1)
|
||||
classifiers = [c.strip(" \"'\n") for c in raw_block.split(",") if c.strip()]
|
||||
|
||||
# Step 3: Check for invalid classifiers
|
||||
invalid = [c for c in classifiers if c not in trove_classifiers]
|
||||
|
||||
if invalid:
|
||||
print("❌ Invalid classifiers:")
|
||||
for c in invalid:
|
||||
print(f" - {c}")
|
||||
print("Valid classifiers:")
|
||||
for c in sorted(trove_classifiers):
|
||||
print(f" - {c}")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("✅ All classifiers are valid.")
|
||||
Reference in New Issue
Block a user