gedcom-x 0.5.8__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 (45) hide show
  1. {gedcom_x-0.5.8.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 +109 -59
  4. gedcomx/__init__.py +1 -1
  5. gedcomx/address.py +102 -16
  6. gedcomx/agent.py +81 -24
  7. gedcomx/attribution.py +52 -28
  8. gedcomx/conclusion.py +97 -45
  9. gedcomx/converter.py +209 -79
  10. gedcomx/coverage.py +10 -1
  11. gedcomx/date.py +42 -8
  12. gedcomx/document.py +37 -7
  13. gedcomx/event.py +77 -20
  14. gedcomx/evidence_reference.py +9 -0
  15. gedcomx/fact.py +53 -54
  16. gedcomx/gedcom.py +10 -0
  17. gedcomx/gedcom5x.py +30 -20
  18. gedcomx/gedcom7/__init__.py +1 -1
  19. gedcomx/gedcomx.py +95 -93
  20. gedcomx/gender.py +21 -9
  21. gedcomx/group.py +9 -0
  22. gedcomx/identifier.py +47 -20
  23. gedcomx/logging_hub.py +19 -0
  24. gedcomx/mutations.py +10 -5
  25. gedcomx/name.py +74 -33
  26. gedcomx/note.py +50 -18
  27. gedcomx/online_account.py +9 -0
  28. gedcomx/person.py +44 -26
  29. gedcomx/place_description.py +54 -8
  30. gedcomx/place_reference.py +30 -8
  31. gedcomx/qualifier.py +19 -3
  32. gedcomx/relationship.py +55 -14
  33. gedcomx/resource.py +45 -18
  34. gedcomx/serialization.py +400 -421
  35. gedcomx/source_citation.py +16 -4
  36. gedcomx/source_description.py +181 -94
  37. gedcomx/source_reference.py +51 -16
  38. gedcomx/subject.py +59 -14
  39. gedcomx/textvalue.py +66 -12
  40. gedcomx/translation.py +3 -3
  41. gedcomx/uri.py +155 -3
  42. gedcom_x-0.5.8.dist-info/RECORD +0 -56
  43. {gedcom_x-0.5.8.dist-info → gedcom_x-0.5.9.dist-info}/WHEEL +0 -0
  44. {gedcom_x-0.5.8.dist-info → gedcom_x-0.5.9.dist-info}/top_level.txt +0 -0
  45. /gedcomx/gedcom7/{Gedcom7.py → gedcom7.py} +0 -0
gedcomx/conclusion.py CHANGED
@@ -1,8 +1,8 @@
1
- import base64
2
- import uuid
1
+
3
2
  import warnings
4
3
 
5
- from typing import List, Optional
4
+ from typing import Any, Optional, List
5
+
6
6
  """
7
7
  ======================================================================
8
8
  Project: Gedcom-X
@@ -12,7 +12,7 @@ from typing import List, Optional
12
12
 
13
13
  Created: 2025-08-25
14
14
  Updated:
15
- -
15
+ - 2025-09-03: _from_json_ refactor
16
16
 
17
17
  ======================================================================
18
18
  """
@@ -23,11 +23,21 @@ GEDCOM Module Type Imports
23
23
  ======================================================================
24
24
  """
25
25
  from .attribution import Attribution
26
- from .Extensions.rs10.rsLink import _rsLinkList, rsLink
26
+ from .Extensions.rs10.rsLink import _rsLinks, rsLink
27
+ from .identifier import make_uid
27
28
  from .note import Note
28
29
  from .qualifier import Qualifier
29
30
  from .resource import Resource, URI
30
31
  from .source_reference import SourceReference
32
+ from .logging_hub import hub, logging
33
+ """
34
+ ======================================================================
35
+ Logging
36
+ ======================================================================
37
+ """
38
+ log = logging.getLogger("gedcomx")
39
+ serial_log = "gedcomx.serialization"
40
+ #=====================================================================
31
41
 
32
42
 
33
43
 
@@ -131,17 +141,7 @@ class Conclusion:
131
141
  """
132
142
  identifier = 'http://gedcomx.org/v1/Conclusion'
133
143
  version = 'http://gedcomx.org/conceptual-model/v1'
134
-
135
- @staticmethod
136
- def default_id_generator():
137
- # Generate a standard UUID
138
- standard_uuid = uuid.uuid4()
139
- # Convert UUID to bytes
140
- uuid_bytes = standard_uuid.bytes
141
- # Encode bytes to a Base64 string
142
- short_uuid = base64.urlsafe_b64encode(uuid_bytes).rstrip(b'=').decode('utf-8')
143
- return short_uuid
144
-
144
+
145
145
  def __init__(self,
146
146
  id: Optional[str] = None,
147
147
  lang: Optional[str] = None,
@@ -152,11 +152,10 @@ class Conclusion:
152
152
  attribution: Optional[Attribution] = None,
153
153
  uri: Optional[Resource] = None,
154
154
  _max_note_count: int = 20,
155
- links: Optional[_rsLinkList] = None) -> None:
155
+ links: Optional[_rsLinks] = None) -> None:
156
156
 
157
- self._id_generator = Conclusion.default_id_generator
158
-
159
- self.id = id if id else None
157
+
158
+ self.id = id if id else make_uid()
160
159
  self.lang = lang
161
160
  self.sources = sources if sources else []
162
161
  self.analysis = analysis
@@ -164,8 +163,7 @@ class Conclusion:
164
163
  self.confidence = confidence
165
164
  self.attribution = attribution
166
165
  self.max_note_count = _max_note_count
167
- self.uri = uri if uri else URI(fragment=id if id else self.id)
168
- self.links = links if links else _rsLinkList() #NOTE This is not in specification, following FS format
166
+ self.links = links if links else _rsLinks() #NOTE This is not in specification, following FS format
169
167
 
170
168
  def add_note(self,note_to_add: Note):
171
169
  if self.notes and len(self.notes) >= self.max_note_count:
@@ -177,7 +175,7 @@ class Conclusion:
177
175
  return False
178
176
  self.notes.append(note_to_add)
179
177
 
180
- def add_source(self, source_to_add: SourceReference):
178
+ def add_source_reference(self, source_to_add: SourceReference):
181
179
  if source_to_add and isinstance(source_to_add,SourceReference):
182
180
  for current_source in self.sources:
183
181
  if source_to_add == current_source:
@@ -205,30 +203,84 @@ class Conclusion:
205
203
 
206
204
  @property
207
205
  def _as_dict_(self):
208
- from .serialization import Serialization
209
- type_as_dict = {}
210
-
211
- if self.id:
212
- type_as_dict['id'] = self.id
213
- if self.lang:
214
- type_as_dict['lang'] = self.lang
215
- if self.sources:
216
- type_as_dict['sources'] = [s._as_dict_ for s in self.sources if s]
217
- if self.analysis:
218
- type_as_dict['analysis'] = getattr(self.analysis, '_as_dict_', self.analysis)
219
- if self.notes:
220
- type_as_dict['notes'] = [
221
- (n._as_dict_ if hasattr(n, '_as_dict_') else n) for n in self.notes if n
222
- ]
223
- if self.confidence is not None:
224
- type_as_dict['confidence'] = self.confidence
225
- if self.attribution:
226
- type_as_dict['attribution'] = getattr(self.attribution, '_as_dict_', self.attribution)
227
- if self.links:
228
- type_as_dict['links'] = self.links._as_dict_
206
+ with hub.use(serial_log):
207
+ log.debug(f"Serializing 'Conclusion' with id: {self.id}")
208
+ type_as_dict = {}
209
+
210
+ if self.id:
211
+ type_as_dict['id'] = self.id
212
+ if self.lang:
213
+ type_as_dict['lang'] = self.lang
214
+ if self.sources and self.sources != []:
215
+ type_as_dict['sources'] = [s._as_dict_ for s in self.sources if s]
216
+ if self.analysis:
217
+ type_as_dict['analysis'] = getattr(self.analysis, '_as_dict_', self.analysis)
218
+ if self.notes and self.notes != []:
219
+ type_as_dict['notes'] = [
220
+ (n._as_dict_ if hasattr(n, '_as_dict_') else n) for n in self.notes if n
221
+ ]
222
+ if self.confidence is not None:
223
+ type_as_dict['confidence'] = self.confidence
224
+ if self.attribution is not None:
225
+ type_as_dict['attribution'] = self.attribution._as_dict_
226
+ if self.links is not None:
227
+ print(self.links)
228
+ type_as_dict['links'] = self.links._as_dict_
229
+ log.debug(f"'Conclusion' serialized with fields: {type_as_dict.keys()}")
230
+ if type_as_dict == {}: log.warning("serializing and empty 'Conclusion'")
229
231
 
230
- return Serialization.serialize_dict(type_as_dict)
232
+ return type_as_dict if type_as_dict != {} else None
233
+
231
234
 
235
+
236
+
237
+ @classmethod
238
+ def _dict_from_json_(cls, data: dict, context=None) -> dict:
239
+ conclusion = {}
240
+
241
+ # Scalars
242
+ if (id_ := data.get("id")) is not None:
243
+ conclusion["id"] = id_
244
+
245
+ if (lang := data.get("lang")) is not None:
246
+ conclusion["lang"] = lang
247
+
248
+ # Lists
249
+ if (sources := data.get("sources")) is not None:
250
+ conclusion["sources"] = [
251
+ SourceReference._from_json_(x, context) for x in sources
252
+ ]
253
+
254
+ if (notes := data.get("notes")) is not None:
255
+ conclusion["notes"] = [
256
+ Note._from_json_(x, context) for x in notes
257
+ ]
258
+
259
+ # Objects
260
+ if (analysis := data.get("analysis")) is not None:
261
+ # depending on your model, analysis might be a Resource or Document
262
+ conclusion["analysis"] = Resource._from_json_(analysis, context)
263
+
264
+ if (confidence := data.get("confidence")) is not None:
265
+ conclusion["confidence"] = ConfidenceLevel._from_json_(confidence, context)
266
+
267
+ if (attribution := data.get("attribution")) is not None:
268
+ conclusion["attribution"] = Attribution._from_json_(attribution, context)
269
+
270
+ if (uri := data.get("uri")) is not None:
271
+ conclusion["uri"] = URI(uri)
272
+
273
+ if (links := data.get("links")) is not None:
274
+ conclusion["links"] = _rsLinks._from_json_(links, context)
275
+ if isinstance(conclusion["links"],dict): assert False
276
+
277
+ # Constant / defaults
278
+ #conclusion["_max_note_count"] = 20
279
+
280
+ #return cls(**conclusion)
281
+ return conclusion
282
+
283
+
232
284
  def __eq__(self, other):
233
285
  if not isinstance(other, self.__class__):
234
286
  return False