gedcom-x 0.5.7__py3-none-any.whl → 0.5.9__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.7.dist-info → gedcom_x-0.5.9.dist-info}/METADATA +1 -1
- gedcom_x-0.5.9.dist-info/RECORD +56 -0
- gedcomx/Extensions/rs10/rsLink.py +110 -60
- gedcomx/TopLevelTypeCollection.py +1 -1
- gedcomx/__init__.py +43 -42
- gedcomx/address.py +217 -0
- gedcomx/{Agent.py → agent.py} +107 -34
- gedcomx/attribution.py +115 -0
- gedcomx/{Conclusion.py → conclusion.py} +120 -51
- gedcomx/{Converter.py → converter.py} +261 -116
- gedcomx/coverage.py +64 -0
- gedcomx/{Date.py → date.py} +43 -9
- gedcomx/{Document.py → document.py} +60 -12
- gedcomx/{Event.py → event.py} +88 -31
- gedcomx/evidence_reference.py +20 -0
- gedcomx/{Fact.py → fact.py} +81 -74
- gedcomx/{Gedcom.py → gedcom.py} +10 -0
- gedcomx/{Gedcom5x.py → gedcom5x.py} +31 -21
- gedcomx/gedcom7/Exceptions.py +9 -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/gedcom7.py +160 -0
- gedcomx/gedcom7/logger.py +19 -0
- gedcomx/{GedcomX.py → gedcomx.py} +109 -106
- gedcomx/gender.py +91 -0
- gedcomx/group.py +72 -0
- gedcomx/{Identifier.py → identifier.py} +48 -21
- gedcomx/{LoggingHub.py → logging_hub.py} +19 -0
- gedcomx/{Mutations.py → mutations.py} +59 -30
- gedcomx/{Name.py → name.py} +88 -47
- gedcomx/note.py +105 -0
- gedcomx/online_account.py +19 -0
- gedcomx/{Person.py → person.py} +61 -41
- gedcomx/{PlaceDescription.py → place_description.py} +71 -23
- gedcomx/{PlaceReference.py → place_reference.py} +32 -10
- gedcomx/{Qualifier.py → qualifier.py} +20 -4
- gedcomx/relationship.py +156 -0
- gedcomx/resource.py +112 -0
- gedcomx/serialization.py +794 -0
- gedcomx/source_citation.py +37 -0
- gedcomx/source_description.py +401 -0
- gedcomx/{SourceReference.py → source_reference.py} +56 -21
- gedcomx/subject.py +122 -0
- gedcomx/textvalue.py +89 -0
- gedcomx/{Translation.py → translation.py} +4 -4
- gedcomx/uri.py +273 -0
- gedcom_x-0.5.7.dist-info/RECORD +0 -49
- gedcomx/Address.py +0 -131
- gedcomx/Attribution.py +0 -91
- gedcomx/Coverage.py +0 -37
- gedcomx/EvidenceReference.py +0 -11
- gedcomx/Gender.py +0 -65
- gedcomx/Group.py +0 -37
- gedcomx/Note.py +0 -73
- gedcomx/OnlineAccount.py +0 -10
- gedcomx/Relationship.py +0 -97
- gedcomx/Resource.py +0 -85
- gedcomx/Serialization.py +0 -816
- gedcomx/SourceCitation.py +0 -25
- gedcomx/SourceDescription.py +0 -314
- gedcomx/Subject.py +0 -59
- gedcomx/TextValue.py +0 -35
- gedcomx/URI.py +0 -105
- {gedcom_x-0.5.7.dist-info → gedcom_x-0.5.9.dist-info}/WHEEL +0 -0
- {gedcom_x-0.5.7.dist-info → gedcom_x-0.5.9.dist-info}/top_level.txt +0 -0
- /gedcomx/{Exceptions.py → exceptions.py} +0 -0
- /gedcomx/{ExtensibleEnum.py → extensible_enum.py} +0 -0
gedcomx/textvalue.py
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
from typing import Any, Optional, Dict
|
2
|
+
|
3
|
+
"""
|
4
|
+
======================================================================
|
5
|
+
Project: Gedcom-X
|
6
|
+
File: textvalue.py
|
7
|
+
Author: David J. Cartwright
|
8
|
+
Purpose:
|
9
|
+
|
10
|
+
Created: 2025-08-25
|
11
|
+
Updated:
|
12
|
+
- 2025-09-03 _from_json_ refactor
|
13
|
+
- 2025-09-04 added _str_ and _repr_ dunders
|
14
|
+
|
15
|
+
======================================================================
|
16
|
+
"""
|
17
|
+
|
18
|
+
"""
|
19
|
+
======================================================================
|
20
|
+
GEDCOM Module Types
|
21
|
+
======================================================================
|
22
|
+
"""
|
23
|
+
from .logging_hub import hub, logging
|
24
|
+
"""
|
25
|
+
======================================================================
|
26
|
+
Logging
|
27
|
+
======================================================================
|
28
|
+
"""
|
29
|
+
log = logging.getLogger("gedcomx")
|
30
|
+
serial_log = "gedcomx.serialization"
|
31
|
+
#=====================================================================
|
32
|
+
|
33
|
+
class TextValue:
|
34
|
+
identifier = 'http://gedcomx.org/v1/TextValue'
|
35
|
+
version = 'http://gedcomx.org/conceptual-model/v1'
|
36
|
+
|
37
|
+
def __init__(self, value: Optional[str] = None, lang: Optional[str] = None) -> None:
|
38
|
+
self.lang = lang
|
39
|
+
self.value = value
|
40
|
+
|
41
|
+
def _append_to_value(self, value_to_append):
|
42
|
+
if not isinstance(value_to_append, str):
|
43
|
+
raise ValueError(f"Cannot append object of type {type(value_to_append)}.")
|
44
|
+
if self.value is None: self.value = value_to_append
|
45
|
+
else: self.value += ' ' + value_to_append
|
46
|
+
|
47
|
+
@property
|
48
|
+
def _as_dict_(self):
|
49
|
+
from .serialization import Serialization
|
50
|
+
return Serialization.serialize(self)
|
51
|
+
type_as_dict = {}
|
52
|
+
if self.lang is not None: type_as_dict['lang'] = self.lang
|
53
|
+
if self.value is not None: type_as_dict['value'] = self.value
|
54
|
+
return type_as_dict if type_as_dict != {} else None
|
55
|
+
|
56
|
+
def __str__(self):
|
57
|
+
return f"{self.value} ({self.lang})"
|
58
|
+
|
59
|
+
def __eq__(self, other: object) -> bool:
|
60
|
+
if isinstance(other,TextValue):
|
61
|
+
if self.value.strip() == other.value.strip():
|
62
|
+
return True
|
63
|
+
return False
|
64
|
+
|
65
|
+
# ...existing code...
|
66
|
+
|
67
|
+
@classmethod
|
68
|
+
def _from_json_(cls, data: Any, context: Any = None) -> "TextValue":
|
69
|
+
"""
|
70
|
+
Create a TextValue from JSON.
|
71
|
+
- Accepts a dict like {"value": "...", "lang": "en"} or a plain string shorthand.
|
72
|
+
- Defaults lang to "en" if not provided.
|
73
|
+
"""
|
74
|
+
if not isinstance(data, dict):
|
75
|
+
raise TypeError(f"{cls.__name__}._from_json_ expected dict or str, got {type(data)}")
|
76
|
+
|
77
|
+
text_value_data: Dict[str, Any] = {}
|
78
|
+
|
79
|
+
if (v := data.get("value")) is None:
|
80
|
+
text_value_data["value"] = v
|
81
|
+
if (l := data.get("lang")) is None:
|
82
|
+
text_value_data["lang"] = l
|
83
|
+
|
84
|
+
return cls(**text_value_data)
|
85
|
+
|
86
|
+
def __repr__(self) -> str:
|
87
|
+
# Debug-friendly: unambiguous constructor-style representation
|
88
|
+
cls = self.__class__.__name__
|
89
|
+
return f"{cls}(value={self.value!r}, lang={self.lang!r})"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from . import *
|
2
|
-
from .
|
2
|
+
from .mutations import GedcomXEventOrFact
|
3
3
|
import re
|
4
4
|
'''
|
5
5
|
{'type': 'Object | Objects | Propertyof',
|
@@ -334,7 +334,7 @@ class Translater():
|
|
334
334
|
print(f"Translated {len(self.gedcomx.agents)} 'REPO' records to Agents")
|
335
335
|
for source in self.gedcom.sources:
|
336
336
|
self.parse_record(source)
|
337
|
-
print(f"Translated {len(self.gedcomx.
|
337
|
+
print(f"Translated {len(self.gedcomx.sourceDescriptions)} 'SOUR' records to SourceDescription")
|
338
338
|
|
339
339
|
for object in self.gedcom.objects:
|
340
340
|
self.parse_record(object)
|
@@ -1089,8 +1089,8 @@ class Translater():
|
|
1089
1089
|
if record.xref and record.xref.strip() == '':
|
1090
1090
|
import_log.warning(f"SOUR points to nothing: {record.describe()}")
|
1091
1091
|
return False
|
1092
|
-
if self.gedcomx.
|
1093
|
-
gxobject = SourceReference(descriptionId=record.xref, description=self.gedcomx.
|
1092
|
+
if self.gedcomx.sourceDescriptions.byId(record.xref):
|
1093
|
+
gxobject = SourceReference(descriptionId=record.xref, description=self.gedcomx.sourceDescriptions.byId(record.xref))
|
1094
1094
|
else:
|
1095
1095
|
import_log.warning(f'Could not find source with id: {record.xref}')
|
1096
1096
|
source_description = SourceDescription(id=record.xref)
|
gedcomx/uri.py
ADDED
@@ -0,0 +1,273 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from typing import Mapping, Sequence, Tuple, Union, Iterable
|
4
|
+
from urllib.parse import urlsplit, urlunsplit, urlencode, parse_qsl, SplitResult
|
5
|
+
from urllib.parse import urlunparse
|
6
|
+
|
7
|
+
"""
|
8
|
+
======================================================================
|
9
|
+
Project: Gedcom-X
|
10
|
+
File: uri.py
|
11
|
+
Author: David J. Cartwright
|
12
|
+
Purpose:
|
13
|
+
|
14
|
+
Created: 2025-08-25
|
15
|
+
Updated:
|
16
|
+
- 2025-09-03: _from_json_ refactor
|
17
|
+
|
18
|
+
======================================================================
|
19
|
+
"""
|
20
|
+
|
21
|
+
"""
|
22
|
+
======================================================================
|
23
|
+
GEDCOM Module Types
|
24
|
+
======================================================================
|
25
|
+
"""
|
26
|
+
from .logging_hub import hub, logging
|
27
|
+
"""
|
28
|
+
======================================================================
|
29
|
+
Logging
|
30
|
+
======================================================================
|
31
|
+
"""
|
32
|
+
log = logging.getLogger("gedcomx")
|
33
|
+
serial_log = "gedcomx.serialization"
|
34
|
+
#=====================================================================
|
35
|
+
|
36
|
+
_DEFAULT_SCHEME = "gedcomx"
|
37
|
+
|
38
|
+
# ---------- typing helpers for urlencode (Option A) ----------
|
39
|
+
QuerySeq = Sequence[Tuple[str, str]]
|
40
|
+
QueryMap = Mapping[str, str]
|
41
|
+
QueryLike = Union[str, QueryMap, QuerySeq]
|
42
|
+
|
43
|
+
def _encode_query(q: QueryLike) -> str:
|
44
|
+
"""Return a properly encoded query string."""
|
45
|
+
if isinstance(q, str):
|
46
|
+
return q
|
47
|
+
if isinstance(q, Mapping):
|
48
|
+
return urlencode(q, doseq=True) # mapping is fine
|
49
|
+
return urlencode(list(q), doseq=True) # coerce iterable to a sequence
|
50
|
+
|
51
|
+
|
52
|
+
class URI():
|
53
|
+
def __init__(self,
|
54
|
+
|
55
|
+
target=None,
|
56
|
+
scheme: str | None = None,
|
57
|
+
authority: str | None = None,
|
58
|
+
path: str | None = None,
|
59
|
+
params: str | None = None,
|
60
|
+
query: str | None = None,
|
61
|
+
fragment: str | None = None,
|
62
|
+
value: str | None = None
|
63
|
+
) -> None:
|
64
|
+
|
65
|
+
self.target = target
|
66
|
+
|
67
|
+
self.scheme = scheme
|
68
|
+
self.authority = authority
|
69
|
+
self.path = path
|
70
|
+
self.params = params
|
71
|
+
self.query = query
|
72
|
+
self.fragment = fragment
|
73
|
+
|
74
|
+
self._value = value
|
75
|
+
|
76
|
+
if self._value:
|
77
|
+
s = urlsplit(self._value)
|
78
|
+
self.scheme = s.scheme or _DEFAULT_SCHEME
|
79
|
+
self.authority=s.netloc
|
80
|
+
self.path=s.path
|
81
|
+
self.query=s.query
|
82
|
+
self.fragment=s.fragment
|
83
|
+
|
84
|
+
if self.target is not None:
|
85
|
+
#log.debug(f"Creating URI from Target {target}, most likely for serialization")
|
86
|
+
if hasattr(self.target,'id'):
|
87
|
+
log.debug(f"'{target}.id' found {target.id}, using as fragment")
|
88
|
+
self.fragment = self.target.id
|
89
|
+
if hasattr(self.target,'uri'):
|
90
|
+
#log.debug(f"'{target}.uri' found, copying")
|
91
|
+
self._value = target.uri._value
|
92
|
+
self.scheme = target.uri.scheme
|
93
|
+
self.authority = target.uri.authority
|
94
|
+
self.path = target.uri.path
|
95
|
+
self.query = target.uri.query
|
96
|
+
self.fragment = target.uri.fragment
|
97
|
+
elif isinstance(target,URI):
|
98
|
+
#log.debug(f"'{target} is a URI, copying")
|
99
|
+
self._value = target._value
|
100
|
+
self.scheme = target.scheme
|
101
|
+
self.authority = target.authority
|
102
|
+
self.path = target.path
|
103
|
+
self.query = target.query
|
104
|
+
self.fragment = target.fragment
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
elif isinstance(self.target,str):
|
109
|
+
#log.warning(f"Creating a URI from target type {type(target)} with data: {target}.")
|
110
|
+
s = urlsplit(self.target)
|
111
|
+
self.scheme = s.scheme or _DEFAULT_SCHEME
|
112
|
+
self.authority=s.netloc
|
113
|
+
self.path=s.path
|
114
|
+
self.query=s.query
|
115
|
+
self.fragment=s.fragment
|
116
|
+
else:
|
117
|
+
#log.warning(f"Unable to create URI from target type {type(target)} with data: {target}.")
|
118
|
+
self._value = target
|
119
|
+
#log.info(f"self.scheme = {self.scheme} self.authority={self.authority} self.path={self.path} self.query={self.query} self.fragment={self.fragment}")
|
120
|
+
|
121
|
+
parts = [
|
122
|
+
self.scheme or "",
|
123
|
+
self.authority or "",
|
124
|
+
self.path or "",
|
125
|
+
self.params or "",
|
126
|
+
self.query or "",
|
127
|
+
self.fragment or "",
|
128
|
+
]
|
129
|
+
if not any(parts):
|
130
|
+
raise ValueError()
|
131
|
+
|
132
|
+
@property
|
133
|
+
def value(self) -> str:
|
134
|
+
parts = [
|
135
|
+
self.scheme or "",
|
136
|
+
self.authority or "",
|
137
|
+
self.path or "",
|
138
|
+
self.params or "",
|
139
|
+
self.query or "",
|
140
|
+
self.fragment or "",
|
141
|
+
]
|
142
|
+
if not any(parts):
|
143
|
+
return None
|
144
|
+
return str(urlunparse(parts))
|
145
|
+
|
146
|
+
def split(self) -> SplitResult:
|
147
|
+
return SplitResult(self.scheme, self.authority, self.path, self.query, self.fragment)
|
148
|
+
|
149
|
+
def __str__(self) -> str:
|
150
|
+
return urlunsplit(self.split())
|
151
|
+
|
152
|
+
def __repr__(self) -> str:
|
153
|
+
return (f"scheme = {self.scheme}, authority={self.authority}, path={self.path}, query={self.query}, fragment={self.fragment}")
|
154
|
+
|
155
|
+
@property
|
156
|
+
def _as_dict_(self):
|
157
|
+
return self.value or self._value
|
158
|
+
|
159
|
+
@property
|
160
|
+
def uri(self):
|
161
|
+
return self
|
162
|
+
|
163
|
+
@classmethod
|
164
|
+
def from_url(cls,url):
|
165
|
+
return cls(target=url)
|
166
|
+
|
167
|
+
@classmethod
|
168
|
+
def _from_json_(cls,data,context=None):
|
169
|
+
return cls(value=data)
|
170
|
+
|
171
|
+
|
172
|
+
|
173
|
+
@dataclass(slots=True)
|
174
|
+
class _URI:
|
175
|
+
scheme: str = field(default=_DEFAULT_SCHEME)
|
176
|
+
authority: str = field(default="")
|
177
|
+
path: str = field(default="")
|
178
|
+
query: str = field(default="")
|
179
|
+
fragment: str = field(default="")
|
180
|
+
|
181
|
+
# ---------- constructors ----------
|
182
|
+
@classmethod
|
183
|
+
def from_url(cls, url: str, *, default_scheme: str = _DEFAULT_SCHEME) -> URI:
|
184
|
+
s = urlsplit(url)
|
185
|
+
scheme = s.scheme or default_scheme
|
186
|
+
return cls(scheme=scheme, authority=s.netloc, path=s.path, query=s.query, fragment=s.fragment)
|
187
|
+
|
188
|
+
@classmethod
|
189
|
+
def parse(cls, value: str) -> URI:
|
190
|
+
return cls.from_url(value)
|
191
|
+
|
192
|
+
@classmethod
|
193
|
+
def from_parts(
|
194
|
+
cls,
|
195
|
+
*,
|
196
|
+
scheme: str | None = None,
|
197
|
+
authority: str = "",
|
198
|
+
path: str = "",
|
199
|
+
query: QueryLike = "",
|
200
|
+
fragment: str = "",
|
201
|
+
) -> URI:
|
202
|
+
q = _encode_query(query)
|
203
|
+
return cls(scheme=scheme or _DEFAULT_SCHEME, authority=authority, path=path, query=q, fragment=fragment)
|
204
|
+
|
205
|
+
# ---------- views ----------
|
206
|
+
@property
|
207
|
+
def uri(self) -> str:
|
208
|
+
return str(self)
|
209
|
+
|
210
|
+
@property
|
211
|
+
def value(self) -> str:
|
212
|
+
return str(self)
|
213
|
+
|
214
|
+
def split(self) -> SplitResult:
|
215
|
+
return SplitResult(self.scheme, self.authority, self.path, self.query, self.fragment)
|
216
|
+
|
217
|
+
def __str__(self) -> str:
|
218
|
+
return urlunsplit(self.split())
|
219
|
+
|
220
|
+
@property
|
221
|
+
def _as_dict_(self) -> dict[str, object]:
|
222
|
+
return {
|
223
|
+
"scheme": self.scheme,
|
224
|
+
"authority": self.authority,
|
225
|
+
"path": self.path,
|
226
|
+
"query": self.query,
|
227
|
+
"fragment": self.fragment,
|
228
|
+
"value": str(self),
|
229
|
+
}
|
230
|
+
|
231
|
+
# Accepts {'resource': '...'} or a plain string
|
232
|
+
@classmethod
|
233
|
+
def _from_json_(cls, data: str | Mapping[str, object],context=None) -> URI:
|
234
|
+
return cls.from_parts(fragment="NOT IMPLIMENTED")
|
235
|
+
if isinstance(data, str):
|
236
|
+
return cls.from_parts(fragment="NOT IMPLIMENTED")
|
237
|
+
if isinstance(data, Mapping):
|
238
|
+
raw = data.get("resource") or data.get("value") or ""
|
239
|
+
if isinstance(raw, str) and raw:
|
240
|
+
return cls.from_url(raw)
|
241
|
+
raise ValueError(f"Cannot build URI from: {data!r}")
|
242
|
+
|
243
|
+
# ---------- functional updaters ----------
|
244
|
+
def with_scheme(self, scheme: str) -> URI: return self.replace(scheme=scheme)
|
245
|
+
def with_authority(self, authority: str) -> URI: return self.replace(authority=authority)
|
246
|
+
def with_path(self, path: str, *, join: bool = False) -> URI:
|
247
|
+
new_path = (self.path.rstrip("/") + "/" + path.lstrip("/")) if join else path
|
248
|
+
return self.replace(path=new_path)
|
249
|
+
def with_fragment(self, fragment: str | None) -> URI:
|
250
|
+
return self.replace(fragment=(fragment or ""))
|
251
|
+
def without_fragment(self) -> URI: return self.replace(fragment="")
|
252
|
+
def with_query(self, query: QueryLike) -> URI:
|
253
|
+
return self.replace(query=_encode_query(query))
|
254
|
+
def add_query_params(self, params: Mapping[str, Union[str, Iterable[str]]]) -> URI:
|
255
|
+
existing = parse_qsl(self.query, keep_blank_values=True)
|
256
|
+
for k, v in params.items():
|
257
|
+
if isinstance(v, str):
|
258
|
+
existing.append((k, v))
|
259
|
+
else:
|
260
|
+
for vv in v:
|
261
|
+
existing.append((k, vv))
|
262
|
+
return self.replace(query=urlencode(existing, doseq=True))
|
263
|
+
|
264
|
+
# ---------- helpers ----------
|
265
|
+
def replace(self, **kwargs) -> URI:
|
266
|
+
cls = type(self)
|
267
|
+
return cls(
|
268
|
+
scheme=kwargs.get("scheme", self.scheme or _DEFAULT_SCHEME),
|
269
|
+
authority=kwargs.get("authority", self.authority),
|
270
|
+
path=kwargs.get("path", self.path),
|
271
|
+
query=kwargs.get("query", self.query),
|
272
|
+
fragment=kwargs.get("fragment", self.fragment),
|
273
|
+
)
|
gedcom_x-0.5.7.dist-info/RECORD
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
gedcomx/Address.py,sha256=HPh-YZEkcxhzGGUxDWrrmAvKsyL__RthMJl6vXcMA80,4865
|
2
|
-
gedcomx/Agent.py,sha256=u7zIr6SNYREDhceOkj09uS6zjl3RXbix5QlQB7mxjz4,8844
|
3
|
-
gedcomx/Attribution.py,sha256=JESWw3U_momYDkQ6vknvaAW9DdIWwRRdQJwdD0UPAEI,3381
|
4
|
-
gedcomx/Conclusion.py,sha256=9VWEu6lphB0Y8L3YH3t2QcXt5xW5NdnSKXpa9eujU30,8781
|
5
|
-
gedcomx/Converter.py,sha256=aM8i8qIhzc9pJ3k75hFQSBkeRax2brucTefPYxENQHI,50968
|
6
|
-
gedcomx/Coverage.py,sha256=VR_lQDUgJ9rI-hHzOA8GxS_I1C_Du_3SvG57dzulXNI,1361
|
7
|
-
gedcomx/Date.py,sha256=I11mm2YEqUenxt-skphCHO-GWKPQrpMomOL_Utapzy0,2344
|
8
|
-
gedcomx/Document.py,sha256=DjL3HwpyCF9cOCdvpvrLu4Mxp7ZIYT1AkQEJGB3TSjY,2967
|
9
|
-
gedcomx/Event.py,sha256=j34nM5pZcmfSthdI87be6cGKGemHJky5xVaajmeSVK4,13321
|
10
|
-
gedcomx/EvidenceReference.py,sha256=WXZpmcKzwb3lYQmGVf-TY2IsbNG3fIInPY1khRjtOSg,348
|
11
|
-
gedcomx/Exceptions.py,sha256=0OdPM3euhBMgX8o61ZwPuKeN8zPuSuuDcSBFflVGFqk,587
|
12
|
-
gedcomx/ExtensibleEnum.py,sha256=DftCZLMBNul3C9hwh-rf0GE3SVdvylvyd5mt7bX_l6o,6535
|
13
|
-
gedcomx/Fact.py,sha256=r1Ct96moCIXCAd24Ho2aLCI12PGH2AoKIyjACtJT7go,24458
|
14
|
-
gedcomx/Gedcom.py,sha256=l_BuLBynQacDtpLjhs2Afrabfiqt2Opoo_5_7myI7Z4,1709
|
15
|
-
gedcomx/Gedcom5x.py,sha256=lbIEvK3h2b-IJoO9Fgmq_qc3nItzB_qTonqLafxYfXk,23137
|
16
|
-
gedcomx/GedcomX.py,sha256=p0PeJqS4bKXGsXY487JOdGNK4vIwARX7YeTDIqPeNNw,19000
|
17
|
-
gedcomx/Gender.py,sha256=vBkYJqhf1mN58Wrw9MvhbVJDNw1pM4-ktFW6mYja_Rw,2285
|
18
|
-
gedcomx/Group.py,sha256=VNI_cI_-YnJ9cHzwMmHD8qwDNMe89kEocPuQ67rwStA,1606
|
19
|
-
gedcomx/Identifier.py,sha256=1uhNO4Ll-_xLyVM-IYdywz7wTEwHEH44xx4JQId9F9c,8491
|
20
|
-
gedcomx/Logging.py,sha256=vBDOjawVXc4tCge1laYjy6_2Ves-fnGzG0m6NnLZejE,624
|
21
|
-
gedcomx/LoggingHub.py,sha256=f4z1r6WL3TdL1kg1eaCfCk7XEn9epCH5zUCXd1OT4mc,7793
|
22
|
-
gedcomx/Mutations.py,sha256=wtmoaiVS9Vw7Dzpfq34VQETBAVFvQnIlD5rbtSTopfs,6314
|
23
|
-
gedcomx/Name.py,sha256=esVS1nqvo5F5ggKQhnW4DYvww_hjXQF91oayLGG4LuU,18661
|
24
|
-
gedcomx/Note.py,sha256=hCwLDJYEQ-kR1-3rknHTx_nLq6ytBzi23sQukD8HHlg,2547
|
25
|
-
gedcomx/OnlineAccount.py,sha256=P24o98IXo_8XQoICYZPgALjdzS0q8t2l4DU3Od9KxyI,291
|
26
|
-
gedcomx/Person.py,sha256=tygyfHWqhbrH3z7TKPAyjJK14M7qu04mCGgXMgi7J_g,8057
|
27
|
-
gedcomx/PlaceDescription.py,sha256=oUih1T8jsUVcxdevPGuFpQOc34t4HoYc9ldr87ZH0IA,5591
|
28
|
-
gedcomx/PlaceReference.py,sha256=20HmaQUAlPrTjsra38j22NBsNqDBnvHZ5NuP6YzlizA,2111
|
29
|
-
gedcomx/Qualifier.py,sha256=iivgraoayJTYZUlkbSAKPzQ7msPYpBvTlmsEsXxz3zw,1778
|
30
|
-
gedcomx/Relationship.py,sha256=Et_72kRohBmWpWra2fS_-ha0YvEDZTZqkoD8HrerQW0,3693
|
31
|
-
gedcomx/Resource.py,sha256=HIOoKlVZtEp13j7sn4xkqRwRrYadqpiXswKpdJRe2Ns,2674
|
32
|
-
gedcomx/Serialization.py,sha256=ZIECHrG-PRZuS2SHGtfv1eg_2Rt-PHPbz4ivF7eH4p8,34041
|
33
|
-
gedcomx/SourceCitation.py,sha256=aW-lEb7bT9QU49GiBjJppFMBvtisR6fhVVuXjr5y4vQ,742
|
34
|
-
gedcomx/SourceDescription.py,sha256=yUBJXsn64OL0MAWSc3QPWrLt8RKYa1omGGp0FOLo-n8,14929
|
35
|
-
gedcomx/SourceReference.py,sha256=d5kNxqalCFlbRWD2kSJAMCexOrH_s1oXu9y_RUmCGa0,5189
|
36
|
-
gedcomx/Subject.py,sha256=2xPZiNjZDYSwLkloUPKDRa7F8_ql5zYMFJLS_9ayUtk,2609
|
37
|
-
gedcomx/TextValue.py,sha256=6B0wMxL0nigFNzhXZDhbTONvFGbnM2t2NcDZiZuu4Zw,1112
|
38
|
-
gedcomx/TopLevelTypeCollection.py,sha256=nvTO6GwFwEZk9jX4fVqhy75ygsshomNb20tnlExKqyY,1495
|
39
|
-
gedcomx/Translation.py,sha256=TZZTfuzjsx2glnUJwPrs0TrrShvLjygYUQ6cxhZXnMc,61398
|
40
|
-
gedcomx/URI.py,sha256=AuIECTwHUkp-2z0Q9iuA3Me1PiawFKZKCR4sAA64FE8,4270
|
41
|
-
gedcomx/Zip.py,sha256=lBxcv-Vip45884EHj56wZJJ5I36Q38UuHUidDxQBoS8,14
|
42
|
-
gedcomx/__init__.py,sha256=DfKVj46fhYtpM45NZnK333iDpt2WQ1XJXWsLcVCARNo,1704
|
43
|
-
gedcomx/Extensions/__init__.py,sha256=MQzi_whzlxiLiknUNh10hG8OVrNqJE38l6n-AwCssx8,24
|
44
|
-
gedcomx/Extensions/rs10/__init__.py,sha256=nSHoZiD8hsCAyE-KyRTuWSLqSJSFh12kSz7hqilAMps,26
|
45
|
-
gedcomx/Extensions/rs10/rsLink.py,sha256=uVmdTJl_atheO-pRpP3a5uUrazudf4R_tZvWSZIQdNk,4353
|
46
|
-
gedcom_x-0.5.7.dist-info/METADATA,sha256=bLAwaXozcWmQ0blAY2igIeEa3Lh-gQjX7NiPHuGESNs,4332
|
47
|
-
gedcom_x-0.5.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
48
|
-
gedcom_x-0.5.7.dist-info/top_level.txt,sha256=smVBF4nxSU-mzCd6idtRYTbYjPICMMi8pTqewEmqF8Y,8
|
49
|
-
gedcom_x-0.5.7.dist-info/RECORD,,
|
gedcomx/Address.py
DELETED
@@ -1,131 +0,0 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
import json
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
class Address:
|
7
|
-
"""A GedcomX Address Data Type
|
8
|
-
A GedcomX Address Data Type.
|
9
|
-
|
10
|
-
Represents a postal address according to the GedcomX conceptual model.
|
11
|
-
|
12
|
-
Args:
|
13
|
-
value (str, optional): A complete address as a single string.
|
14
|
-
city (str, optional): Name of the city or town.
|
15
|
-
country (str, optional): Name of the country.
|
16
|
-
postalCode (str, optional): Postal or ZIP code.
|
17
|
-
stateOrProvince (str, optional): Name of the state, province, or region.
|
18
|
-
street (str, optional): First street address line.
|
19
|
-
street2 (str, optional): Second street address line.
|
20
|
-
street3 (str, optional): Third street address line.
|
21
|
-
street4 (str, optional): Fourth street address line.
|
22
|
-
street5 (str, optional): Fifth street address line.
|
23
|
-
street6 (str, optional): Sixth street address line.
|
24
|
-
"""
|
25
|
-
|
26
|
-
identifier = "http://gedcomx.org/v1/Address"
|
27
|
-
version = 'http://gedcomx.org/conceptual-model/v1'
|
28
|
-
|
29
|
-
def __init__(self, value: Optional[str] = None,
|
30
|
-
city: Optional[str] = None,
|
31
|
-
country: Optional[str] = None,
|
32
|
-
postalCode: Optional[str] = None,
|
33
|
-
stateOrProvince: Optional[str] = None,
|
34
|
-
street: Optional[str] = None,
|
35
|
-
street2: Optional[str] = None,
|
36
|
-
street3: Optional[str] = None,
|
37
|
-
street4: Optional[str] = None,
|
38
|
-
street5: Optional[str] = None,
|
39
|
-
street6: Optional[str] = None):
|
40
|
-
|
41
|
-
self._value = value #TODO impliment a parser for date strings.
|
42
|
-
self.city = city
|
43
|
-
self.country = country
|
44
|
-
self.postalCode = postalCode
|
45
|
-
self.stateOrProvince = stateOrProvince
|
46
|
-
self.street = street
|
47
|
-
self.street2 = street2
|
48
|
-
self.street3 = street3
|
49
|
-
self.street4 = street4
|
50
|
-
self.street5 = street5
|
51
|
-
self.street6 = street6
|
52
|
-
|
53
|
-
@property
|
54
|
-
def value(self) -> str:
|
55
|
-
return ', '.join(filter(None, [
|
56
|
-
self.street, self.street2, self.street3,
|
57
|
-
self.street4, self.street5, self.street6,
|
58
|
-
self.city, self.stateOrProvince,
|
59
|
-
self.postalCode, self.country
|
60
|
-
]))
|
61
|
-
|
62
|
-
@value.setter
|
63
|
-
def value(self,value: str):
|
64
|
-
self._value = value
|
65
|
-
return
|
66
|
-
raise NotImplementedError("Parsing of a full address is not implimented.")
|
67
|
-
|
68
|
-
def _append(self,value):
|
69
|
-
if self._value:
|
70
|
-
self._value = self._value + ' ' + value
|
71
|
-
else:
|
72
|
-
self._value = value
|
73
|
-
|
74
|
-
def __eq__(self, other):
|
75
|
-
if not isinstance(other, self.__class__):
|
76
|
-
return False
|
77
|
-
|
78
|
-
return (
|
79
|
-
self.value == other.value and
|
80
|
-
self.city == other.city and
|
81
|
-
self.country == other.country and
|
82
|
-
self.postalCode == other.postalCode and
|
83
|
-
self.stateOrProvince == other.stateOrProvince and
|
84
|
-
self.street == other.street and
|
85
|
-
self.street2 == other.street2 and
|
86
|
-
self.street3 == other.street3 and
|
87
|
-
self.street4 == other.street4 and
|
88
|
-
self.street5 == other.street5 and
|
89
|
-
self.street6 == other.street6
|
90
|
-
)
|
91
|
-
|
92
|
-
def __str__(self) -> str:
|
93
|
-
# Combine non-empty address components into a formatted string
|
94
|
-
parts = [
|
95
|
-
self._value,
|
96
|
-
self.street,
|
97
|
-
self.street2,
|
98
|
-
self.street3,
|
99
|
-
self.street4,
|
100
|
-
self.street5,
|
101
|
-
self.street6,
|
102
|
-
self.city,
|
103
|
-
self.stateOrProvince,
|
104
|
-
self.postalCode,
|
105
|
-
self.country
|
106
|
-
]
|
107
|
-
|
108
|
-
# Filter out any parts that are None or empty strings
|
109
|
-
filtered_parts = [str(part) for part in parts if part]
|
110
|
-
|
111
|
-
# Join the remaining parts with a comma and space
|
112
|
-
return ', '.join(filtered_parts)
|
113
|
-
|
114
|
-
@property
|
115
|
-
def _as_dict_(self):
|
116
|
-
from .Serialization import Serialization
|
117
|
-
type_as_dict = {}
|
118
|
-
if self.city: type_as_dict["city"] = self.city
|
119
|
-
if self.country: type_as_dict["country"] = self.country
|
120
|
-
if self.postalCode: type_as_dict["postalCode"] = self.postalCode
|
121
|
-
if self.stateOrProvince: type_as_dict["stateOrProvince"] = self.stateOrProvince
|
122
|
-
if self.street: type_as_dict["street"] = self.street
|
123
|
-
if self.street2: type_as_dict["street2"] = self.street2
|
124
|
-
if self.street3: type_as_dict["street3"] = self.street3
|
125
|
-
if self.street4: type_as_dict["street4"] = self.street4
|
126
|
-
if self.street5: type_as_dict["street5"] = self.street5
|
127
|
-
if self.street6: type_as_dict["street6"] = self.street6
|
128
|
-
|
129
|
-
return Serialization.serialize_dict(type_as_dict)
|
130
|
-
|
131
|
-
|
gedcomx/Attribution.py
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
|
2
|
-
from datetime import datetime
|
3
|
-
from typing import Optional, Dict, Any
|
4
|
-
|
5
|
-
"""
|
6
|
-
======================================================================
|
7
|
-
Project: Gedcom-X
|
8
|
-
File: Attribution.py
|
9
|
-
Author: David J. Cartwright
|
10
|
-
Purpose:
|
11
|
-
|
12
|
-
Created: 2025-08-25
|
13
|
-
Updated:
|
14
|
-
- 2025-08-31: fixed _as_dict_ to deal with Resources and ignore empty fields
|
15
|
-
|
16
|
-
======================================================================
|
17
|
-
"""
|
18
|
-
|
19
|
-
"""
|
20
|
-
======================================================================
|
21
|
-
GEDCOM Module Types
|
22
|
-
======================================================================
|
23
|
-
"""
|
24
|
-
|
25
|
-
from .Agent import Agent
|
26
|
-
from .Resource import Resource
|
27
|
-
#=====================================================================
|
28
|
-
|
29
|
-
|
30
|
-
class Attribution:
|
31
|
-
"""Attribution Information for a Genealogy, Conclusion, Subject and child classes
|
32
|
-
|
33
|
-
Args:
|
34
|
-
contributor (Agent, optional): Contributor to object being attributed.
|
35
|
-
modified (timestamp, optional): timestamp for when this record was modified.
|
36
|
-
changeMessage (str, optional): Birth date (YYYY-MM-DD).
|
37
|
-
creator (Agent, optional): Creator of object being attributed.
|
38
|
-
created (timestamp, optional): timestamp for when this record was created
|
39
|
-
|
40
|
-
Raises:
|
41
|
-
|
42
|
-
"""
|
43
|
-
identifier = 'http://gedcomx.org/v1/Attribution'
|
44
|
-
version = 'http://gedcomx.org/conceptual-model/v1'
|
45
|
-
|
46
|
-
def __init__(self,contributor: Optional[Agent | Resource] = None,
|
47
|
-
modified: Optional[datetime] = None,
|
48
|
-
changeMessage: Optional[str] = None,
|
49
|
-
creator: Optional[Agent | Resource] = None,
|
50
|
-
created: Optional[datetime] = None) -> None:
|
51
|
-
|
52
|
-
self.contributor = contributor
|
53
|
-
self.modified = modified
|
54
|
-
self.changeMessage = changeMessage
|
55
|
-
self.creator = creator
|
56
|
-
self.created = created
|
57
|
-
|
58
|
-
@property
|
59
|
-
def _as_dict_(self) -> Dict[str, Any]:
|
60
|
-
"""
|
61
|
-
Serialize Attribution to a JSON-ready dict, skipping None values.
|
62
|
-
"""
|
63
|
-
from Serialization import Serialization
|
64
|
-
type_as_dict: Dict[str, Any] = {}
|
65
|
-
if self.contributor:
|
66
|
-
type_as_dict['contributor'] = Resource(target=self.contributor)._as_dict_
|
67
|
-
if self.modified:
|
68
|
-
type_as_dict['modified'] = self.modified if self.modified else None
|
69
|
-
if self.changeMessage:
|
70
|
-
type_as_dict['changeMessage'] = self.changeMessage if self.changeMessage else None
|
71
|
-
if self.creator:
|
72
|
-
type_as_dict['creator'] = Resource(target=self.creator)._as_dict_
|
73
|
-
if self.created:
|
74
|
-
type_as_dict['created'] = self.created if self.created else None
|
75
|
-
|
76
|
-
return Serialization.serialize_dict(type_as_dict)
|
77
|
-
|
78
|
-
@classmethod
|
79
|
-
def _from_json_(cls, data: Dict[str, Any]) -> 'Attribution':
|
80
|
-
"""
|
81
|
-
Construct Attribution from a dict (as parsed from JSON).
|
82
|
-
Handles 'created' and 'modified' as ISO strings or epoch ms ints.
|
83
|
-
"""
|
84
|
-
# contributor
|
85
|
-
|
86
|
-
"""
|
87
|
-
Create a Person instance from a JSON-dict (already parsed).
|
88
|
-
"""
|
89
|
-
from .Serialization import Serialization
|
90
|
-
|
91
|
-
return Serialization.deserialize(data, Attribution)
|