Test Failed
Push — master ( 121a6b...418b67 )
by Oliver
03:25 queued 10s
created

person   A

Complexity

Total Complexity 37

Size/Duplication

Total Lines 225
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 37
eloc 161
dl 0
loc 225
rs 9.44
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A Person.get_yob_and_yod() 0 4 1
A Person.get_year_of_birth() 0 6 3
A Person.__post_init__() 0 7 1
B Person.get_age() 0 13 8
A _Peertitle_default.nobility_title() 0 4 2
A Person.get_dob_and_dod() 0 4 1
A Person.get_sex() 0 11 4
A _Peertitle_default.title_fix() 0 13 4
A _Academic_title_default.title_repair() 0 12 5
A _Academic_title_default.degree_title() 0 4 2
A Name.__post_init__() 0 17 4
A Academic.__post_init__() 0 3 1
A Noble.__post_init__() 0 4 1
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
"""
4
A set of dataclasses concerning roles of persons and their particulars.
5
"""
6
import datetime
7
import os
8
import sys
9
from dataclasses import dataclass, field
10
from typing import Optional, Tuple
11
12
from gender_guesser import detector as sex  # type: ignore
13
14
PACKAGE_PARENT = ".."
15
SCRIPT_DIR = os.path.dirname(
16
    os.path.realpath(os.path.join(os.getcwd(), os.path.expanduser(__file__)))
17
)  # isort:skip # noqa # pylint: disable=wrong-import-position
18
sys.path.append(
19
    os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT))
20
)  # isort: skip # noqa # pylint: disable=wrong-import-position
21
22
from src.resources.constants import PEER_PREPOSITIONS  # type: ignore # noqa
23
from src.resources.constants import PEERTITLES  # type: ignore # noqa
24
from src.resources.helpers import (  # type: ignore # noqa; type: ignore # noqa; type: ignore  # noqa; type: ignore # noqa
25
    AttrDisplay,
26
    NotInRange,
27
    Party,
28
    TooManyFirstNames,
29
)
30
31
32
@dataclass
33
class _Name_default:
34
    middle_name_1: Optional[str] = field(default=None)
35
    middle_name_2: Optional[str] = field(default=None)
36
    maiden_name: Optional[str] = field(default=None)
37
    divorcée: Optional[str] = field(default=None)
38
39
40
@dataclass
41
class _Name_base:
42
    first_name: str
43
    last_name: str
44
45
46
@dataclass
47
class Name(_Name_default, _Name_base, AttrDisplay):
48
49
    """
50
    The most basic part to describe a person.
51
    To add more middle names, dataclass _Name_default has to be given further
52
    middle_name attributes. Since this project currently focusses on German
53
    politicians, the limit of three given names is preserved.
54
    """
55
56
    def __post_init__(self):
57
        """
58
        In case a Name instance is initialized with all first names in one
59
        string, __post_init__ will take care of this and assign each first
60
        name its attribute. Also it will raise TooManyFirstNames if more than
61
        three first names are given.
62
        """
63
        first_names = self.first_name.split(" ")
64
        self.first_name = first_names[0]
65
        if len(first_names) == 2:
66
            self.middle_name_1 = first_names[1]
67
        elif len(first_names) == 3:
68
            self.middle_name_1 = first_names[1]
69
            self.middle_name_2 = first_names[-1]
70
        elif len(first_names) > 3:
71
            print(first_names)
72
            raise TooManyFirstNames("There are more than three first names!")
73
74
75
@dataclass
76
class _Peertitle_default:
77
    peer_title: Optional[str] = field(default=None)
78
    peer_preposition: Optional[str] = field(default=None)
79
80
    def nobility_title(self) -> None:
81
        if self.peer_title is not None:
82
            title = self.peer_title
83
            self.peer_title, self.peer_preposition = self.title_fix(title)
84
85
    def title_fix(self, title) -> Tuple[str, str]:
86
        titles = title.split(" ")
87
        title_tmp = ""
88
        preposition_tmp = ""
89
        for prep in titles:
90
            if prep.lower() in PEER_PREPOSITIONS:
91
                preposition_tmp = preposition_tmp + prep.lower() + " "
92
            elif prep in PEERTITLES:
93
                title_tmp = title_tmp + prep + " "
94
        peer_preposition = preposition_tmp.strip()
95
        peer_title = title_tmp.strip()
96
97
        return peer_title, peer_preposition
98
99
100
@dataclass
101
class Noble(_Peertitle_default, Name, AttrDisplay):
102
    def __post_init__(self):
103
        """Initialize names and titles."""
104
        Name.__post_init__(self)
105
        self.nobility_title()
106
107
108
@dataclass
109
class _Academic_title_default:
110
    academic_title: Optional[str] = field(default=None)
111
112
    def degree_title(self) -> None:
113
        if self.academic_title is not None:
114
            title = self.academic_title
115
            self.academic_title = self.title_repair(title)
116
117
    def title_repair(self, title) -> str:
118
        if ".D" in title:
119
            title = ". ".join(c for c in title.split("."))
120
        if ".A" in title:
121
            title = ". ".join(c for c in title.split("."))
122
        if title.endswith("Dr"):
123
            title = title[:-2] + "Dr."
124
        while "  " in title:
125
            title = title.replace("  ", " ")
126
        title = title.strip()
127
128
        return title
129
130
131
@dataclass
132
class Academic(_Academic_title_default, Name, AttrDisplay):
133
    def __post_init__(self):
134
        Name.__post_init__(self)
135
        self.degree_title()
136
137
138
@dataclass
139
class _Person_default:
140
    gender: str = field(default="unknown")
141
    year_of_birth: str = field(default="unknown")
142
    date_of_birth: str = field(default="unknown")
143
    age: str = field(default="unknown")
144
    deceased: bool = field(default=False)
145
    year_of_death: str = field(default="unknown")
146
    date_of_death: str = field(default="unknown")
147
    profession: str = field(default="unknown")
148
149
150
@dataclass
151
class Person(
152
    _Peertitle_default,
153
    _Academic_title_default,
154
    _Person_default,
155
    Name,
156
    AttrDisplay,  # noqa
157
):
158
    def __post_init__(self):
159
        Name.__post_init__(self)
160
        Noble.__post_init__(self)
161
        Academic.__post_init__(self)
162
        self.get_sex()
163
        self.get_age()
164
        self.get_year_of_birth()
165
166
    def get_sex(self) -> None:
167
        if "-" in self.first_name:
168
            first_name = self.first_name.split("-")[0]
169
        else:
170
            first_name = self.first_name
171
        d = sex.Detector()
172
        gender = d.get_gender(f"{first_name}")
173
        if "female" in gender:
174
            self.gender = "female"
175
        elif "male" in gender:
176
            self.gender = "male"
177
178
    def get_year_of_birth(self) -> None:
179
        if "." in self.date_of_birth:
180
            self.year_of_birth = self.date_of_birth.split(".")[-1]
181
        elif len(self.date_of_birth.strip()) == 4:
182
            self.year_of_birth = self.date_of_birth
183
            self.date_of_birth = "unknown"
184
185
    def get_age(self) -> None:
186
        today = datetime.date.today()
187
        if self.date_of_birth != "unknown":
188
            born = str(self.date_of_birth)
189
            if len(born) > 4 and len(born) < 12 and "-" in born:
190
                self.get_yob_and_yod(born)
191
            elif len(born) > 8 and "-" in born:
192
                self.get_dob_and_dod(born)
193
            elif "." in born:
194
                born = born.split(".")[-1]
195
                self.age = str(int(today.year) - int(born.strip()))
196
            else:
197
                self.age = str(int(today.year) - int(born.strip()))
198
199
    def get_yob_and_yod(self, born) -> None:
200
        self.year_of_death = born.strip()[5:]
201
        self.year_of_birth = born[:4]
202
        self.deceased = True
203
204
    def get_dob_and_dod(self, born) -> None:
205
        self.date_of_death = born.split("-")[-1].strip()
206
        self.date_of_birth = born.split("-")[0].strip()
207
        self.deceased = True
208
209
210
if __name__ == "__main__":
211
212
    name = Name("Hans Hermann", "Werner")
213
    print(name)
214
215
    noble = Noble("Dagmara", "Bodelschwingh", peer_title="Gräfin von")
216
    print(noble)
217
218
    academic = Academic("Horst Heiner", "Wiekeiner", academic_title="Dr.")  # noqa
219
    print(academic)
220
221
    person_1 = Person(
222
        "Sven", "Rübennase", academic_title="MBA", date_of_birth="1990"
223
    )  # noqa
224
    print(person_1)
225