Skip to content

Commit 7e23949

Browse files
authored
relax new contribution validation, with tests (#95)
1 parent 4b5a22f commit 7e23949

11 files changed

+698
-15
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
**/__pycache__/

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,15 @@ contribution. These files are created from the database using the script `script
7777
The Processing application's contribution manager reads in a `contribs.txt` file.
7878
This file is created from the database using the script `scripts/to_contribs_txt.py`.
7979

80+
These artifacts are created and released via Github Actions.
81+
82+
## Contributing
83+
84+
Thanks for your interest in contributing to this repository.
85+
The scripts are currently written in Python.
86+
87+
Because much of this repository is workflows and automation, we recommend to run the workflows on your fork before
88+
creating pull requests.
8089

8190
## Contributors
8291

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
ruamel.yaml
22
tenacity~=9.0.0
33
requests~=2.32.3
4-
pydantic~=2.9.2
4+
pydantic~=2.11
55
javaproperties~=0.8.2
6+
pytest

scripts/__init__.py

Whitespace-only changes.

scripts/parse_and_validate_properties_txt.py

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
Reads a properties txt file from a library's release artifacts,
33
and validates the contents. If valid, it returns the contents
44
as an object.
5-
6-
TODO: write tests for validation
75
"""
86
import json
97
import argparse
@@ -13,38 +11,32 @@
1311
import re
1412
import os
1513
from typing import Optional, Union
16-
from pydantic import BaseModel, Field, ConfigDict, field_validator
14+
from pydantic import BaseModel, Field, ConfigDict, field_validator, AliasChoices
1715
import javaproperties as jp
1816

1917

18+
2019
class PropertiesBase(BaseModel):
2120
name: str
22-
authors: str
21+
authors: str = Field(validation_alias=AliasChoices('authors','authorList'))
2322
url: str
24-
categories: Optional[str] = Field(None)
23+
categories: Optional[str] = Field(None, validation_alias=AliasChoices('categories','category'))
2524
sentence: str
2625
paragraph: Optional[str] = None
2726
version: int
2827
prettyVersion: str
2928
minRevision: int = Field(0)
3029
maxRevision: int = Field(0)
31-
modes: Optional[str] = Field(None, alias='compatibleModesList')
30+
modes: Optional[str] = Field(None, validation_alias=AliasChoices('modes','compatibleModesList'))
3231

3332
model_config = ConfigDict(
3433
extra='allow',
3534
)
3635

3736
class PropertiesExisting(PropertiesBase):
38-
authors: str = Field(alias='authorList')
39-
categories: Optional[str] = Field(None, alias='category')
4037
version: Union[int, str]
4138
prettyVersion: Optional[str] = None
4239

43-
model_config = ConfigDict(
44-
extra='allow',
45-
populate_by_name=True,
46-
)
47-
4840
@field_validator('minRevision', 'maxRevision', mode='before')
4941
def default_on_error(cls, v):
5042
if v.isdigit():
@@ -54,7 +46,7 @@ def default_on_error(cls, v):
5446

5547

5648
class LibraryPropertiesNew(PropertiesBase):
57-
categories: str
49+
categories: str = Field(validation_alias=AliasChoices('categories','category'))
5850

5951

6052
@retry(stop=stop_after_attempt(3),

tests/__init__.py

Whitespace-only changes.

tests/unit/__init__.py

Whitespace-only changes.

tests/unit/conftest.py

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import pytest
2+
3+
4+
# Test Fixtures
5+
@pytest.fixture
6+
def valid_properties_data():
7+
"""Complete valid data for PropertiesExisting"""
8+
return {
9+
"name": "Test Library",
10+
"authors": "John Doe, Jane Smith",
11+
"url": "https://example.com/library",
12+
"categories": "utility,helper",
13+
"sentence": "A helpful test library for demonstrations",
14+
"paragraph": "This is a more detailed description of the test library.",
15+
"version": "1",
16+
"prettyVersion": "1.0.0",
17+
"minRevision": "5",
18+
"maxRevision": "10",
19+
"modes": "standard,debug"
20+
}
21+
22+
23+
@pytest.fixture
24+
def valid_properties_data_aliases():
25+
"""Complete valid data for PropertiesExisting"""
26+
return {
27+
"name": "Test Library",
28+
"authorList": "John Doe, Jane Smith",
29+
"url": "https://example.com/library",
30+
"category": "utility,helper",
31+
"sentence": "A helpful test library for demonstrations",
32+
"paragraph": "This is a more detailed description of the test library.",
33+
"version": "1",
34+
"prettyVersion": "1.0.0",
35+
"minRevision": "5",
36+
"maxRevision": "10",
37+
"compatibleModesList": "standard,debug"
38+
}
39+
40+
41+
@pytest.fixture
42+
def minimal_properties_base_data():
43+
"""Minimal required data for PropertiesExisting"""
44+
return {
45+
"name": "Minimal Library",
46+
"authors": "Test Author",
47+
"url": "https://minimal.com",
48+
"sentence": "A minimal test case",
49+
"version": "1",
50+
"prettyVersion": "1.0"
51+
}
52+
53+
54+
@pytest.fixture
55+
def minimal_properties_base_data_aliases():
56+
"""Minimal required data for PropertiesExisting"""
57+
return {
58+
"name": "Minimal Library",
59+
"authorList": "Test Author",
60+
"url": "https://minimal.com",
61+
"sentence": "A minimal test case",
62+
"version": "1",
63+
"prettyVersion": "1.0"
64+
}
65+
66+
67+
@pytest.fixture
68+
def minimal_properties_existing_data():
69+
"""Minimal required data for PropertiesExisting"""
70+
return {
71+
"name": "Minimal Library",
72+
"authors": "Test Author",
73+
"url": "https://minimal.com",
74+
"sentence": "A minimal test case",
75+
"version": "1",
76+
}
77+
78+
79+
@pytest.fixture
80+
def minimal_properties_existing_data_aliases():
81+
"""Minimal required data for PropertiesExisting"""
82+
return {
83+
"name": "Minimal Library",
84+
"authorList": "Test Author",
85+
"url": "https://minimal.com",
86+
"sentence": "A minimal test case",
87+
"version": "1",
88+
}
89+
90+
91+
@pytest.fixture
92+
def minimal_properties_library_data():
93+
"""Minimal required data for PropertiesExisting"""
94+
return {
95+
"name": "Minimal Library",
96+
"authors": "Test Author",
97+
"url": "https://minimal.com",
98+
"categories": "minimal,library",
99+
"sentence": "A minimal test case",
100+
"version": "1",
101+
"prettyVersion": "1.0"
102+
}
103+
104+
105+
@pytest.fixture
106+
def minimal_properties_library_data_aliases():
107+
"""Minimal required data for PropertiesExisting"""
108+
return {
109+
"name": "Minimal Library",
110+
"authorList": "Test Author",
111+
"url": "https://minimal.com",
112+
"category": "minimal,library",
113+
"sentence": "A minimal test case",
114+
"version": "1",
115+
"prettyVersion": "1.0"
116+
}
117+
118+
119+
@pytest.fixture
120+
def properties_with_extra_fields():
121+
"""Data with extra fields (should be allowed due to extra='allow')"""
122+
return {
123+
"name": "Extra Fields Library",
124+
"authors": "Extra Author",
125+
"url": "https://extra.com",
126+
"categories": "extra,fields",
127+
"sentence": "Library with extra fields",
128+
"version": "2",
129+
"prettyVersion": "2.0",
130+
"customField": "custom value",
131+
"anotherExtra": "42"
132+
}

0 commit comments

Comments
 (0)