1 | #!/usr/bin/env python |
||
2 | # -*- coding: utf-8 -*- |
||
3 | """A set of dataclasses concerning roles of persons and their particulars.""" |
||
4 | import datetime |
||
5 | import os |
||
6 | import sys |
||
7 | from dataclasses import dataclass, field |
||
8 | from typing import Optional, Tuple |
||
9 | |||
10 | from gender_guesser import detector as sex # type: ignore |
||
0 ignored issues
–
show
introduced
by
![]() |
|||
11 | |||
12 | PACKAGE_PARENT = ".." |
||
13 | SCRIPT_DIR = os.path.dirname( |
||
14 | os.path.realpath(os.path.join(os.getcwd(), os.path.expanduser(__file__))) |
||
15 | ) # isort:skip # noqa # pylint: disable=wrong-import-position |
||
16 | sys.path.append( |
||
17 | os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)) |
||
18 | ) # isort: skip # noqa # pylint: disable=wrong-import-position |
||
19 | |||
20 | from personroles.resources.constants import ( # type: ignore # noqa |
||
21 | PEER_PREPOSITIONS, |
||
22 | PEERTITLES, |
||
23 | ) |
||
24 | from personroles.resources.helpers import AttrDisplay # type: ignore # noqa |
||
25 | from personroles.resources.helpers import TooManyFirstNames # noqa |
||
26 | |||
27 | |||
28 | @dataclass |
||
0 ignored issues
–
show
Class name "_Name_default" doesn't conform to PascalCase naming style ('[^\\W\\da-z][^\\W_]+$' pattern)
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. ![]() |
|||
29 | class _Name_default: |
||
30 | middle_name_1: Optional[str] = field(default=None) |
||
31 | middle_name_2: Optional[str] = field(default=None) |
||
32 | maiden_name: Optional[str] = field(default=None) |
||
33 | divorcée: Optional[str] = field(default=None) |
||
34 | |||
35 | |||
36 | @dataclass |
||
0 ignored issues
–
show
Class name "_Name_base" doesn't conform to PascalCase naming style ('[^\\W\\da-z][^\\W_]+$' pattern)
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. ![]() |
|||
37 | class _Name_base: |
||
38 | first_name: str |
||
39 | last_name: str |
||
40 | |||
41 | |||
42 | @dataclass |
||
43 | class Name(_Name_default, _Name_base, AttrDisplay): |
||
44 | """A person's names: first, middle_1, middle_2, last name""" |
||
45 | |||
46 | def __post_init__(self): |
||
47 | """ |
||
48 | In case a Name instance is initialized with all first names in one |
||
49 | string, __post_init__ will take care of this and assign each first |
||
50 | name its attribute. Also it will raise TooManyFirstNames if more than |
||
51 | three first names are given. |
||
52 | """ |
||
53 | first_names = self.first_name.split(" ") |
||
54 | self.first_name = first_names[0] |
||
55 | if len(first_names) == 2: |
||
56 | self.middle_name_1 = first_names[1] |
||
57 | elif len(first_names) == 3: |
||
58 | self.middle_name_1 = first_names[1] |
||
59 | self.middle_name_2 = first_names[-1] |
||
60 | elif len(first_names) > 3: |
||
61 | print(first_names) |
||
62 | raise TooManyFirstNames("There are more than three first names!") |
||
63 | |||
64 | |||
65 | @dataclass |
||
0 ignored issues
–
show
Class name "_Peertitle_default" doesn't conform to PascalCase naming style ('[^\\W\\da-z][^\\W_]+$' pattern)
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. ![]() |
|||
66 | class _Peertitle_default: |
||
67 | peer_title: Optional[str] = field(default=None) |
||
68 | peer_preposition: Optional[str] = field(default=None) |
||
69 | |||
70 | def nobility_title(self) -> None: |
||
0 ignored issues
–
show
|
|||
71 | if self.peer_title is not None: |
||
72 | title = self.peer_title |
||
73 | self.peer_title, self.peer_preposition = self.title_fix(title) |
||
74 | |||
75 | def title_fix(self, title) -> Tuple[str, str]: |
||
0 ignored issues
–
show
This method could be written as a function/class method.
If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example class Foo:
def some_method(self, x, y):
return x + y;
could be written as class Foo:
@classmethod
def some_method(cls, x, y):
return x + y;
![]() |
|||
76 | titles = title.split(" ") |
||
77 | title_tmp = "" |
||
78 | preposition_tmp = "" |
||
79 | for prep in titles: |
||
80 | if prep.lower() in PEER_PREPOSITIONS: |
||
81 | preposition_tmp = preposition_tmp + prep.lower() + " " |
||
82 | elif prep in PEERTITLES: |
||
83 | title_tmp = title_tmp + prep + " " |
||
84 | peer_preposition = preposition_tmp.strip() |
||
85 | peer_title = title_tmp.strip() |
||
86 | |||
87 | return peer_title, peer_preposition |
||
88 | |||
89 | |||
90 | @dataclass |
||
0 ignored issues
–
show
|
|||
91 | class Noble(_Peertitle_default, Name, AttrDisplay): |
||
92 | def __post_init__(self): |
||
93 | """Initialize names and titles.""" |
||
94 | Name.__post_init__(self) |
||
95 | self.nobility_title() |
||
96 | |||
97 | |||
98 | @dataclass |
||
0 ignored issues
–
show
Class name "_Academic_title_default" doesn't conform to PascalCase naming style ('[^\\W\\da-z][^\\W_]+$' pattern)
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. ![]() |
|||
99 | class _Academic_title_default: |
||
100 | academic_title: Optional[str] = field(default=None) |
||
101 | |||
102 | def degree_title(self) -> None: |
||
0 ignored issues
–
show
|
|||
103 | if self.academic_title is not None: |
||
104 | title = self.academic_title |
||
105 | self.academic_title = self.title_repair(title) |
||
106 | |||
107 | def title_repair(self, title) -> str: |
||
0 ignored issues
–
show
This method could be written as a function/class method.
If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example class Foo:
def some_method(self, x, y):
return x + y;
could be written as class Foo:
@classmethod
def some_method(cls, x, y):
return x + y;
![]() |
|||
108 | if ".D" in title: |
||
109 | title = ". ".join(c for c in title.split(".")) |
||
110 | if ".A" in title: |
||
111 | title = ". ".join(c for c in title.split(".")) |
||
112 | if title.endswith("Dr"): |
||
113 | title = title[:-2] + "Dr." |
||
114 | while " " in title: |
||
115 | title = title.replace(" ", " ") |
||
116 | title = title.strip() |
||
117 | |||
118 | return title |
||
119 | |||
120 | |||
121 | @dataclass |
||
0 ignored issues
–
show
|
|||
122 | class Academic(_Academic_title_default, Name, AttrDisplay): |
||
123 | def __post_init__(self): |
||
124 | """Initialize names of Name and degree.""" |
||
125 | Name.__post_init__(self) |
||
126 | self.degree_title() |
||
127 | |||
128 | |||
129 | @dataclass |
||
0 ignored issues
–
show
Class name "_Person_default" doesn't conform to PascalCase naming style ('[^\\W\\da-z][^\\W_]+$' pattern)
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. ![]() |
|||
130 | class _Person_default: |
||
131 | gender: str = field(default="unknown") |
||
132 | year_of_birth: str = field(default="unknown") |
||
133 | date_of_birth: str = field(default="unknown") |
||
134 | age: str = field(default="unknown") |
||
135 | deceased: bool = field(default=False) |
||
136 | year_of_death: str = field(default="unknown") |
||
137 | date_of_death: str = field(default="unknown") |
||
138 | profession: str = field(default="unknown") |
||
139 | |||
140 | |||
141 | @dataclass |
||
0 ignored issues
–
show
|
|||
142 | class Person( |
||
143 | _Peertitle_default, |
||
0 ignored issues
–
show
|
|||
144 | _Academic_title_default, |
||
0 ignored issues
–
show
|
|||
145 | _Person_default, |
||
0 ignored issues
–
show
|
|||
146 | Name, |
||
0 ignored issues
–
show
|
|||
147 | AttrDisplay, # noqa |
||
0 ignored issues
–
show
|
|||
148 | ): |
||
149 | def __post_init__(self): |
||
150 | """ |
||
151 | Initializing names, titles (academic and peer), age, sex, and year of |
||
152 | birth.""" |
||
153 | Name.__post_init__(self) |
||
154 | Noble.__post_init__(self) |
||
155 | Academic.__post_init__(self) |
||
156 | self.get_sex() |
||
157 | self.get_age() |
||
158 | self.get_year_of_birth() |
||
159 | |||
160 | def get_sex(self) -> None: |
||
0 ignored issues
–
show
|
|||
161 | if "-" in self.first_name: |
||
162 | first_name = self.first_name.split("-")[0] |
||
163 | else: |
||
164 | first_name = self.first_name |
||
165 | d = sex.Detector() |
||
0 ignored issues
–
show
Variable name "d" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. ![]() |
|||
166 | gender = d.get_gender(f"{first_name}") |
||
167 | if "female" in gender: |
||
168 | self.gender = "female" |
||
169 | elif "male" in gender: |
||
170 | self.gender = "male" |
||
171 | |||
172 | def get_year_of_birth(self) -> None: |
||
0 ignored issues
–
show
|
|||
173 | if "." in self.date_of_birth: |
||
174 | self.year_of_birth = self.date_of_birth.split(".")[-1] |
||
175 | elif len(self.date_of_birth.strip()) == 4: |
||
176 | self.year_of_birth = self.date_of_birth |
||
177 | self.date_of_birth = "unknown" |
||
178 | |||
179 | def get_age(self) -> None: |
||
0 ignored issues
–
show
|
|||
180 | today = datetime.date.today() |
||
181 | if self.date_of_birth != "unknown": |
||
182 | born = str(self.date_of_birth) |
||
183 | if len(born) > 4 and len(born) < 12 and "-" in born: |
||
184 | self.get_yob_and_yod(born) |
||
185 | elif len(born) > 8 and "-" in born: |
||
186 | self.get_dob_and_dod(born) |
||
187 | elif "." in born: |
||
188 | born = born.split(".")[-1] |
||
189 | self.age = str(int(today.year) - int(born.strip())) |
||
190 | else: |
||
191 | self.age = str(int(today.year) - int(born.strip())) |
||
192 | |||
193 | def get_yob_and_yod(self, born) -> None: |
||
0 ignored issues
–
show
|
|||
194 | self.year_of_death = born.strip()[5:] |
||
195 | self.year_of_birth = born[:4] |
||
196 | self.deceased = True |
||
197 | |||
198 | def get_dob_and_dod(self, born) -> None: |
||
0 ignored issues
–
show
|
|||
199 | self.date_of_death = born.split("-")[-1].strip() |
||
200 | self.date_of_birth = born.split("-")[0].strip() |
||
201 | self.deceased = True |
||
202 | |||
203 | |||
204 | if __name__ == "__main__": |
||
205 | |||
206 | name = Name("Hans Hermann", "Werner") |
||
207 | print('name = Name("Hans Hermann", "Werner")') |
||
208 | print(name) |
||
209 | |||
210 | noble = Noble("Dagmara", "Bodelschwingh", peer_title="Gräfin von") |
||
211 | print('noble = Noble("Dagmara", "Bodelschwingh", peer_title="Gräfin von")') |
||
212 | print(noble) |
||
213 | |||
214 | academic = Academic("Horst Heiner", "Wiekeiner", academic_title="Dr.") # noqa |
||
215 | print( |
||
216 | 'academic = Academic("Horst Heiner", "Wiekeiner", academic_title="Dr.")' # noqa |
||
217 | ) # noqa |
||
218 | print(academic) |
||
219 | |||
220 | person_1 = Person( |
||
221 | "Sven", "Rübennase", academic_title="MBA", date_of_birth="1990" |
||
222 | ) # noqa |
||
223 | print( |
||
224 | 'person_1 = Person("Sven", "Rübennase", academic_title="MBA", date_of_birth="1990")' # noqa |
||
225 | ) # noqa |
||
226 | print(person_1) |
||
227 |