Skip to content

Commit a400d97

Browse files
committed
disable error raise on users without email in poetry
1 parent a1548c9 commit a400d97

3 files changed

Lines changed: 118 additions & 10 deletions

File tree

src/somesy/pyproject/models.py

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Pyproject models."""
22

33
from enum import Enum
4+
from logging import getLogger
45
from pathlib import Path
56
from typing import Dict, List, Optional, Set, Union
67

@@ -10,6 +11,7 @@
1011
EmailStr,
1112
Field,
1213
TypeAdapter,
14+
ValidationError,
1315
field_validator,
1416
model_validator,
1517
)
@@ -19,6 +21,7 @@
1921
from somesy.core.types import HttpUrlStr
2022

2123
EMailAddress = TypeAdapter(EmailStr)
24+
logger = getLogger("somesy")
2225

2326

2427
class PoetryConfig(BaseModel):
@@ -81,26 +84,38 @@ def validate_version(cls, v):
8184
@field_validator("authors", "maintainers")
8285
@classmethod
8386
def validate_email_format(cls, v):
84-
"""Validate email format."""
87+
"""Validate person format, omit person that is not in correct format, don't raise an error."""
88+
if v is None:
89+
return []
90+
validated = []
8591
for author in v:
86-
if (
87-
not isinstance(author, str)
88-
or " " not in author
89-
or not EMailAddress.validate_python(author.split(" ")[-1][1:-1])
90-
):
91-
raise ValueError("Invalid email format")
92-
return v
92+
try:
93+
if not (
94+
not isinstance(author, str)
95+
or " " not in author
96+
or not EMailAddress.validate_python(author.split(" ")[-1][1:-1])
97+
):
98+
validated.append(author)
99+
else:
100+
logger.warning(
101+
f"Invalid email format for author/maintainer {author}, omitting."
102+
)
103+
except ValidationError:
104+
logger.warning(
105+
f"Invalid email format for author/maintainer {author}, omitting."
106+
)
107+
return validated
93108

94109
@field_validator("readme")
95110
@classmethod
96111
def validate_readme(cls, v):
97112
"""Validate readme file(s) by checking whether files exist."""
98113
if isinstance(v, list):
99114
if any(not e.is_file() for e in v):
100-
raise ValueError("Some file(s) do not exist")
115+
logger.warning("Some readme file(s) do not exist")
101116
else:
102117
if not v.is_file():
103-
raise ValueError("File does not exist")
118+
logger.warning("Readme file does not exist")
104119

105120

106121
class ContentTypeEnum(Enum):

src/somesy/pyproject/writer.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,52 @@ def __init__(self, path: Path):
9696
"""
9797
super().__init__(path, section=["tool", "poetry"], model_cls=PoetryConfig)
9898

99+
@property
100+
def authors(self) -> List[str]:
101+
"""Get authors from the pyproject.toml file."""
102+
# check if authors can be converted to person, only return valid ones
103+
authors = self._get_property("authors")
104+
if authors is None:
105+
return []
106+
107+
valid_authors = []
108+
for author in authors:
109+
try:
110+
self._to_person(author)
111+
valid_authors.append(author)
112+
except (ValueError, AttributeError):
113+
logger.warning(f"Invalid author format: {author}")
114+
return valid_authors
115+
116+
@authors.setter
117+
def authors(self, authors: List[Person]) -> None:
118+
"""Set the authors of the project."""
119+
authors = [self._from_person(c) for c in authors]
120+
self._set_property(self._get_key("authors"), authors)
121+
122+
@property
123+
def maintainers(self) -> List[str]:
124+
"""Get maintainers from the pyproject.toml file."""
125+
# check if maintainers can be converted to person, only return valid ones
126+
maintainers = self._get_property("maintainers")
127+
if maintainers is None:
128+
return []
129+
130+
valid_maintainers = []
131+
for maintainer in maintainers:
132+
try:
133+
self._to_person(maintainer)
134+
valid_maintainers.append(maintainer)
135+
except (ValueError, AttributeError):
136+
logger.warning(f"Invalid maintainer format: {maintainer}")
137+
return valid_maintainers
138+
139+
@maintainers.setter
140+
def maintainers(self, maintainers: List[Person]) -> None:
141+
"""Set the maintainers of the project."""
142+
maintainers = [self._from_person(c) for c in maintainers]
143+
self._set_property(self._get_key("maintainers"), maintainers)
144+
99145
@staticmethod
100146
def _from_person(person: Person):
101147
"""Convert project metadata person object to poetry string for person format "full name <email>."""

tests/output/test_pyproject_writer.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ def test_from_to_person(person):
7777
assert p.full_name == person.full_name
7878
assert p.email == person.email
7979

80+
with pytest.raises(AttributeError):
81+
p = Poetry._to_person("John Doe")
82+
8083
# test for setuptools
8184
assert SetupTools._from_person(person) == {
8285
"name": person.full_name,
@@ -165,3 +168,47 @@ def test_person_merge_pyproject(request, writer_class, writer_file_fixture, pers
165168
assert len(pj.maintainers) == 1
166169
assert pj.authors[0] == person1c_rep
167170
assert pj.authors[1] == person3_rep
171+
172+
173+
def test_without_email(tmp_path, person):
174+
pyproject_str = """
175+
[tool.poetry]
176+
name = "ttt"
177+
version = "0.1.0"
178+
description = "asd"
179+
authors = ["John Doe"]
180+
license = "MIT"
181+
182+
[tool.poetry.dependencies]
183+
python = "^3.10"
184+
185+
186+
[build-system]
187+
requires = ["poetry-core"]
188+
build-backend = "poetry.core.masonry.api"
189+
"""
190+
191+
# save to file
192+
pyproject_file = tmp_path / Path("pyproject.toml")
193+
pyproject_file.write_text(pyproject_str)
194+
195+
# load and sync
196+
p = Poetry(pyproject_file)
197+
assert len(p.authors) == 0
198+
199+
pm = ProjectMetadata(
200+
name="My awesome project",
201+
description="Project description",
202+
license=LicenseEnum.MIT,
203+
version="0.1.0",
204+
people=[
205+
person.model_copy(
206+
update=dict(author=True, publication_author=True, maintainer=True)
207+
)
208+
],
209+
)
210+
211+
p.sync(pm)
212+
213+
assert len(p.authors) == 1
214+
assert len(p.maintainers) == 1

0 commit comments

Comments
 (0)