gedcom-x 0.5.6__py3-none-any.whl → 0.5.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gedcom_x-0.5.6.dist-info → gedcom_x-0.5.8.dist-info}/METADATA +1 -1
- gedcom_x-0.5.8.dist-info/RECORD +56 -0
- gedcomx/Extensions/__init__.py +1 -0
- gedcomx/Extensions/rs10/__init__.py +1 -0
- gedcomx/Extensions/rs10/rsLink.py +116 -0
- gedcomx/TopLevelTypeCollection.py +1 -1
- gedcomx/__init__.py +43 -41
- gedcomx/{Address.py → address.py} +13 -13
- gedcomx/{Agent.py → agent.py} +52 -24
- gedcomx/{Attribution.py → attribution.py} +36 -9
- gedcomx/{Conclusion.py → conclusion.py} +49 -21
- gedcomx/converter.py +1049 -0
- gedcomx/coverage.py +55 -0
- gedcomx/{Date.py → date.py} +11 -4
- gedcomx/{Document.py → document.py} +27 -8
- gedcomx/{Event.py → event.py} +102 -27
- gedcomx/{EvidenceReference.py → evidence_reference.py} +2 -2
- gedcomx/{Fact.py → fact.py} +45 -34
- gedcomx/{Gedcom5x.py → gedcom5x.py} +78 -61
- gedcomx/gedcom7/Exceptions.py +9 -0
- gedcomx/gedcom7/Gedcom7.py +160 -0
- gedcomx/gedcom7/GedcomStructure.py +94 -0
- gedcomx/gedcom7/Specification.py +347 -0
- gedcomx/gedcom7/__init__.py +26 -0
- gedcomx/gedcom7/g7interop.py +205 -0
- gedcomx/gedcom7/logger.py +19 -0
- gedcomx/gedcomx.py +501 -0
- gedcomx/{Gender.py → gender.py} +29 -17
- gedcomx/group.py +63 -0
- gedcomx/{Identifier.py → identifier.py} +13 -16
- gedcomx/{LoggingHub.py → logging_hub.py} +21 -0
- gedcomx/{Mutations.py → mutations.py} +50 -26
- gedcomx/name.py +396 -0
- gedcomx/{Note.py → note.py} +17 -10
- gedcomx/{OnlineAccount.py → online_account.py} +1 -1
- gedcomx/{Person.py → person.py} +52 -29
- gedcomx/place_description.py +123 -0
- gedcomx/place_reference.py +62 -0
- gedcomx/qualifier.py +54 -0
- gedcomx/{Relationship.py → relationship.py} +33 -13
- gedcomx/resource.py +85 -0
- gedcomx/serialization.py +815 -0
- gedcomx/{SourceDescription.py → source_description.py} +144 -85
- gedcomx/{SourceReference.py → source_reference.py} +15 -14
- gedcomx/{Subject.py → subject.py} +30 -28
- gedcomx/{GedcomX.py → translation.py} +283 -446
- gedcomx/{URI.py → uri.py} +42 -26
- gedcom_x-0.5.6.dist-info/RECORD +0 -45
- gedcomx/Coverage.py +0 -36
- gedcomx/Group.py +0 -37
- gedcomx/Name.py +0 -276
- gedcomx/PlaceDescription.py +0 -70
- gedcomx/PlaceReference.py +0 -30
- gedcomx/Qualifier.py +0 -27
- gedcomx/Resource.py +0 -75
- gedcomx/Serialization.py +0 -401
- gedcomx/Translation.py +0 -219
- {gedcom_x-0.5.6.dist-info → gedcom_x-0.5.8.dist-info}/WHEEL +0 -0
- {gedcom_x-0.5.6.dist-info → gedcom_x-0.5.8.dist-info}/top_level.txt +0 -0
- /gedcomx/{Exceptions.py → exceptions.py} +0 -0
- /gedcomx/{ExtensibleEnum.py → extensible_enum.py} +0 -0
- /gedcomx/{Gedcom.py → gedcom.py} +0 -0
- /gedcomx/{SourceCitation.py → source_citation.py} +0 -0
- /gedcomx/{TextValue.py → textvalue.py} +0 -0
gedcomx/{URI.py → uri.py}
RENAMED
@@ -1,11 +1,25 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
from dataclasses import dataclass, field
|
3
|
-
from typing import Mapping,
|
3
|
+
from typing import Mapping, Sequence, Tuple, Union, Iterable
|
4
4
|
from urllib.parse import urlsplit, urlunsplit, urlencode, parse_qsl, SplitResult
|
5
5
|
|
6
6
|
_DEFAULT_SCHEME = "gedcomx"
|
7
7
|
|
8
|
-
|
8
|
+
# ---------- typing helpers for urlencode (Option A) ----------
|
9
|
+
QuerySeq = Sequence[Tuple[str, str]]
|
10
|
+
QueryMap = Mapping[str, str]
|
11
|
+
QueryLike = Union[str, QueryMap, QuerySeq]
|
12
|
+
|
13
|
+
def _encode_query(q: QueryLike) -> str:
|
14
|
+
"""Return a properly encoded query string."""
|
15
|
+
if isinstance(q, str):
|
16
|
+
return q
|
17
|
+
if isinstance(q, Mapping):
|
18
|
+
return urlencode(q, doseq=True) # mapping is fine
|
19
|
+
return urlencode(list(q), doseq=True) # coerce iterable to a sequence
|
20
|
+
|
21
|
+
|
22
|
+
@dataclass(slots=True)
|
9
23
|
class URI:
|
10
24
|
scheme: str = field(default=_DEFAULT_SCHEME)
|
11
25
|
authority: str = field(default="")
|
@@ -15,29 +29,33 @@ class URI:
|
|
15
29
|
|
16
30
|
# ---------- constructors ----------
|
17
31
|
@classmethod
|
18
|
-
def from_url(cls, url: str, *, default_scheme: str = _DEFAULT_SCHEME) ->
|
32
|
+
def from_url(cls, url: str, *, default_scheme: str = _DEFAULT_SCHEME) -> URI:
|
19
33
|
s = urlsplit(url)
|
20
34
|
scheme = s.scheme or default_scheme
|
21
35
|
return cls(scheme=scheme, authority=s.netloc, path=s.path, query=s.query, fragment=s.fragment)
|
22
36
|
|
23
37
|
@classmethod
|
24
|
-
def parse(cls, value: str) ->
|
38
|
+
def parse(cls, value: str) -> URI:
|
25
39
|
return cls.from_url(value)
|
26
40
|
|
27
41
|
@classmethod
|
28
42
|
def from_parts(
|
29
43
|
cls,
|
30
44
|
*,
|
31
|
-
scheme:
|
45
|
+
scheme: str | None = None,
|
32
46
|
authority: str = "",
|
33
47
|
path: str = "",
|
34
|
-
query:
|
35
|
-
fragment: str = ""
|
36
|
-
) ->
|
37
|
-
q =
|
48
|
+
query: QueryLike = "",
|
49
|
+
fragment: str = "",
|
50
|
+
) -> URI:
|
51
|
+
q = _encode_query(query)
|
38
52
|
return cls(scheme=scheme or _DEFAULT_SCHEME, authority=authority, path=path, query=q, fragment=fragment)
|
39
53
|
|
40
54
|
# ---------- views ----------
|
55
|
+
@property
|
56
|
+
def uri(self) -> str:
|
57
|
+
return str(self)
|
58
|
+
|
41
59
|
@property
|
42
60
|
def value(self) -> str:
|
43
61
|
return str(self)
|
@@ -49,9 +67,7 @@ class URI:
|
|
49
67
|
return urlunsplit(self.split())
|
50
68
|
|
51
69
|
@property
|
52
|
-
def _as_dict_(self) -> dict:
|
53
|
-
# Keeps a simple, explicit structure
|
54
|
-
return urlunsplit(self.split())
|
70
|
+
def _as_dict_(self) -> dict[str, object]:
|
55
71
|
return {
|
56
72
|
"scheme": self.scheme,
|
57
73
|
"authority": self.authority,
|
@@ -61,30 +77,29 @@ class URI:
|
|
61
77
|
"value": str(self),
|
62
78
|
}
|
63
79
|
|
64
|
-
# Accepts {'resource': '...'} or a plain string
|
80
|
+
# Accepts {'resource': '...'} or a plain string
|
65
81
|
@classmethod
|
66
|
-
def from_jsonish(cls, data:
|
82
|
+
def from_jsonish(cls, data: str | Mapping[str, object]) -> URI:
|
67
83
|
if isinstance(data, str):
|
68
84
|
return cls.from_url(data)
|
69
85
|
if isinstance(data, Mapping):
|
70
86
|
raw = data.get("resource") or data.get("value") or ""
|
71
|
-
if raw:
|
87
|
+
if isinstance(raw, str) and raw:
|
72
88
|
return cls.from_url(raw)
|
73
89
|
raise ValueError(f"Cannot build URI from: {data!r}")
|
74
90
|
|
75
91
|
# ---------- functional updaters ----------
|
76
|
-
def with_scheme(self, scheme: str) ->
|
77
|
-
def with_authority(self, authority: str) ->
|
78
|
-
def with_path(self, path: str, *, join: bool = False) ->
|
92
|
+
def with_scheme(self, scheme: str) -> URI: return self.replace(scheme=scheme)
|
93
|
+
def with_authority(self, authority: str) -> URI: return self.replace(authority=authority)
|
94
|
+
def with_path(self, path: str, *, join: bool = False) -> URI:
|
79
95
|
new_path = (self.path.rstrip("/") + "/" + path.lstrip("/")) if join else path
|
80
96
|
return self.replace(path=new_path)
|
81
|
-
def with_fragment(self, fragment: str | None) ->
|
97
|
+
def with_fragment(self, fragment: str | None) -> URI:
|
82
98
|
return self.replace(fragment=(fragment or ""))
|
83
|
-
def without_fragment(self) ->
|
84
|
-
def with_query(self, query:
|
85
|
-
|
86
|
-
|
87
|
-
def add_query_params(self, params: Mapping[str, Union[str, Iterable[str]]]) -> "URI":
|
99
|
+
def without_fragment(self) -> URI: return self.replace(fragment="")
|
100
|
+
def with_query(self, query: QueryLike) -> URI:
|
101
|
+
return self.replace(query=_encode_query(query))
|
102
|
+
def add_query_params(self, params: Mapping[str, Union[str, Iterable[str]]]) -> URI:
|
88
103
|
existing = parse_qsl(self.query, keep_blank_values=True)
|
89
104
|
for k, v in params.items():
|
90
105
|
if isinstance(v, str):
|
@@ -95,8 +110,9 @@ class URI:
|
|
95
110
|
return self.replace(query=urlencode(existing, doseq=True))
|
96
111
|
|
97
112
|
# ---------- helpers ----------
|
98
|
-
def replace(self, **kwargs) ->
|
99
|
-
|
113
|
+
def replace(self, **kwargs) -> URI:
|
114
|
+
cls = type(self)
|
115
|
+
return cls(
|
100
116
|
scheme=kwargs.get("scheme", self.scheme or _DEFAULT_SCHEME),
|
101
117
|
authority=kwargs.get("authority", self.authority),
|
102
118
|
path=kwargs.get("path", self.path),
|
gedcom_x-0.5.6.dist-info/RECORD
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
gedcomx/Address.py,sha256=FDBic6oQB30eKMWM7-6_YVPHaJdPhziU5LybwE5TY5Q,4855
|
2
|
-
gedcomx/Agent.py,sha256=C-tzfqcjuU22iJ2LjoatKdCbI_i0xskpmZsuj58K6WY,8555
|
3
|
-
gedcomx/Attribution.py,sha256=2bcl2UNsMPn10kDrA080qFRzxK-KYqZBgmPGNBZ2M4Y,2608
|
4
|
-
gedcomx/Conclusion.py,sha256=t8n8FuWwzinFTPHp9D2Umu93-4A12I9L5fCx510mfqA,8414
|
5
|
-
gedcomx/Coverage.py,sha256=BVlB3kWDoOP2j86j67hNJLC4LqoLwqs3N93z0ZbXYTw,1227
|
6
|
-
gedcomx/Date.py,sha256=cv2UeyOcTHuH2CVHq9EjTnj3FR-r4_OVuPiuc8sbOPc,2130
|
7
|
-
gedcomx/Document.py,sha256=32nWfDNVWkPK2_I0-hhcNQkrjH3ssdbtw-II3QMMelw,2957
|
8
|
-
gedcomx/Event.py,sha256=BHhmO2UlxbkSzB5htdMRf2h-WNuJQsWfrSC8tNGQ6Mg,10375
|
9
|
-
gedcomx/EvidenceReference.py,sha256=WXZpmcKzwb3lYQmGVf-TY2IsbNG3fIInPY1khRjtOSg,348
|
10
|
-
gedcomx/Exceptions.py,sha256=0OdPM3euhBMgX8o61ZwPuKeN8zPuSuuDcSBFflVGFqk,587
|
11
|
-
gedcomx/ExtensibleEnum.py,sha256=DftCZLMBNul3C9hwh-rf0GE3SVdvylvyd5mt7bX_l6o,6535
|
12
|
-
gedcomx/Fact.py,sha256=-Zz321xeFd93riaX4C4i7gIPwpqdArAYZDlWRoXA1Uk,24444
|
13
|
-
gedcomx/Gedcom.py,sha256=l_BuLBynQacDtpLjhs2Afrabfiqt2Opoo_5_7myI7Z4,1709
|
14
|
-
gedcomx/Gedcom5x.py,sha256=ZaMqvmDTn684m4uSDRy3uxgKk442K5WZjDy_0s2ga-8,22459
|
15
|
-
gedcomx/GedcomX.py,sha256=mFviKVvk8dSn4tHPd1hkHBxoTOMNKlBv7gH3Q1n87IU,63666
|
16
|
-
gedcomx/Gender.py,sha256=AV125vECC5JSgvNJRmotjDEt-A3cFzth6pcSLFwJBEE,2328
|
17
|
-
gedcomx/Group.py,sha256=VNI_cI_-YnJ9cHzwMmHD8qwDNMe89kEocPuQ67rwStA,1606
|
18
|
-
gedcomx/Identifier.py,sha256=pJB8DlMF1k5DNR0Lha6rGTTiOtwe0joVLRLQCuoXtIw,8507
|
19
|
-
gedcomx/Logging.py,sha256=vBDOjawVXc4tCge1laYjy6_2Ves-fnGzG0m6NnLZejE,624
|
20
|
-
gedcomx/LoggingHub.py,sha256=lOeMP_0hFPydVNuMcUC31FMBRHtRMP02pBMM8TuhsNg,7143
|
21
|
-
gedcomx/Mutations.py,sha256=idhQsnikCTovmNEGAhDsOe97V0L9AnFTRaufzUPm64w,6298
|
22
|
-
gedcomx/Name.py,sha256=en_VkGjpZPP_Dbl9HSq2h2JCtLS2NMzmLvis5RdBPeM,12913
|
23
|
-
gedcomx/Note.py,sha256=cvV4-fCZ0oh2zXfzD-YYoIM_WTox-fk2_bfl3i4CoNc,2251
|
24
|
-
gedcomx/OnlineAccount.py,sha256=P24o98IXo_8XQoICYZPgALjdzS0q8t2l4DU3Od9KxyI,291
|
25
|
-
gedcomx/Person.py,sha256=LyGPCZh6rZU_dE3GCJE92x1lLk41c_Edr_Po9smhPLc,7321
|
26
|
-
gedcomx/PlaceDescription.py,sha256=TRHIkDiErHa_mlx_x8gYCF6UnQ-XgT08uSmYmFNa4u0,3255
|
27
|
-
gedcomx/PlaceReference.py,sha256=3NyEYq0FaMI8m3l4H6-Ov-n9NUq_m751iYVxofqtv30,870
|
28
|
-
gedcomx/Qualifier.py,sha256=mZ_GWT3gca8g9nWidlXIRTN5dEtf_rmnLHYl1jJkQYs,728
|
29
|
-
gedcomx/Relationship.py,sha256=oyT501vR5jvWxqEYy3KvW9egD4CPL5JaAYWJmlNy9Ig,3599
|
30
|
-
gedcomx/Resource.py,sha256=bZ2dV-OdpvmDRCppyfHJXiarIKL7-OcofwvYRnpOJW0,2324
|
31
|
-
gedcomx/Serialization.py,sha256=ubtmrvi-nKmVUCK1XGwuLijrPMggNJe--kkCIC-87Ds,18580
|
32
|
-
gedcomx/SourceCitation.py,sha256=aW-lEb7bT9QU49GiBjJppFMBvtisR6fhVVuXjr5y4vQ,742
|
33
|
-
gedcomx/SourceDescription.py,sha256=zOkXo-fy-uCl_EGU8B-c6pzhlMk3nYNHn13ln1AkYk0,11914
|
34
|
-
gedcomx/SourceReference.py,sha256=swVzZ5A0jt5yFYJNJvMnQZtb7d-2YEAQPxp2a4lEY1k,5071
|
35
|
-
gedcomx/Subject.py,sha256=znee3SxYKk99JLP6KmZHkXs5hIOGu_jeLwxagENNfXs,3298
|
36
|
-
gedcomx/TextValue.py,sha256=6B0wMxL0nigFNzhXZDhbTONvFGbnM2t2NcDZiZuu4Zw,1112
|
37
|
-
gedcomx/TopLevelTypeCollection.py,sha256=nvTO6GwFwEZk9jX4fVqhy75ygsshomNb20tnlExKqyY,1495
|
38
|
-
gedcomx/Translation.py,sha256=NWa1NtTOC_VgQ-EGwWG06zUpddRxdKFSLPP6066JFaA,12485
|
39
|
-
gedcomx/URI.py,sha256=S2pFsu_VyKgOsRdHIj8pjnh6_tdA3OjAYiIugoEd70k,4271
|
40
|
-
gedcomx/Zip.py,sha256=lBxcv-Vip45884EHj56wZJJ5I36Q38UuHUidDxQBoS8,14
|
41
|
-
gedcomx/__init__.py,sha256=O8LkNk9b8BHIN3mf0RowfR9M2HdKYhF8Fgi3qxW2RSs,1660
|
42
|
-
gedcom_x-0.5.6.dist-info/METADATA,sha256=rNO-ZyEC3th_8iML9XtfJOQcnPJI1uksyWz2MB9DAV8,4332
|
43
|
-
gedcom_x-0.5.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
44
|
-
gedcom_x-0.5.6.dist-info/top_level.txt,sha256=smVBF4nxSU-mzCd6idtRYTbYjPICMMi8pTqewEmqF8Y,8
|
45
|
-
gedcom_x-0.5.6.dist-info/RECORD,,
|
gedcomx/Coverage.py
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
|
-
from .Date import Date
|
4
|
-
from .PlaceReference import PlaceReference
|
5
|
-
from .Serialization import Serialization
|
6
|
-
|
7
|
-
class Coverage:
|
8
|
-
identifier = 'http://gedcomx.org/v1/Coverage'
|
9
|
-
version = 'http://gedcomx.org/conceptual-model/v1'
|
10
|
-
|
11
|
-
def __init__(self,spatial: Optional[PlaceReference], temporal: Optional[Date]) -> None:
|
12
|
-
self.spatial = spatial
|
13
|
-
self.temporal = temporal
|
14
|
-
|
15
|
-
# ...existing code...
|
16
|
-
|
17
|
-
@property
|
18
|
-
def _as_dict_(self):
|
19
|
-
type_as_dict = {
|
20
|
-
'spatial': self.spatial if self.spatial else None,
|
21
|
-
'temporal': self. temporal if self.temporal else None
|
22
|
-
}
|
23
|
-
|
24
|
-
return Serialization.serialize_dict(type_as_dict)
|
25
|
-
|
26
|
-
@classmethod
|
27
|
-
def _from_json_(cls, data: dict):
|
28
|
-
"""
|
29
|
-
Create a Coverage instance from a JSON-dict (already parsed).
|
30
|
-
"""
|
31
|
-
from .PlaceReference import PlaceReference
|
32
|
-
from .Date import Date
|
33
|
-
|
34
|
-
spatial = PlaceReference._from_json_(data.get('spatial')) if data.get('spatial') else None
|
35
|
-
temporal = Date._from_json_(data.get('temporal')) if data.get('temporal') else None
|
36
|
-
return cls(spatial=spatial, temporal=temporal)
|
gedcomx/Group.py
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
from enum import Enum
|
2
|
-
from typing import List, Optional
|
3
|
-
|
4
|
-
from .Attribution import Attribution
|
5
|
-
from .Conclusion import ConfidenceLevel
|
6
|
-
from .Date import Date
|
7
|
-
from .EvidenceReference import EvidenceReference
|
8
|
-
from .Identifier import Identifier
|
9
|
-
from .Note import Note
|
10
|
-
from .PlaceReference import PlaceReference
|
11
|
-
from .SourceReference import SourceReference
|
12
|
-
from .Resource import Resource
|
13
|
-
|
14
|
-
from .TextValue import TextValue
|
15
|
-
from .Subject import Subject
|
16
|
-
|
17
|
-
class GroupRoleType(Enum):
|
18
|
-
def __init__(self) -> None:
|
19
|
-
super().__init__()
|
20
|
-
|
21
|
-
class GroupRole:
|
22
|
-
identifier = 'http://gedcomx.org/v1/GroupRole'
|
23
|
-
version = 'http://gedcomx.org/conceptual-model/v1'
|
24
|
-
|
25
|
-
def __init__(self, person: Resource,type: Optional[Enum], date: Optional[Date],details: Optional[str]) -> None:
|
26
|
-
pass
|
27
|
-
|
28
|
-
class Group(Subject):
|
29
|
-
identifier = 'http://gedcomx.org/v1/Group'
|
30
|
-
version = 'http://gedcomx.org/conceptual-model/v1'
|
31
|
-
|
32
|
-
def __init__(self, id: str | None, lang: str | None, sources: SourceReference | None, analysis: Resource | None, notes: Note | None, confidence: ConfidenceLevel | None, attribution: Attribution | None, extracted: bool | None, evidence: List[EvidenceReference] | None, media: List[SourceReference] | None, identifiers: List[Identifier] | None,
|
33
|
-
names: TextValue,
|
34
|
-
date: Optional[Date],
|
35
|
-
place: Optional[PlaceReference],
|
36
|
-
roles: Optional[List[GroupRole]]) -> None:
|
37
|
-
super().__init__(id, lang, sources, analysis, notes, confidence, attribution, extracted, evidence, media, identifiers)
|
gedcomx/Name.py
DELETED
@@ -1,276 +0,0 @@
|
|
1
|
-
from enum import Enum
|
2
|
-
from typing import List,Optional
|
3
|
-
from typing_extensions import Self
|
4
|
-
|
5
|
-
from .Attribution import Attribution
|
6
|
-
from .Conclusion import Conclusion, ConfidenceLevel
|
7
|
-
from .Date import Date
|
8
|
-
from .Note import Note
|
9
|
-
from .Serialization import Serialization
|
10
|
-
from .SourceReference import SourceReference
|
11
|
-
from .Resource import Resource
|
12
|
-
|
13
|
-
|
14
|
-
class NameType(Enum):
|
15
|
-
BirthName = "http://gedcomx.org/BirthName"
|
16
|
-
MarriedName = "http://gedcomx.org/MarriedName"
|
17
|
-
AlsoKnownAs = "http://gedcomx.org/AlsoKnownAs"
|
18
|
-
Nickname = "http://gedcomx.org/Nickname"
|
19
|
-
AdoptiveName = "http://gedcomx.org/AdoptiveName"
|
20
|
-
FormalName = "http://gedcomx.org/FormalName"
|
21
|
-
ReligiousName = "http://gedcomx.org/ReligiousName"
|
22
|
-
|
23
|
-
@property
|
24
|
-
def description(self):
|
25
|
-
descriptions = {
|
26
|
-
NameType.BirthName: "Name given at birth.",
|
27
|
-
NameType.MarriedName: "Name accepted at marriage.",
|
28
|
-
NameType.AlsoKnownAs: "\"Also known as\" name.",
|
29
|
-
NameType.Nickname: "Nickname.",
|
30
|
-
NameType.AdoptiveName: "Name given at adoption.",
|
31
|
-
NameType.FormalName: "A formal name, usually given to distinguish it from a name more commonly used.",
|
32
|
-
NameType.ReligiousName: "A name given at a religious rite or ceremony."
|
33
|
-
}
|
34
|
-
return descriptions.get(self, "No description available.")
|
35
|
-
|
36
|
-
class NamePartQualifier(Enum):
|
37
|
-
Title = "http://gedcomx.org/Title"
|
38
|
-
Primary = "http://gedcomx.org/Primary"
|
39
|
-
Secondary = "http://gedcomx.org/Secondary"
|
40
|
-
Middle = "http://gedcomx.org/Middle"
|
41
|
-
Familiar = "http://gedcomx.org/Familiar"
|
42
|
-
Religious = "http://gedcomx.org/Religious"
|
43
|
-
Family = "http://gedcomx.org/Family"
|
44
|
-
Maiden = "http://gedcomx.org/Maiden"
|
45
|
-
Patronymic = "http://gedcomx.org/Patronymic"
|
46
|
-
Matronymic = "http://gedcomx.org/Matronymic"
|
47
|
-
Geographic = "http://gedcomx.org/Geographic"
|
48
|
-
Occupational = "http://gedcomx.org/Occupational"
|
49
|
-
Characteristic = "http://gedcomx.org/Characteristic"
|
50
|
-
Postnom = "http://gedcomx.org/Postnom"
|
51
|
-
Particle = "http://gedcomx.org/Particle"
|
52
|
-
RootName = "http://gedcomx.org/RootName"
|
53
|
-
|
54
|
-
@property
|
55
|
-
def description(self):
|
56
|
-
descriptions = {
|
57
|
-
NamePartQualifier.Title: "A designation for honorifics (e.g., Dr., Rev., His Majesty, Haji), ranks (e.g., Colonel, General), positions (e.g., Count, Chief), or other titles (e.g., PhD, MD). Name part qualifiers of type Title SHOULD NOT provide a value.",
|
58
|
-
NamePartQualifier.Primary: "A designation for the most prominent name among names of that type (e.g., the primary given name). Name part qualifiers of type Primary SHOULD NOT provide a value.",
|
59
|
-
NamePartQualifier.Secondary: "A designation for a name that is not primary in its importance among names of that type. Name part qualifiers of type Secondary SHOULD NOT provide a value.",
|
60
|
-
NamePartQualifier.Middle: "Useful for cultures designating a middle name distinct from a given name and surname. Name part qualifiers of type Middle SHOULD NOT provide a value.",
|
61
|
-
NamePartQualifier.Familiar: "A designation for one's familiar name. Name part qualifiers of type Familiar SHOULD NOT provide a value.",
|
62
|
-
NamePartQualifier.Religious: "A name given for religious purposes. Name part qualifiers of type Religious SHOULD NOT provide a value.",
|
63
|
-
NamePartQualifier.Family: "A name that associates a person with a group, such as a clan, tribe, or patriarchal hierarchy. Name part qualifiers of type Family SHOULD NOT provide a value.",
|
64
|
-
NamePartQualifier.Maiden: "Original surname retained by women after adopting a new surname upon marriage. Name part qualifiers of type Maiden SHOULD NOT provide a value.",
|
65
|
-
NamePartQualifier.Patronymic: "A name derived from a father or paternal ancestor. Name part qualifiers of type Patronymic SHOULD NOT provide a value.",
|
66
|
-
NamePartQualifier.Matronymic: "A name derived from a mother or maternal ancestor. Name part qualifiers of type Matronymic SHOULD NOT provide a value.",
|
67
|
-
NamePartQualifier.Geographic: "A name derived from associated geography. Name part qualifiers of type Geographic SHOULD NOT provide a value.",
|
68
|
-
NamePartQualifier.Occupational: "A name derived from one's occupation. Name part qualifiers of type Occupational SHOULD NOT provide a value.",
|
69
|
-
NamePartQualifier.Characteristic: "A name derived from a characteristic. Name part qualifiers of type Characteristic SHOULD NOT provide a value.",
|
70
|
-
NamePartQualifier.Postnom: "A name mandated by law for populations in specific regions. Name part qualifiers of type Postnom SHOULD NOT provide a value.",
|
71
|
-
NamePartQualifier.Particle: "A grammatical designation for articles, prepositions, conjunctions, and other words used as name parts. Name part qualifiers of type Particle SHOULD NOT provide a value.",
|
72
|
-
NamePartQualifier.RootName: "The 'root' of a name part, as distinguished from prefixes or suffixes (e.g., the root of 'Wilkówna' is 'Wilk'). A RootName qualifier MUST provide a value property."
|
73
|
-
}
|
74
|
-
return descriptions.get(self, "No description available.")
|
75
|
-
|
76
|
-
class NamePartType(Enum):
|
77
|
-
Prefix = "http://gedcomx.org/Prefix"
|
78
|
-
Suffix = "http://gedcomx.org/Suffix"
|
79
|
-
Given = "http://gedcomx.org/Given"
|
80
|
-
Surname = "http://gedcomx.org/Surname"
|
81
|
-
|
82
|
-
@property
|
83
|
-
def description(self):
|
84
|
-
descriptions = {
|
85
|
-
NamePartType.Prefix: "A name prefix.",
|
86
|
-
NamePartType.Suffix: "A name suffix.",
|
87
|
-
NamePartType.Given: "A given name.",
|
88
|
-
NamePartType.Surname: "A surname."
|
89
|
-
}
|
90
|
-
return descriptions.get(self, "No description available.")
|
91
|
-
|
92
|
-
class NamePart:
|
93
|
-
identifier = 'http://gedcomx.org/v1/NamePart'
|
94
|
-
version = 'http://gedcomx.org/conceptual-model/v1'
|
95
|
-
|
96
|
-
def __init__(self,
|
97
|
-
type: Optional[NamePartType] = None,
|
98
|
-
value: Optional[str] = None,
|
99
|
-
qualifiers: Optional[List[NamePartQualifier]] = []) -> None:
|
100
|
-
self.type = type
|
101
|
-
self.value = value
|
102
|
-
self.qualifiers = qualifiers
|
103
|
-
|
104
|
-
def _as_dict_(self):
|
105
|
-
return Serialization.serialize_dict(
|
106
|
-
{'type': self.type.value if self.type else None,
|
107
|
-
'value': self.value if self.value else None,
|
108
|
-
'qualifiers': [qualifier.value for qualifier in self.qualifiers] if self.qualifiers else None})
|
109
|
-
|
110
|
-
def __eq__(self, other):
|
111
|
-
if not isinstance(other, NamePart):
|
112
|
-
return NotImplemented
|
113
|
-
return (self.type == other.type and
|
114
|
-
self.value == other.value and
|
115
|
-
self.qualifiers == other.qualifiers)
|
116
|
-
|
117
|
-
class NameForm:
|
118
|
-
identifier = 'http://gedcomx.org/v1/NameForm'
|
119
|
-
version = 'http://gedcomx.org/conceptual-model/v1'
|
120
|
-
|
121
|
-
def __init__(self, lang: Optional[str] = 'en', fullText: Optional[str] = None,parts: Optional[List[NamePart]] = []) -> None:
|
122
|
-
self.lang = lang
|
123
|
-
self.fullText = fullText
|
124
|
-
self.parts = parts
|
125
|
-
|
126
|
-
@property
|
127
|
-
def _as_dict_(self):
|
128
|
-
return Serialization.serialize_dict(
|
129
|
-
{'lang': self.lang,
|
130
|
-
'fullText': self.fullText,
|
131
|
-
'parts': [part._as_dict_() for part in self.parts] if self.parts else None})
|
132
|
-
|
133
|
-
def _fulltext_parts(self):
|
134
|
-
pass
|
135
|
-
|
136
|
-
class Name(Conclusion):
|
137
|
-
identifier = 'http://gedcomx.org/v1/Name'
|
138
|
-
version = 'http://gedcomx.org/conceptual-model/v1'
|
139
|
-
|
140
|
-
@staticmethod
|
141
|
-
def simple(text: str):
|
142
|
-
"""
|
143
|
-
Takes a string and returns a GedcomX Name Object
|
144
|
-
"""
|
145
|
-
if text:
|
146
|
-
text = text.replace("/","")
|
147
|
-
parts = text.rsplit(' ', 1)
|
148
|
-
|
149
|
-
# Assign val1 and val2 based on the split
|
150
|
-
given = parts[0] if len(parts) > 1 else ""
|
151
|
-
surname = parts[1] if len(parts) > 1 else parts[0]
|
152
|
-
|
153
|
-
# Remove any '/' characters from both val1 and val2
|
154
|
-
#given = given.replace('/', '')
|
155
|
-
#surname = surname.replace('/', '')
|
156
|
-
|
157
|
-
given_name_part = NamePart(type = NamePartType.Given, value=given)
|
158
|
-
surname_part = NamePart(type = NamePartType.Surname, value=surname)
|
159
|
-
|
160
|
-
name_form = NameForm(fullText=text,parts=[given_name_part,surname_part])
|
161
|
-
name = Name(type=NameType.BirthName,nameForms=[name_form])
|
162
|
-
else:
|
163
|
-
name = Name()
|
164
|
-
return name
|
165
|
-
|
166
|
-
def __init__(self, id: str = None,
|
167
|
-
lang: str = 'en',
|
168
|
-
sources: Optional[List[SourceReference]] = None,
|
169
|
-
analysis: Resource = None,
|
170
|
-
notes: Optional[List[Note]] = None,
|
171
|
-
confidence: Optional[ConfidenceLevel] = None,
|
172
|
-
attribution: Optional[Attribution] = None,
|
173
|
-
type: Optional[NameType] = None,
|
174
|
-
nameForms: Optional[List[NameForm]]= None,
|
175
|
-
date: Optional[Date] = None) -> None:
|
176
|
-
super().__init__(id, lang, sources, analysis, notes, confidence, attribution)
|
177
|
-
self.type = type
|
178
|
-
self.nameForms = nameForms if nameForms else []
|
179
|
-
self.date = date
|
180
|
-
|
181
|
-
def _add_name_part(self, namepart_to_add: NamePart):
|
182
|
-
if namepart_to_add and isinstance(namepart_to_add, NamePart):
|
183
|
-
for current_namepart in self.nameForms[0].parts:
|
184
|
-
if namepart_to_add == current_namepart:
|
185
|
-
return False
|
186
|
-
self.nameForms[0].parts.append(namepart_to_add)
|
187
|
-
|
188
|
-
@property
|
189
|
-
def _as_dict_(self):
|
190
|
-
def _serialize(value):
|
191
|
-
if isinstance(value, (str, int, float, bool, type(None))):
|
192
|
-
return value
|
193
|
-
elif isinstance(value, dict):
|
194
|
-
return {k: _serialize(v) for k, v in value.items()}
|
195
|
-
elif isinstance(value, (list, tuple, set)):
|
196
|
-
return [_serialize(v) for v in value]
|
197
|
-
elif hasattr(value, "_as_dict_"):
|
198
|
-
return value._as_dict_
|
199
|
-
else:
|
200
|
-
return str(value) # fallback for unknown objects
|
201
|
-
|
202
|
-
name_as_dict = super()._as_dict_
|
203
|
-
|
204
|
-
name_as_dict.update( {
|
205
|
-
'type':self.type.value if self.type else None,
|
206
|
-
'nameForms': [nameForm._as_dict_ for nameForm in self.nameForms],
|
207
|
-
'date': self.date._as_dict_ if self.date else None})
|
208
|
-
|
209
|
-
#del name_as_dict['id']
|
210
|
-
# Serialize and exclude None values
|
211
|
-
for key, value in name_as_dict.items():
|
212
|
-
if value is not None:
|
213
|
-
name_as_dict[key] = _serialize(value)
|
214
|
-
|
215
|
-
# 3) merge and filter out None *at the top level*
|
216
|
-
return {
|
217
|
-
k: v
|
218
|
-
for k, v in name_as_dict.items()
|
219
|
-
if v is not None
|
220
|
-
}
|
221
|
-
|
222
|
-
return name_as_dict
|
223
|
-
|
224
|
-
class QuickName():
|
225
|
-
def __new__(cls,name: str) -> Name:
|
226
|
-
obj = Name(nameForms=[NameForm(fullText=name)])
|
227
|
-
return obj
|
228
|
-
|
229
|
-
def ensure_list(val):
|
230
|
-
if val is None:
|
231
|
-
return []
|
232
|
-
return val if isinstance(val, list) else [val]
|
233
|
-
|
234
|
-
NamePart._from_json_ = classmethod(lambda cls, data: NamePart(
|
235
|
-
type=NamePartType(data['type']) if 'type' in data else None,
|
236
|
-
value=data.get('value'),
|
237
|
-
qualifiers=[NamePartQualifier(q) for q in ensure_list(data.get('qualifiers'))]
|
238
|
-
))
|
239
|
-
|
240
|
-
NamePart._to_dict_ = lambda self: {
|
241
|
-
'type': self.type.value if self.type else None,
|
242
|
-
'value': self.value,
|
243
|
-
'qualifiers': [q.value for q in self.qualifiers] if self.qualifiers else []
|
244
|
-
}
|
245
|
-
|
246
|
-
|
247
|
-
# NameForm
|
248
|
-
NameForm._from_json_ = classmethod(lambda cls, data: NameForm(
|
249
|
-
lang=data.get('lang', 'en'),
|
250
|
-
fullText=data.get('fullText'),
|
251
|
-
parts=[NamePart._from_json_(p) for p in ensure_list(data.get('parts'))]
|
252
|
-
))
|
253
|
-
|
254
|
-
NameForm._to_dict_ = lambda self: {
|
255
|
-
'lang': self.lang,
|
256
|
-
'fullText': self.fullText,
|
257
|
-
'parts': [p._to_dict_() for p in self.parts] if self.parts else []
|
258
|
-
}
|
259
|
-
|
260
|
-
|
261
|
-
# Name
|
262
|
-
Name._from_json_ = classmethod(lambda cls, data: cls(
|
263
|
-
id=data.get('id'),
|
264
|
-
lang=data.get('lang', 'en'),
|
265
|
-
sources=[SourceReference._from_json_(s) for s in ensure_list(data.get('sources'))],
|
266
|
-
analysis=Resource._from_json_(data['analysis']) if data.get('analysis') else None,
|
267
|
-
notes=[Note._from_json_(n) for n in ensure_list(data.get('notes'))],
|
268
|
-
confidence=ConfidenceLevel._from_json_(data['confidence']) if data.get('confidence') else None,
|
269
|
-
attribution=Attribution._from_json_(data['attribution']) if data.get('attribution') else None,
|
270
|
-
type=NameType(data['type']) if data.get('type') else None,
|
271
|
-
nameForms=[NameForm._from_json_(nf) for nf in ensure_list(data.get('nameForms'))],
|
272
|
-
date=Date._from_json_(data['date']) if data.get('date') else None
|
273
|
-
))
|
274
|
-
|
275
|
-
|
276
|
-
|
gedcomx/PlaceDescription.py
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
from typing import List, Optional
|
2
|
-
|
3
|
-
from .Attribution import Attribution
|
4
|
-
from .Conclusion import ConfidenceLevel
|
5
|
-
from .Date import Date
|
6
|
-
from .EvidenceReference import EvidenceReference
|
7
|
-
from .Identifier import IdentifierList
|
8
|
-
from .Note import Note
|
9
|
-
from .SourceReference import SourceReference
|
10
|
-
from .TextValue import TextValue
|
11
|
-
from .Resource import Resource
|
12
|
-
from .Serialization import Serialization
|
13
|
-
from .Subject import Subject
|
14
|
-
from .URI import URI
|
15
|
-
|
16
|
-
class PlaceDescription(Subject):
|
17
|
-
identifier = "http://gedcomx.org/v1/PlaceDescription"
|
18
|
-
version = 'http://gedcomx.org/conceptual-model/v1'
|
19
|
-
|
20
|
-
def __init__(self, id: Optional[str] =None,
|
21
|
-
lang: str = 'en',
|
22
|
-
sources: Optional[List[SourceReference]] = None,
|
23
|
-
analysis: Optional[Resource] = None,
|
24
|
-
notes: Optional[List[Note]] =None,
|
25
|
-
confidence: Optional[ConfidenceLevel] = None,
|
26
|
-
attribution: Optional[Attribution] = None,
|
27
|
-
extracted: Optional[bool] = None,
|
28
|
-
evidence: Optional[List[EvidenceReference]] = None,
|
29
|
-
media: Optional[List[SourceReference]] = None,
|
30
|
-
identifiers: Optional[IdentifierList] = None,
|
31
|
-
names: Optional[List[TextValue]] = None,
|
32
|
-
type: Optional[str] = None,
|
33
|
-
place: Optional[URI] = None,
|
34
|
-
jurisdiction: Optional["Resource | PlaceDescription"] = None, # PlaceDescription
|
35
|
-
latitude: Optional[float] = None,
|
36
|
-
longitude: Optional[float] = None,
|
37
|
-
temporalDescription: Optional[Date] = None,
|
38
|
-
spatialDescription: Optional[Resource] = None,) -> None:
|
39
|
-
|
40
|
-
super().__init__(id, lang, sources, analysis, notes, confidence, attribution, extracted, evidence, media, identifiers)
|
41
|
-
self.names = names
|
42
|
-
self.type = type
|
43
|
-
self.place = place
|
44
|
-
self.jurisdiction = jurisdiction
|
45
|
-
self.latitide = latitude
|
46
|
-
self.longitute = longitude
|
47
|
-
self.temporalDescription = temporalDescription
|
48
|
-
self.spacialDescription = spatialDescription
|
49
|
-
|
50
|
-
@property
|
51
|
-
def _as_dict_(self):
|
52
|
-
type_as_dict = super()._as_dict_
|
53
|
-
type_as_dict.update({
|
54
|
-
"names": [n for n in self.names] if self.names else None,
|
55
|
-
"type": self.type if self.type else None,
|
56
|
-
"place": self.place._as_dict_ if self.place else None,
|
57
|
-
"jurisdiction": self.jurisdiction._as_dict_ if self.jurisdiction else None,
|
58
|
-
"latitude": float(self.latitide) if self.latitide else None,
|
59
|
-
"longitude": float(self.longitute) if self.longitute else None,
|
60
|
-
"temporalDescription": self.temporalDescription if self.temporalDescription else None,
|
61
|
-
"spatialDescription": self.spacialDescription._as_dict_ if self.spacialDescription else None
|
62
|
-
})
|
63
|
-
return Serialization.serialize_dict(type_as_dict)
|
64
|
-
|
65
|
-
@classmethod
|
66
|
-
def _from_json_(cls, data: dict):
|
67
|
-
"""
|
68
|
-
Create a PlaceDescription instance from a JSON-dict (already parsed).
|
69
|
-
"""
|
70
|
-
return Serialization.deserialize(data, PlaceDescription)
|
gedcomx/PlaceReference.py
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
|
-
from .Resource import Resource
|
4
|
-
from .Serialization import Serialization
|
5
|
-
|
6
|
-
class PlaceReference:
|
7
|
-
identifier = 'http://gedcomx.org/v1/PlaceReference'
|
8
|
-
version = 'http://gedcomx.org/conceptual-model/v1'
|
9
|
-
|
10
|
-
def __init__(self,
|
11
|
-
original: Optional[str] = None,
|
12
|
-
description: Optional[Resource] = None) -> None:
|
13
|
-
self.original = original
|
14
|
-
self.description = description
|
15
|
-
|
16
|
-
@property
|
17
|
-
def _as_dict_(self):
|
18
|
-
type_as_dict = {
|
19
|
-
'original': self.original,
|
20
|
-
'description': self.description._as_dict_ if self.description else None
|
21
|
-
}
|
22
|
-
return Serialization.serialize_dict(type_as_dict)
|
23
|
-
|
24
|
-
@classmethod
|
25
|
-
def _from_json_(cls, data):
|
26
|
-
|
27
|
-
return Serialization.deserialize(data, PlaceReference)
|
28
|
-
|
29
|
-
|
30
|
-
|
gedcomx/Qualifier.py
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
|
-
class Qualifier:
|
4
|
-
identifier = 'http://gedcomx.org/v1/Qualifier'
|
5
|
-
version = 'http://gedcomx.org/conceptual-model/v1'
|
6
|
-
|
7
|
-
def __init__(self, name: str, value: Optional[str]) -> None:
|
8
|
-
self.name = name
|
9
|
-
self.value = value
|
10
|
-
|
11
|
-
@property
|
12
|
-
def __as_dict__(self):
|
13
|
-
from .Serialization import serialize_to_dict
|
14
|
-
|
15
|
-
data = {
|
16
|
-
"name":self.name if self.name else None,
|
17
|
-
"value":self.value if self.value else None
|
18
|
-
}
|
19
|
-
|
20
|
-
return serialize_to_dict(data,False)
|
21
|
-
|
22
|
-
# Qualifier
|
23
|
-
Qualifier._from_json_ = classmethod(lambda cls, data: Qualifier(
|
24
|
-
name=data.get('name'),
|
25
|
-
value=data.get('value')
|
26
|
-
))
|
27
|
-
|