Skip to content

Commit a98ad96

Browse files
committed
add pass_validation to each output and update tests
1 parent 37a0a9a commit a98ad96

16 files changed

Lines changed: 141 additions & 24 deletions

src/somesy/cff/writer.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def __init__(
1818
self,
1919
path: Path,
2020
create_if_not_exists: bool = True,
21+
pass_validation: bool = False,
2122
):
2223
"""Citation File Format (CFF) parser.
2324
@@ -35,7 +36,10 @@ def __init__(
3536
"maintainers": ["contact"],
3637
}
3738
super().__init__(
38-
path, create_if_not_exists=create_if_not_exists, direct_mappings=mappings
39+
path,
40+
create_if_not_exists=create_if_not_exists,
41+
direct_mappings=mappings,
42+
pass_validation=pass_validation,
3943
)
4044

4145
def _init_new_file(self):
@@ -53,8 +57,10 @@ def _load(self):
5357
with open(self.path) as f:
5458
self._data = self._yaml.load(f)
5559

56-
def _validate(self):
60+
def _validate(self) -> None:
5761
"""Validate the CFF file."""
62+
if self.pass_validation:
63+
return
5864
try:
5965
citation = create_citation(self.path, None)
6066
citation.validate()

src/somesy/codemeta/writer.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def __init__(
2020
self,
2121
path: Path,
2222
merge: Optional[bool] = False,
23+
pass_validation: Optional[bool] = False,
2324
):
2425
"""Codemeta.json parser.
2526
@@ -46,7 +47,12 @@ def __init__(
4647
if path.is_file() and not self.merge:
4748
logger.verbose("Deleting existing codemeta.json file.")
4849
path.unlink()
49-
super().__init__(path, create_if_not_exists=True, direct_mappings=mappings)
50+
super().__init__(
51+
path,
52+
create_if_not_exists=True,
53+
direct_mappings=mappings,
54+
pass_validation=pass_validation,
55+
)
5056

5157
# if merge is True, add necessary keys to the codemeta.json file
5258
if self.merge:
@@ -95,6 +101,8 @@ def _load(self) -> None:
95101

96102
def _validate(self) -> None:
97103
"""Validate codemeta.json content using pydantic class."""
104+
if self.pass_validation:
105+
return
98106
invalid_fields = validate_codemeta(self._data)
99107
if invalid_fields and self.merge:
100108
raise ValueError(

src/somesy/fortran/writer.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818
class Fortran(ProjectMetadataWriter):
1919
"""Fortran config file handler parsed from fpm.toml."""
2020

21-
def __init__(self, path: Path):
21+
def __init__(
22+
self,
23+
path: Path,
24+
pass_validation: Optional[bool] = False,
25+
):
2226
"""Fortran config file handler parsed from fpm.toml.
2327
2428
See [somesy.core.writer.ProjectMetadataWriter.__init__][].
@@ -28,7 +32,12 @@ def __init__(self, path: Path):
2832
"maintainers": ["maintainer"],
2933
"documentation": IgnoreKey(),
3034
}
31-
super().__init__(path, create_if_not_exists=False, direct_mappings=mappings)
35+
super().__init__(
36+
path,
37+
create_if_not_exists=False,
38+
direct_mappings=mappings,
39+
pass_validation=pass_validation,
40+
)
3241

3342
@property
3443
def authors(self):
@@ -71,6 +80,8 @@ def _validate(self) -> None:
7180
In order to preserve toml comments and structure, tomlkit library is used.
7281
Pydantic class only used for validation.
7382
"""
83+
if self.pass_validation:
84+
return
7485
config = dict(self._get_property([]))
7586
logger.debug(
7687
f"Validating config using {FortranConfig.__name__}: {pretty_repr(config)}"

src/somesy/julia/writer.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,20 @@
1818
class Julia(ProjectMetadataWriter):
1919
"""Julia config file handler parsed from Project.toml."""
2020

21-
def __init__(self, path: Path):
21+
def __init__(
22+
self,
23+
path: Path,
24+
pass_validation: Optional[bool] = False,
25+
):
2226
"""Julia config file handler parsed from Project.toml.
2327
2428
See [somesy.core.writer.ProjectMetadataWriter.__init__][].
2529
"""
26-
super().__init__(path, create_if_not_exists=False)
30+
super().__init__(
31+
path,
32+
create_if_not_exists=False,
33+
pass_validation=pass_validation,
34+
)
2735

2836
def _load(self) -> None:
2937
"""Load Project.toml file."""
@@ -36,6 +44,8 @@ def _validate(self) -> None:
3644
In order to preserve toml comments and structure, tomlkit library is used.
3745
Pydantic class only used for validation.
3846
"""
47+
if self.pass_validation:
48+
return
3949
config = dict(self._get_property([]))
4050
logger.debug(
4151
f"Validating config using {JuliaConfig.__name__}: {pretty_repr(config)}"

src/somesy/mkdocs/writer.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@
1717
class MkDocs(ProjectMetadataWriter):
1818
"""Project documentation with Markdown (MkDocs) parser and saver."""
1919

20-
def __init__(self, path: Path, create_if_not_exists: bool = False):
20+
def __init__(
21+
self,
22+
path: Path,
23+
create_if_not_exists: bool = False,
24+
pass_validation: Optional[bool] = False,
25+
):
2126
"""Project documentation with Markdown (MkDocs) parser.
2227
2328
See [somesy.core.writer.ProjectMetadataWriter.__init__][].
@@ -38,16 +43,21 @@ def __init__(self, path: Path, create_if_not_exists: bool = False):
3843
"keywords": IgnoreKey(),
3944
}
4045
super().__init__(
41-
path, create_if_not_exists=create_if_not_exists, direct_mappings=mappings
46+
path,
47+
create_if_not_exists=create_if_not_exists,
48+
direct_mappings=mappings,
49+
pass_validation=pass_validation,
4250
)
4351

4452
def _load(self):
4553
"""Load the MkDocs file."""
4654
with open(self.path) as f:
4755
self._data = self._yaml.load(f)
4856

49-
def _validate(self):
57+
def _validate(self) -> None:
5058
"""Validate the MkDocs file."""
59+
if self.pass_validation:
60+
return
5161
config = dict(self._get_property([]))
5262
logger.debug(
5363
f"Validating config using {MkDocsConfig.__name__}: {pretty_repr(config)}"

src/somesy/package_json/writer.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class PackageJSON(ProjectMetadataWriter):
2121
def __init__(
2222
self,
2323
path: Path,
24+
pass_validation: Optional[bool] = False,
2425
):
2526
"""package.json parser.
2627
@@ -30,7 +31,12 @@ def __init__(
3031
"authors": ["author"],
3132
"documentation": IgnoreKey(),
3233
}
33-
super().__init__(path, create_if_not_exists=False, direct_mappings=mappings)
34+
super().__init__(
35+
path,
36+
create_if_not_exists=False,
37+
direct_mappings=mappings,
38+
pass_validation=pass_validation,
39+
)
3440

3541
@property
3642
def authors(self):
@@ -106,6 +112,8 @@ def _load(self) -> None:
106112

107113
def _validate(self) -> None:
108114
"""Validate package.json content using pydantic class."""
115+
if self.pass_validation:
116+
return
109117
config = dict(self._get_property([]))
110118
logger.debug(
111119
f"Validating config using {PackageJsonConfig.__name__}: {pretty_repr(config)}"

src/somesy/pom_xml/writer.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def __init__(
2424
self,
2525
path: Path,
2626
create_if_not_exists: bool = True,
27+
pass_validation: Optional[bool] = False,
2728
):
2829
"""Java Maven pom.xml parser.
2930
@@ -40,7 +41,10 @@ def __init__(
4041
"contributors": ["contributors", "contributor"],
4142
}
4243
super().__init__(
43-
path, create_if_not_exists=create_if_not_exists, direct_mappings=mappings
44+
path,
45+
create_if_not_exists=create_if_not_exists,
46+
direct_mappings=mappings,
47+
pass_validation=pass_validation,
4448
)
4549

4650
def _init_new_file(self):
@@ -54,7 +58,7 @@ def _load(self):
5458
ET.register_namespace("", POM_URL) # register POM as default xml namespace
5559
self._data = XMLProxy.parse(self.path, default_namespace=POM_URL)
5660

57-
def _validate(self):
61+
def _validate(self) -> None:
5862
"""Validate the POM file."""
5963
logger.info("Cannot validate POM file, skipping validation.")
6064

src/somesy/pyproject/writer.py

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@ class PyprojectCommon(ProjectMetadataWriter):
2121
"""Poetry config file handler parsed from pyproject.toml."""
2222

2323
def __init__(
24-
self, path: Path, *, section: List[str], model_cls, direct_mappings=None
24+
self,
25+
path: Path,
26+
*,
27+
section: List[str],
28+
model_cls,
29+
direct_mappings=None,
30+
pass_validation: Optional[bool] = False,
2531
):
2632
"""Poetry config file handler parsed from pyproject.toml.
2733
@@ -30,7 +36,10 @@ def __init__(
3036
self._model_cls = model_cls
3137
self._section = section
3238
super().__init__(
33-
path, create_if_not_exists=False, direct_mappings=direct_mappings or {}
39+
path,
40+
create_if_not_exists=False,
41+
direct_mappings=direct_mappings or {},
42+
pass_validation=pass_validation,
3443
)
3544

3645
def _load(self) -> None:
@@ -44,6 +53,8 @@ def _validate(self) -> None:
4453
In order to preserve toml comments and structure, tomlkit library is used.
4554
Pydantic class only used for validation.
4655
"""
56+
if self.pass_validation:
57+
return
4758
config = dict(self._get_property([]))
4859
logger.debug(
4960
f"Validating config using {self._model_cls.__name__}: {pretty_repr(config)}"
@@ -89,12 +100,21 @@ def _set_property(self, key: Union[str, List[str], IgnoreKey], value: Any) -> No
89100
class Poetry(PyprojectCommon):
90101
"""Poetry config file handler parsed from pyproject.toml."""
91102

92-
def __init__(self, path: Path):
103+
def __init__(
104+
self,
105+
path: Path,
106+
pass_validation: Optional[bool] = False,
107+
):
93108
"""Poetry config file handler parsed from pyproject.toml.
94109
95110
See [somesy.core.writer.ProjectMetadataWriter.__init__][].
96111
"""
97-
super().__init__(path, section=["tool", "poetry"], model_cls=PoetryConfig)
112+
super().__init__(
113+
path,
114+
section=["tool", "poetry"],
115+
model_cls=PoetryConfig,
116+
pass_validation=pass_validation,
117+
)
98118

99119
@staticmethod
100120
def _from_person(person: Union[Person, Entity]):
@@ -119,7 +139,7 @@ def _to_person(person: str) -> Optional[Union[Person, Entity]]:
119139
class SetupTools(PyprojectCommon):
120140
"""Setuptools config file handler parsed from setup.cfg."""
121141

122-
def __init__(self, path: Path):
142+
def __init__(self, path: Path, pass_validation: Optional[bool] = False):
123143
"""Setuptools config file handler parsed from pyproject.toml.
124144
125145
See [somesy.core.writer.ProjectMetadataWriter.__init__][].
@@ -132,7 +152,11 @@ def __init__(self, path: Path):
132152
"license": ["license", "text"],
133153
}
134154
super().__init__(
135-
path, section=section, direct_mappings=mappings, model_cls=SetuptoolsConfig
155+
path,
156+
section=section,
157+
direct_mappings=mappings,
158+
model_cls=SetuptoolsConfig,
159+
pass_validation=pass_validation,
136160
)
137161

138162
@staticmethod
@@ -186,11 +210,12 @@ class Pyproject(wrapt.ObjectProxy):
186210

187211
__wrapped__: Union[SetupTools, Poetry]
188212

189-
def __init__(self, path: Path):
213+
def __init__(self, path: Path, pass_validation: Optional[bool] = False):
190214
"""Pyproject wrapper class. Wraps either setuptools or poetry.
191215
192216
Args:
193217
path (Path): Path to pyproject.toml file.
218+
pass_validation (bool, optional): Whether to pass validation. Defaults to False.
194219
195220
Raises:
196221
FileNotFoundError: Raised when pyproject.toml file is not found.
@@ -207,10 +232,10 @@ def __init__(self, path: Path):
207232
# inspect file to pick suitable project metadata writer
208233
if "project" in data:
209234
logger.verbose("Found setuptools-based metadata in pyproject.toml")
210-
self.__wrapped__ = SetupTools(path)
235+
self.__wrapped__ = SetupTools(path, pass_validation=pass_validation)
211236
elif "tool" in data and "poetry" in data["tool"]:
212237
logger.verbose("Found poetry-based metadata in pyproject.toml")
213-
self.__wrapped__ = Poetry(path)
238+
self.__wrapped__ = Poetry(path, pass_validation=pass_validation)
214239
else:
215240
msg = "The pyproject.toml file is ambiguous, either add a [project] or [tool.poetry] section"
216241
raise ValueError(msg)

src/somesy/rust/writer.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818
class Rust(ProjectMetadataWriter):
1919
"""Rust config file handler parsed from Cargo.toml."""
2020

21-
def __init__(self, path: Path):
21+
def __init__(
22+
self,
23+
path: Path,
24+
pass_validation: Optional[bool] = False,
25+
):
2226
"""Rust config file handler parsed from Cargo.toml.
2327
2428
See [somesy.core.writer.ProjectMetadataWriter.__init__][].
@@ -27,7 +31,12 @@ def __init__(self, path: Path):
2731
mappings: FieldKeyMapping = {
2832
"maintainers": IgnoreKey(),
2933
}
30-
super().__init__(path, create_if_not_exists=False, direct_mappings=mappings)
34+
super().__init__(
35+
path,
36+
create_if_not_exists=False,
37+
direct_mappings=mappings,
38+
pass_validation=pass_validation,
39+
)
3140

3241
def _load(self) -> None:
3342
"""Load Cargo.toml file."""
@@ -40,6 +49,8 @@ def _validate(self) -> None:
4049
In order to preserve toml comments and structure, tomlkit library is used.
4150
Pydantic class only used for validation.
4251
"""
52+
if self.pass_validation:
53+
return
4354
config = dict(self._get_property([]))
4455
logger.debug(
4556
f"Validating config using {RustConfig.__name__}: {pretty_repr(config)}"

tests/input/test_cff_validate.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ def test_cff_validate_reject(tmp_path):
2525
# try to load the CFF file
2626
with pytest.raises(ValueError):
2727
CFF(cff_path)
28+
29+
# if we pass validation, it should not raise an error
30+
CFF(cff_path, pass_validation=True)

0 commit comments

Comments
 (0)