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.
Files changed (69) hide show
  1. {gedcom_x-0.5.7.dist-info → gedcom_x-0.5.9.dist-info}/METADATA +1 -1
  2. gedcom_x-0.5.9.dist-info/RECORD +56 -0
  3. gedcomx/Extensions/rs10/rsLink.py +110 -60
  4. gedcomx/TopLevelTypeCollection.py +1 -1
  5. gedcomx/__init__.py +43 -42
  6. gedcomx/address.py +217 -0
  7. gedcomx/{Agent.py → agent.py} +107 -34
  8. gedcomx/attribution.py +115 -0
  9. gedcomx/{Conclusion.py → conclusion.py} +120 -51
  10. gedcomx/{Converter.py → converter.py} +261 -116
  11. gedcomx/coverage.py +64 -0
  12. gedcomx/{Date.py → date.py} +43 -9
  13. gedcomx/{Document.py → document.py} +60 -12
  14. gedcomx/{Event.py → event.py} +88 -31
  15. gedcomx/evidence_reference.py +20 -0
  16. gedcomx/{Fact.py → fact.py} +81 -74
  17. gedcomx/{Gedcom.py → gedcom.py} +10 -0
  18. gedcomx/{Gedcom5x.py → gedcom5x.py} +31 -21
  19. gedcomx/gedcom7/Exceptions.py +9 -0
  20. gedcomx/gedcom7/GedcomStructure.py +94 -0
  21. gedcomx/gedcom7/Specification.py +347 -0
  22. gedcomx/gedcom7/__init__.py +26 -0
  23. gedcomx/gedcom7/g7interop.py +205 -0
  24. gedcomx/gedcom7/gedcom7.py +160 -0
  25. gedcomx/gedcom7/logger.py +19 -0
  26. gedcomx/{GedcomX.py → gedcomx.py} +109 -106
  27. gedcomx/gender.py +91 -0
  28. gedcomx/group.py +72 -0
  29. gedcomx/{Identifier.py → identifier.py} +48 -21
  30. gedcomx/{LoggingHub.py → logging_hub.py} +19 -0
  31. gedcomx/{Mutations.py → mutations.py} +59 -30
  32. gedcomx/{Name.py → name.py} +88 -47
  33. gedcomx/note.py +105 -0
  34. gedcomx/online_account.py +19 -0
  35. gedcomx/{Person.py → person.py} +61 -41
  36. gedcomx/{PlaceDescription.py → place_description.py} +71 -23
  37. gedcomx/{PlaceReference.py → place_reference.py} +32 -10
  38. gedcomx/{Qualifier.py → qualifier.py} +20 -4
  39. gedcomx/relationship.py +156 -0
  40. gedcomx/resource.py +112 -0
  41. gedcomx/serialization.py +794 -0
  42. gedcomx/source_citation.py +37 -0
  43. gedcomx/source_description.py +401 -0
  44. gedcomx/{SourceReference.py → source_reference.py} +56 -21
  45. gedcomx/subject.py +122 -0
  46. gedcomx/textvalue.py +89 -0
  47. gedcomx/{Translation.py → translation.py} +4 -4
  48. gedcomx/uri.py +273 -0
  49. gedcom_x-0.5.7.dist-info/RECORD +0 -49
  50. gedcomx/Address.py +0 -131
  51. gedcomx/Attribution.py +0 -91
  52. gedcomx/Coverage.py +0 -37
  53. gedcomx/EvidenceReference.py +0 -11
  54. gedcomx/Gender.py +0 -65
  55. gedcomx/Group.py +0 -37
  56. gedcomx/Note.py +0 -73
  57. gedcomx/OnlineAccount.py +0 -10
  58. gedcomx/Relationship.py +0 -97
  59. gedcomx/Resource.py +0 -85
  60. gedcomx/Serialization.py +0 -816
  61. gedcomx/SourceCitation.py +0 -25
  62. gedcomx/SourceDescription.py +0 -314
  63. gedcomx/Subject.py +0 -59
  64. gedcomx/TextValue.py +0 -35
  65. gedcomx/URI.py +0 -105
  66. {gedcom_x-0.5.7.dist-info → gedcom_x-0.5.9.dist-info}/WHEEL +0 -0
  67. {gedcom_x-0.5.7.dist-info → gedcom_x-0.5.9.dist-info}/top_level.txt +0 -0
  68. /gedcomx/{Exceptions.py → exceptions.py} +0 -0
  69. /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 .Mutations import GedcomXEventOrFact
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.source_descriptions)} 'SOUR' records to SourceDescription")
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.source_descriptions.byId(record.xref):
1093
- gxobject = SourceReference(descriptionId=record.xref, description=self.gedcomx.source_descriptions.byId(record.xref))
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
+ )
@@ -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)