Skip to content

Commit 0212cdc

Browse files
authored
Merge pull request #39 from Materials-Data-Science-and-Informatics/feature/consistent_pydantic
consistent pydantic field definitions
2 parents 2d3108d + 3fa1583 commit 0212cdc

4 files changed

Lines changed: 132 additions & 82 deletions

File tree

src/somesy/core/models.py

Lines changed: 68 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -148,38 +148,49 @@ def at_least_one_target(cls, values):
148148
return values
149149

150150
# cli flags
151-
show_info: bool = Field(
152-
False, description="Show basic information messages on run (-v flag)."
153-
)
154-
verbose: bool = Field(False, description="Show verbose messages on run (-vv flag).")
155-
debug: bool = Field(False, description="Show debug messages on run (-vvv flag).")
156-
157-
input_file: Path = Field(
158-
Path("somesy.toml"), description="Project metadata input file path."
159-
)
151+
show_info: Annotated[
152+
bool,
153+
Field(
154+
description="Show basic information messages on run (-v flag).",
155+
),
156+
] = False
157+
verbose: Annotated[
158+
bool, Field(description="Show verbose messages on run (-vv flag).")
159+
] = False
160+
debug: Annotated[
161+
bool, Field(description="Show debug messages on run (-vvv flag).")
162+
] = False
160163

161-
no_sync_pyproject: bool = Field(
162-
False, description="Do not sync with pyproject.toml."
163-
)
164-
pyproject_file: Path = Field(
165-
Path("pyproject.toml"), description="pyproject.toml file path."
166-
)
164+
input_file: Annotated[
165+
Path, Field(description="Project metadata input file path.")
166+
] = Path("somesy.toml")
167167

168-
no_sync_package_json: bool = Field(
169-
False, description="Do not sync with package.json."
170-
)
171-
package_json_file: Path = Field(
172-
Path("package.json"), description="package.json file path."
173-
)
168+
no_sync_pyproject: Annotated[
169+
bool, Field(description="Do not sync with pyproject.toml.")
170+
] = False
171+
pyproject_file: Annotated[
172+
Path, Field(description="pyproject.toml file path.")
173+
] = Path("pyproject.toml")
174174

175-
no_sync_cff: bool = Field(False, description="Do not sync with CFF.")
176-
cff_file: Path = Field(Path("CITATION.cff"), description="CFF file path.")
175+
no_sync_package_json: Annotated[
176+
bool, Field(description="Do not sync with package.json.")
177+
] = False
178+
package_json_file: Annotated[
179+
Path, Field(description="package.json file path.")
180+
] = Path("package.json")
177181

178-
no_sync_codemeta: bool = Field(False, description="Do not sync with codemeta.json.")
179-
codemeta_file: Path = Field(
180-
Path("codemeta.json"), description="codemeta.json file path."
182+
no_sync_cff: Annotated[bool, Field(description="Do not sync with CFF.")] = False
183+
cff_file: Annotated[Path, Field(description="CFF file path.")] = Path(
184+
"CITATION.cff"
181185
)
182186

187+
no_sync_codemeta: Annotated[
188+
bool, Field(description="Do not sync with codemeta.json.")
189+
] = False
190+
codemeta_file: Annotated[
191+
Path, Field(description="codemeta.json file path.")
192+
] = Path("codemeta.json")
193+
183194
def log_level(self) -> SomesyLogLevel:
184195
"""Return log level derived from this configuration."""
185196
return SomesyLogLevel.from_flags(
@@ -375,23 +386,30 @@ def at_least_one_author(cls, people):
375386
raise ValueError("At least one person must be an author of this project.")
376387
return people
377388

378-
name: str = Field(description="Project name.")
379-
description: str = Field(description="Project description.")
380-
version: Optional[str] = Field(description="Project version.")
381-
license: LicenseEnum = Field(description="SPDX License string.")
382-
383-
repository: Optional[AnyUrl] = Field(
384-
None, description="URL of the project source code repository."
385-
)
386-
homepage: Optional[AnyUrl] = Field(None, description="URL of the project homepage.")
387-
388-
keywords: Optional[List[str]] = Field(
389-
None, min_items=1, description="Keywords that describe the project."
390-
)
389+
name: Annotated[str, Field(description="Project name.")]
390+
description: Annotated[str, Field(description="Project description.")]
391+
version: Annotated[Optional[str], Field(description="Project version.")]
392+
license: Annotated[LicenseEnum, Field(description="SPDX License string.")]
391393

392-
people: List[Person] = Field(
393-
min_items=1, description="Project authors, maintainers and contributors."
394-
)
394+
repository: Annotated[
395+
Optional[AnyUrl],
396+
Field(description="URL of the project source code repository."),
397+
] = None
398+
homepage: Annotated[
399+
Optional[AnyUrl], Field(description="URL of the project homepage.")
400+
] = None
401+
402+
keywords: Annotated[
403+
Optional[List[str]],
404+
Field(min_items=1, description="Keywords that describe the project."),
405+
] = None
406+
407+
people: Annotated[
408+
List[Person],
409+
Field(
410+
min_items=1, description="Project authors, maintainers and contributors."
411+
),
412+
]
395413

396414
def authors(self):
397415
"""Return people marked as authors."""
@@ -407,12 +425,14 @@ class SomesyInput(SomesyBaseModel):
407425

408426
_origin: Optional[Path]
409427

410-
project: ProjectMetadata = Field(
411-
description="Project metadata to be used and synchronized."
412-
)
413-
config: Optional[SomesyConfig] = Field(
414-
description="somesy tool configuration (matches CLI flags)."
415-
)
428+
project: Annotated[
429+
ProjectMetadata,
430+
Field(description="Project metadata to be used and synchronized."),
431+
]
432+
config: Annotated[
433+
Optional[SomesyConfig],
434+
Field(description="somesy tool configuration (matches CLI flags)."),
435+
]
416436

417437
def is_somesy_file(self) -> bool:
418438
"""Return whether this somesy input is from a somesy config file.

src/somesy/package_json/models.py

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,59 @@
22
import re
33
from typing import List, Optional, Union
44

5-
from pydantic import AnyUrl, BaseModel, EmailStr, ValidationError, validator
5+
from pydantic import AnyUrl, BaseModel, EmailStr, Field, ValidationError, validator
6+
from typing_extensions import Annotated
67

78

89
class PackageAuthor(BaseModel):
910
"""Package author model."""
1011

11-
name: Optional[str]
12-
email: Optional[EmailStr]
13-
url: Optional[AnyUrl]
12+
name: Annotated[Optional[str], Field(description="Author name")]
13+
email: Annotated[Optional[EmailStr], Field(description="Author email")]
14+
url: Annotated[Optional[AnyUrl], Field(description="Author website or orcid page")]
1415

1516

1617
class PackageRepository(BaseModel):
1718
"""Package repository model."""
1819

19-
type: str
20-
url: Optional[str]
20+
type: Annotated[Optional[str], Field(description="Repository type")]
21+
url: Annotated[str, Field(description="Repository url")]
2122

2223

2324
class PackageLicense(BaseModel):
2425
"""Package license model."""
2526

26-
type: str
27-
url: Optional[str]
27+
type: Annotated[Optional[str], Field(description="License type")]
28+
url: Annotated[str, Field(description="License url")]
2829

2930

3031
class PackageJsonConfig(BaseModel):
3132
"""Package.json config model."""
3233

33-
name: str
34-
version: str
35-
description: Optional[str]
36-
author: Optional[Union[str, PackageAuthor]]
37-
maintainers: Optional[List[Union[str, PackageAuthor]]]
38-
contributors: Optional[List[Union[str, PackageAuthor]]]
39-
license: Optional[Union[str, PackageLicense]]
40-
repository: Optional[PackageRepository]
41-
homepage: Optional[AnyUrl]
42-
keywords: Optional[List[str]]
34+
name: Annotated[str, Field(description="Package name")]
35+
version: Annotated[str, Field(description="Package version")]
36+
description: Annotated[Optional[str], Field(description="Package description")]
37+
author: Annotated[
38+
Optional[Union[str, PackageAuthor]], Field(description="Package author")
39+
]
40+
maintainers: Annotated[
41+
Optional[List[Union[str, PackageAuthor]]],
42+
Field(description="Package maintainers"),
43+
]
44+
contributors: Annotated[
45+
Optional[List[Union[str, PackageAuthor]]],
46+
Field(description="Package contributors"),
47+
]
48+
license: Annotated[
49+
Optional[Union[str, PackageLicense]], Field(description="Package license")
50+
]
51+
repository: Annotated[
52+
Optional[Union[PackageRepository, str]], Field(description="Package repository")
53+
]
54+
homepage: Annotated[Optional[AnyUrl], Field(description="Package homepage")]
55+
keywords: Annotated[
56+
Optional[List[str]], Field(description="Keywords that describe the package")
57+
]
4358

4459
# convert package author to dict if it is a string
4560
@classmethod

src/somesy/package_json/writer.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,5 @@ def sync(self, metadata: ProjectMetadata) -> None:
109109
"""
110110
super().sync(metadata)
111111
self.contributors = self._sync_person_list(self.contributors, metadata.people)
112-
self.repository = {"type": "git", "url": metadata.repository}
112+
if metadata.repository:
113+
self.repository = {"type": "git", "url": metadata.repository}

src/somesy/pyproject/models.py

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,37 @@
2121
class PoetryConfig(BaseModel):
2222
"""Poetry configuration model."""
2323

24-
name: Annotated[str, Field(regex=r"^[A-Za-z0-9]+([_-][A-Za-z0-9]+)*$")]
24+
name: Annotated[
25+
str,
26+
Field(regex=r"^[A-Za-z0-9]+([_-][A-Za-z0-9]+)*$", description="Package name"),
27+
]
2528
version: Annotated[
26-
str, Field(regex=r"^\d+(\.\d+)*((a|b|rc)\d+)?(post\d+)?(dev\d+)?$")
29+
str,
30+
Field(
31+
regex=r"^\d+(\.\d+)*((a|b|rc)\d+)?(post\d+)?(dev\d+)?$",
32+
description="Package version",
33+
),
2734
]
28-
description: str
29-
license: Optional[Union[LicenseEnum, List[LicenseEnum]]] = Field(
30-
None, description="An SPDX license identifier."
31-
)
32-
authors: Set[str]
33-
maintainers: Optional[Set[str]] = None
34-
readme: Optional[Union[Path, List[Path]]] = None
35-
homepage: Optional[HttpUrl] = None
36-
repository: Optional[HttpUrl] = None
37-
documentation: Optional[HttpUrl] = None
38-
keywords: Optional[Set[str]] = None
39-
classifiers: Optional[List[str]] = None
40-
urls: Optional[Dict[str, HttpUrl]] = None
35+
description: Annotated[str, Field(description="Package description")]
36+
license: Annotated[
37+
Optional[Union[LicenseEnum, List[LicenseEnum]]],
38+
Field(description="An SPDX license identifier."),
39+
]
40+
authors: Annotated[Set[str], Field(description="Package authors")]
41+
maintainers: Annotated[Optional[Set[str]], Field(description="Package maintainers")]
42+
readme: Annotated[
43+
Optional[Union[Path, List[Path]]], Field(description="Package readme file(s)")
44+
]
45+
homepage: Annotated[Optional[HttpUrl], Field(description="Package homepage")]
46+
repository: Annotated[Optional[HttpUrl], Field(description="Package repository")]
47+
documentation: Annotated[
48+
Optional[HttpUrl], Field(description="Package documentation page")
49+
]
50+
keywords: Annotated[
51+
Optional[Set[str]], Field(description="Keywords that describe the package")
52+
]
53+
classifiers: Annotated[Optional[List[str]], Field(description="pypi classifiers")]
54+
urls: Annotated[Optional[Dict[str, HttpUrl]], Field(description="Package URLs")]
4155

4256
@validator("version")
4357
def validate_version(cls, v):

0 commit comments

Comments
 (0)