Skip to content

Commit d7c6e29

Browse files
scripts: add script to check pypi classifiers
1 parent c600bc8 commit d7c6e29

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

scripts/check_classifiers.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import re
2+
import sys
3+
import urllib.request
4+
from pathlib import Path
5+
6+
# Step 1: Get pyproject.toml path from args
7+
if len(sys.argv) != 2:
8+
print(f"Usage: {sys.argv[0]} path/to/pyproject.toml", file=sys.stderr)
9+
sys.exit(1)
10+
11+
pyproject_path = Path(sys.argv[1])
12+
if not pyproject_path.is_file():
13+
print(f"File not found: {pyproject_path}", file=sys.stderr)
14+
sys.exit(1)
15+
16+
# Step 1: Download the official Trove classifier list
17+
url = "https://pypi.org/pypi?%3Aaction=list_classifiers"
18+
with urllib.request.urlopen(url) as response:
19+
trove_classifiers = {line.decode("utf-8").strip() for line in response}
20+
21+
# Step 2: Extract classifiers from pyproject.toml
22+
with open(pyproject_path) as f:
23+
content = f.read()
24+
25+
match = re.search(r"classifiers\s*=\s*\[([^\]]*)\]", content, re.MULTILINE | re.DOTALL)
26+
if not match:
27+
print("No 'classifiers' block found in pyproject.toml", file=sys.stderr)
28+
sys.exit(1)
29+
30+
raw_block = match.group(1)
31+
classifiers = [c.strip(" \"'\n") for c in raw_block.split(",") if c.strip()]
32+
33+
# Step 3: Check for invalid classifiers
34+
invalid = [c for c in classifiers if c not in trove_classifiers]
35+
36+
if invalid:
37+
print("❌ Invalid classifiers:")
38+
for c in invalid:
39+
print(f" - {c}")
40+
print("Valid classifiers:")
41+
for c in sorted(trove_classifiers):
42+
print(f" - {c}")
43+
sys.exit(1)
44+
else:
45+
print("✅ All classifiers are valid.")

0 commit comments

Comments
 (0)