Skip to content

Commit 194dfff

Browse files
authored
Invalid classifiers check (#4)
* Add InvalidClassifier exception, better tests * Make tests more clear * Don't allow private classifiers * Don't allow classifiers that start/end with whitespace * Don't allow classifiers that contain colons * Remove unnecessary import * Fix imports
1 parent d35933f commit 194dfff

File tree

7 files changed

+65
-15
lines changed

7 files changed

+65
-15
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ BINDIR = $(PWD)/.state/env/bin
1111
$(BINDIR)/python -m pip install -r requirements/dev.txt
1212

1313
build: .state/env/pyvenv.cfg
14-
$(BINDIR)/python _internal/generator.py
14+
$(BINDIR)/python -m _internal.generator
1515

1616
test: .state/env/pyvenv.cfg
1717
$(BINDIR)/pytest
1818
$(eval TMPDIR := $(shell mktemp -d))
19-
$(BINDIR)/python _internal/generator.py --output $(TMPDIR)/test.py
19+
$(BINDIR)/python -m _internal.generator --output $(TMPDIR)/test.py
2020
diff trove_classifiers/__init__.py $(TMPDIR)/test.py
2121

2222
lint: .state/env/pyvenv.cfg

_internal/classifiers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from models import ClassifierRoot, ClassifierNode
1+
from .models import ClassifierRoot, ClassifierNode
22

33
classifiers = ClassifierRoot(
44
children=[

_internal/exceptions.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class InvalidClassifier(Exception):
2+
pass

_internal/generator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from jinja2 import Template
66

7-
from classifiers import classifiers
7+
from .classifiers import classifiers
88

99
parser = argparse.ArgumentParser()
1010
parser.add_argument(

_internal/models.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from .exceptions import InvalidClassifier
2+
3+
14
class ClassifierRoot:
25
def __init__(self, children):
36
self.children = children
@@ -23,10 +26,21 @@ def __init__(
2326
skip=False,
2427
):
2528
if deprecated_by and not deprecated:
26-
raise Exception(
29+
raise InvalidClassifier(
2730
"Using deprecated_by, but not marking the classifier as deprecated"
2831
)
2932

33+
if short_name.lower().startswith("private"):
34+
raise InvalidClassifier("Classifiers starting with 'Private' are invalid")
35+
36+
if short_name.strip().rstrip() != short_name:
37+
raise InvalidClassifier(
38+
"Classifiers starting or ending with whitespace are invalid"
39+
)
40+
41+
if ":" in short_name:
42+
raise InvalidClassifier("Classifiers containing ':' are invalid")
43+
3044
self.short_name = short_name
3145
self.prefix_list = []
3246
self.deprecated = deprecated

setup.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
from setuptools import setup, find_packages
55

6-
from trove_classifiers import classifiers
7-
86
here = path.abspath(path.dirname(__file__))
97

108
# Get the long description from the README file

tests/test_classifiers.py

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22

33
from _internal.models import ClassifierRoot, ClassifierNode
4+
from _internal.exceptions import InvalidClassifier
45

56

67
def test_nested_prefixes():
@@ -13,10 +14,10 @@ def test_nested_prefixes():
1314
]
1415
)
1516

16-
assert root.generate() == [
17-
ClassifierNode("Foo"),
18-
ClassifierNode("Foo :: Bar"),
19-
ClassifierNode("Foo :: Bar :: Baz"),
17+
assert [node.full_name for node in root.generate()] == [
18+
"Foo",
19+
"Foo :: Bar",
20+
"Foo :: Bar :: Baz",
2021
]
2122

2223

@@ -31,12 +32,47 @@ def test_skip():
3132
]
3233
)
3334

34-
assert root.generate() == [
35-
ClassifierNode("Foo :: Bar"),
36-
ClassifierNode("Foo :: Bar :: Baz"),
35+
assert [node.full_name for node in root.generate()] == [
36+
"Foo :: Bar",
37+
"Foo :: Bar :: Baz",
3738
]
3839

3940

4041
def test_bad_deprecation_failure():
41-
with pytest.raises(Exception):
42+
with pytest.raises(InvalidClassifier) as excinfo:
4243
ClassifierNode("blah", deprecated_by=["spam"])
44+
45+
assert excinfo.value.args == (
46+
"Using deprecated_by, but not marking the classifier as deprecated",
47+
)
48+
49+
50+
@pytest.mark.parametrize(
51+
"parent, child",
52+
[("Private", "Foo"), ("private", "Foo"), ("Foo", "Private"), ("Foo", "private"),],
53+
)
54+
def test_private_classifier_failure(parent, child):
55+
with pytest.raises(InvalidClassifier) as excinfo:
56+
ClassifierNode(
57+
parent, children=[ClassifierNode(child)],
58+
)
59+
60+
assert excinfo.value.args == ("Classifiers starting with 'Private' are invalid",)
61+
62+
63+
@pytest.mark.parametrize("classifier", [" Foo", "Foo "])
64+
def test_whitespace_classifier_failure(classifier):
65+
with pytest.raises(InvalidClassifier) as excinfo:
66+
ClassifierNode(classifier)
67+
68+
assert excinfo.value.args == (
69+
"Classifiers starting or ending with whitespace are invalid",
70+
)
71+
72+
73+
@pytest.mark.parametrize("classifier", ["Foo:", "Foo :: Bar"])
74+
def test_colon_classifier_failure(classifier):
75+
with pytest.raises(InvalidClassifier) as excinfo:
76+
ClassifierNode(classifier)
77+
78+
assert excinfo.value.args == ("Classifiers containing ':' are invalid",)

0 commit comments

Comments
 (0)