Skip to content

Commit 6a17973

Browse files
author
notactuallyfinn
committed
added tests for two functions and fixed the bugs that were found
1 parent a3396d7 commit 6a17973

File tree

2 files changed

+80
-60
lines changed

2 files changed

+80
-60
lines changed

src/hermes_toml/harvest.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,9 @@ def handle_pypi_classifieres(cls, classifiers: str | list[str], data):
354354
if isinstance(classifiers, str):
355355
classifiers = [classifiers]
356356

357+
# remove duplicates
358+
classifiers = list(set(classifiers))
359+
357360
sorted_classifiers = {
358361
"schema:targetProduct": [], "schema:audience": [], "schema:license": [],
359362
"schema:inLanguage": [], "schema:programming Language": [], "schema:about": []
@@ -365,32 +368,33 @@ def handle_pypi_classifieres(cls, classifiers: str | list[str], data):
365368
classifier = classifier.split(" :: ")
366369
if len(classifier) < 2:
367370
continue
368-
if classifier[0] == "Operating System":
369-
temp = {"@type": "SoftwareApplication", "name": classifier[-1]}
371+
if (classifier[0] == "Operating System" and
372+
not (len(classifier) == 2 and classifier[1] == "Microsoft")):
373+
temp = {"@type": "schema:SoftwareApplication", "schema:name": classifier[-1]}
370374
sorted_classifiers["schema:targetProduct"].append(temp)
371375
elif classifier[0] == "Intended Audience":
372-
temp = {"@type": "Audience", "name": classifier[-1]}
376+
temp = {"@type": "schema:Audience", "schema:name": classifier[-1]}
373377
sorted_classifiers["schema:audience"].append(temp)
374378
elif (classifier[0] == "License" and
375379
not (classifier[1] == "OSI Approved" and len(classifier) == 2)):
376-
temp = {"@type": "CreativeWork", "name": classifier[-1]}
380+
temp = {"@type": "schema:CreativeWork", "schema:name": classifier[-1]}
377381
sorted_classifiers["schema:license"].append(temp)
378382
elif classifier[0] == "Natural Language":
379383
sorted_classifiers["schema:inLanguage"].append(classifier[-1])
380384
elif classifier[0] == "Programming Language":
381385
if classifier[1] == "Python" and len(classifier) > 2:
382-
if classifier[2].isdecimal():
383-
temp = f"Python {classifier[2]}"
384-
elif classifier[2] == "Free Threading":
386+
if classifier[2] == "Free Threading":
385387
temp = "Python Free Threading" \
386388
f"{f' {classifier[3]}' if len(classifier) > 3 else ''}"
387389
elif classifier[2] == "Implementation":
388390
temp = classifier[3] if len(classifier) > 3 else "Python Implementation"
391+
else:
392+
temp = f"Python {classifier[2]}"
389393
sorted_classifiers["schema:programming Language"].append(temp)
390394
else:
391395
sorted_classifiers["schema:programming Language"].append(classifier[-1])
392396
elif classifier[0] == "Topic":
393-
temp = {"@type": "Thing", "name": " ".join(classifier[1:])}
397+
temp = {"@type": "schema:Thing", "schema:name": " ".join(classifier[1:])}
394398
sorted_classifiers["schema:about"].append(temp)
395399

396400
# add everything to the SoftwareMetadata object
@@ -432,7 +436,7 @@ def handle_urls(cls, urls: dict[str, str], data):
432436
# iterate over the dictionaries items and add the url to the correct bucket
433437
# if the key hints it to be the right one
434438
for name, url in urls.items():
435-
if not (isinstance(name, str) and isinstance(url, str)):
439+
if (not (isinstance(name, str) and isinstance(url, str))) or url == "":
436440
continue
437441
name = name.lower()
438442
if name.find("code") != -1 or name.find("repository") != -1:
@@ -450,6 +454,7 @@ def handle_urls(cls, urls: dict[str, str], data):
450454

451455
# add everything to the SoftwareMetadata object
452456
for key, value in sorted_urls.items():
457+
value = list(set(value))
453458
if len(value) > 1:
454459
data[key] = value
455460
elif len(value) == 1:

test/hermes_toml_test/test_harvest.py

Lines changed: 66 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,64 +7,79 @@
77

88
import pytest
99
import toml
10+
from pytest_unordered import unordered
1011
from hermes_toml.harvest import TomlHarvestPlugin
1112

1213
@pytest.mark.parametrize("in_data, out_data", [
13-
({"givenName": "Tom"}, {"givenName": "Tom"}), ({"a": "b"}, {}),
14-
({"givenName": "Tom","a": "b"}, {"givenName": "Tom"}), ({}, {})
14+
({}, {}), (None, {}), ("", {}), (1, {}), ([], {}), ({1:""}, {}), ({None:""}, {}),
15+
({1:"", None:""}, {}), ({"a":[]}, {}), ({"a":None}, {}), ({"a":1}, {}), ({"a":{}}, {}),
16+
({"a":1, "b":None}, {}), ({"a":""}, {}), ({"a":"b"}, {"relatedLink":"b"}),
17+
({"a":"b", "b":None}, {"relatedLink":"b"}), ({"code": "a"}, {"schema:codeRepository": "a"}),
18+
({"a":"b", "b":"c"}, {"relatedLink":unordered(["b", "c"])}),
19+
({"codeRepository": "a"}, {"schema:codeRepository": "a"}),
20+
({"repository": "a"}, {"schema:codeRepository": "a"}),
21+
({"code": "a", "repository":"b"}, {"schema:codeRepository": unordered(["a", "b"])}),
22+
({"code": "a", "repository":"a"}, {"schema:codeRepository": "a"}),
23+
({"buildInstructions": "a"}, {"buildInstructions": "a"}),
24+
({"IssueTracker": "a"}, {"IssueTracker": "a"}), ({"readme": "a"}, {"readme": "a"}),
25+
({"discussion": "a"}, {"schema:discussionURL": "a"}),
26+
({"readme":"a","code":"b","homepage":"c"},
27+
{"readme":"a","schema:codeRepository":"b","relatedLink":"c"}),
28+
({"readme":"a","code":"b","homepage":"c", "mymistake":"c"},
29+
{"readme":"a","schema:codeRepository":"b","relatedLink":"c"}),
30+
({"readme":"a","code":"b","homepage":"c", "mypage":"d"},
31+
{"readme":"a","schema:codeRepository":"b","relatedLink":unordered(["c", "d"])})
1532
])
16-
def test_remove_forbidden_keys(in_data, out_data):
17-
assert TomlHarvestPlugin.remove_forbidden_keys(in_data) == out_data
33+
def test_handle_urls(in_data, out_data):
34+
data = {}
35+
TomlHarvestPlugin.handle_urls(in_data, data)
36+
assert data == out_data
1837

1938
@pytest.mark.parametrize("in_data, out_data", [
20-
({"givenName": "Tom"}, {"givenName": "Tom"}), ({"a": "b"}, {}),
21-
({"givenName": "Tom","a": "b"}, {"givenName": "Tom"}), ({}, {}),
22-
([{"givenName": "Tom"}], [{"givenName": "Tom"}]),
23-
([{"givenName": "Tom"}, {"a": "b"}], [{"givenName": "Tom"}]),
24-
([{}, {"givenName": "Tom"}, {"a": "b"}], [{"givenName": "Tom"}]),
25-
([{}], []), ([{"b":"c"}], []), ([], [])
39+
(1, {}), ({}, {}), ("", {}), ([], {}), ([""], {}), (["", ""], {}), ([1], {}),
40+
("Development Status :: xxx", {}), ("Environment :: xxx", {}), ("Framework :: xxx", {}),
41+
("Intended Audience :: xxx", {"schema:audience": {"@type": "schema:Audience", "schema:name": "xxx"}}),
42+
("License :: xxx", {"schema:license": {"@type": "schema:CreativeWork", "schema:name": "xxx"}}),
43+
("License :: OSI Approved", {}), ("Operating System :: Microsoft", {}),
44+
("License :: OSI Approved :: xxx", {"schema:license": {"@type": "schema:CreativeWork", "schema:name": "xxx"}}),
45+
("Natural Language :: xxx", {"schema:inLanguage": "xxx"}),
46+
("Operating System :: xxx", {"schema:targetProduct": {"@type": "schema:SoftwareApplication", "schema:name": "xxx"}}),
47+
("Operating System :: x :: xxx", {"schema:targetProduct": {"@type": "schema:SoftwareApplication", "schema:name": "xxx"}}),
48+
("Operating System :: x :: x :: xxx", {"schema:targetProduct": {"@type": "schema:SoftwareApplication", "schema:name": "xxx"}}),
49+
("Operating System :: Microsoft :: xxx", {"schema:targetProduct": {"@type": "schema:SoftwareApplication", "schema:name": "xxx"}}),
50+
("Programming Language :: xxx", {"schema:programming Language": "xxx"}),
51+
(["Programming Language :: xxx", 1], {"schema:programming Language": "xxx"}),
52+
("Programming Language :: Python :: xxx", {"schema:programming Language": "Python xxx"}),
53+
("Programming Language :: Python :: x :: only", {"schema:programming Language": "Python x"}),
54+
("Programming Language :: Python :: Free Threading :: xxx", {"schema:programming Language": "Python Free Threading xxx"}),
55+
("Programming Language :: Python :: Implementation :: x", {"schema:programming Language": "x"}),
56+
("Topic :: a", {"schema:about": {"@type": "schema:Thing", "schema:name": "a"}}),
57+
("Topic :: a :: b", {"schema:about": {"@type": "schema:Thing", "schema:name": "a b"}}),
58+
("Topic :: a :: b :: c", {"schema:about": {"@type": "schema:Thing", "schema:name": "a b c"}}),
59+
("Topic :: a :: b :: c :: d", {"schema:about": {"@type": "schema:Thing", "schema:name": "a b c d"}}),
60+
(["Natural Language :: xxx", "Natural Language :: xxx"], {"schema:inLanguage": "xxx"}),
61+
(["Natural Language :: xxx", "Natural Language :: yyy"], {"schema:inLanguage": unordered(["xxx", "yyy"])}),
62+
(["Natural Language :: xxx", "Programming Language :: xxx"], {"schema:inLanguage": "xxx", "schema:programming Language": "xxx"}),
63+
(["Natural Language :: xxx", "Programming Language :: xxx", "Programming Language :: xxx"],
64+
{"schema:inLanguage": "xxx", "schema:programming Language": "xxx"}),
65+
(["Natural Language :: xxx", "Programming Language :: xxx", "Programming Language :: yyy"],
66+
{"schema:inLanguage": "xxx", "schema:programming Language": unordered(["xxx", "yyy"])}),
67+
(["Topic :: a", "Topic :: b"], {"schema:about": unordered([{"@type": "schema:Thing", "schema:name": "a"}, {"@type": "schema:Thing", "schema:name": "b"}])}),
2668
])
27-
def test_handle_person(in_data, out_data):
28-
assert TomlHarvestPlugin.handle_person_in_unknown_format(in_data) == out_data
69+
def test_handle_pypi_classifiers(in_data, out_data):
70+
data = {}
71+
TomlHarvestPlugin.handle_pypi_classifieres(in_data, data)
72+
assert data == out_data
2973

30-
@pytest.mark.parametrize("in_data", [
31-
(15), ([{}, (15)]), (None)
32-
])
33-
def test_handle_person_with_error(in_data):
34-
with pytest.raises(ValueError):
35-
TomlHarvestPlugin.handle_person_in_unknown_format(in_data)
74+
"""
75+
Test-Cases:
76+
korrekte Eingabe:
77+
{"project": {"keywords": ["A", "B", "C"], "classifiers": ["Development Status :: 1 - Planning", "Environment :: Console"], "readme": {"text": "Test", content-type: "text/markdown"},
78+
"requires-python": ">=3.12", "name": "Test", "authors": [{"name": "Testi", "email": "testi@domain.de"}, {"name": "Test", "email": "test@otherdomain.com"}],
79+
"maintainers": [{"name": "Tester", "email": "tester@domain.com"}, {"name": "Testers", "email": "testers@otherdomain.de"}], "dependencies": ["scipy>=1.0", "numpy~=1.5"],
80+
"license": "MIT AND (Apache-2.0 OR BSD-2-Clause)", "urls": ["homepage": "mypage.org", "documentation": "mydocumentation.com"], "version": "1.5.2"
81+
}
82+
}
3683
37-
@pytest.fixture(scope="session")
38-
def toml_file(tmp_path_factory):
39-
fn = tmp_path_factory.mktemp("data") / "test.toml"
40-
return fn
4184
42-
@pytest.mark.parametrize("in_data, out_data", [
43-
({}, {}), ({"project": {"name":"a"}}, {"name": "a"}),
44-
({"tool": {"poetry": {"name":"a"}}}, {"name": "a"}),
45-
({"project":{"name":"a"}, "a":{"b":"c"}}, {"name":"a"}),
46-
({"project":{"name":"a", "requires-python":">3.7"}}, {"name":"a", "runtimePlatform":"Python >3.7"}),
47-
({"project":{"authors":{"givenName":"a"}}}, {"author":{"givenName":"a", "@type":"Person"}}),
48-
({"project":{"authors":[{"givenName":"a"}, {"givenName":"a"}]}}, {"author":[{"givenName":"a", "@type":"Person"}, {"givenName":"a", "@type":"Person"}]}),
49-
({"project":{"authors":{"givenName":"a", "a":"b"}}}, {"author":{"givenName":"a", "@type":"Person"}}),
50-
({"project":{"authors":{"a":"b"}}}, {}),
51-
({"project":{"authors":[{"a":"a"}, {"givenName":"a"}]}}, {"author":{"givenName":"a", "@type":"Person"}}),
52-
({"project":{"authors":[{"a":"b"}]}}, {}),
53-
({"project":{"authors":["abc def<abc.def@dlr.com>"]}}, {"author":{"name":"abc def", "email": "abc.def@dlr.com", "@type": "Person"}}),
54-
({"project":{"authors":"abc def<abc.def@dlr.com>"}}, {"author":{"name":"abc def", "email": "abc.def@dlr.com", "@type": "Person"}})
55-
])
56-
def test_read_from_toml(in_data, out_data, toml_file):
57-
toml.dump(in_data, open(toml_file, "w", encoding="utf8"))
58-
assert TomlHarvestPlugin.read_from_toml(str(toml_file)) == out_data
59-
60-
@pytest.mark.parametrize("in_data", [
61-
({"project": {"authors":1}}), ({"tool": {"poetry": {"authors":1}}}),
62-
({"project": {"authors":[1]}}), ({"tool": {"poetry": {"authors":[1]}}}),
63-
({"project": {"name":"a"}, "tool": {"poetry": {"name":"a"}}}),
64-
({"project": {"authors":["as<as>as"]}}),
65-
({"project": {"authors":"as<as>as"}})
66-
])
67-
def test_read_from_toml_with_error(in_data, toml_file):
68-
toml.dump(in_data, open(toml_file, "w", encoding="utf8"))
69-
with pytest.raises(ValueError):
70-
TomlHarvestPlugin.read_from_toml(str(toml_file))
85+
"""

0 commit comments

Comments
 (0)