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/coverage.py
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
"""
|
3
|
+
======================================================================
|
4
|
+
Project: Gedcom-X
|
5
|
+
File: coverage.py
|
6
|
+
Author: David J. Cartwright
|
7
|
+
Purpose:
|
8
|
+
|
9
|
+
Created: 2025-08-25
|
10
|
+
Updated:
|
11
|
+
- 2025-08-31:
|
12
|
+
|
13
|
+
======================================================================
|
14
|
+
"""
|
15
|
+
|
16
|
+
"""
|
17
|
+
======================================================================
|
18
|
+
GEDCOM Module Types
|
19
|
+
======================================================================
|
20
|
+
"""
|
21
|
+
from .date import Date
|
22
|
+
from .place_reference import PlaceReference
|
23
|
+
|
24
|
+
|
25
|
+
class Coverage:
|
26
|
+
identifier = 'http://gedcomx.org/v1/Coverage'
|
27
|
+
version = 'http://gedcomx.org/conceptual-model/v1'
|
28
|
+
|
29
|
+
def __init__(self,spatial: Optional[PlaceReference], temporal: Optional[Date]) -> None:
|
30
|
+
self.spatial = spatial
|
31
|
+
self.temporal = temporal
|
32
|
+
|
33
|
+
# ...existing code...
|
34
|
+
|
35
|
+
@property
|
36
|
+
def _as_dict_(self):
|
37
|
+
from .serialization import Serialization
|
38
|
+
type_as_dict = {}
|
39
|
+
if self.spatial:
|
40
|
+
type_as_dict['spatial'] = getattr(self.spatial, '_as_dict_', self.spatial)
|
41
|
+
if self.temporal: # (fixed: no space after the dot)
|
42
|
+
type_as_dict['temporal'] = getattr(self.temporal, '_as_dict_', self.temporal)
|
43
|
+
return Serialization.serialize_dict(type_as_dict)
|
44
|
+
|
45
|
+
@classmethod
|
46
|
+
def _from_json_(cls, data: dict):
|
47
|
+
"""
|
48
|
+
Create a Coverage instance from a JSON-dict (already parsed).
|
49
|
+
"""
|
50
|
+
from .place_reference import PlaceReference
|
51
|
+
from .date import Date
|
52
|
+
|
53
|
+
spatial = PlaceReference._from_json_(data.get('spatial')) if data.get('spatial') else None
|
54
|
+
temporal = Date._from_json_(data.get('temporal')) if data.get('temporal') else None
|
55
|
+
return cls(spatial=spatial, temporal=temporal)
|
gedcomx/{Date.py → date.py}
RENAMED
@@ -4,6 +4,8 @@ from dateutil import parser
|
|
4
4
|
import time
|
5
5
|
|
6
6
|
|
7
|
+
|
8
|
+
|
7
9
|
class DateFormat:
|
8
10
|
def __init__(self) -> None:
|
9
11
|
pass
|
@@ -16,18 +18,23 @@ class Date:
|
|
16
18
|
version = 'http://gedcomx.org/conceptual-model/v1'
|
17
19
|
|
18
20
|
def __init__(self, original: Optional[str],normalized: Optional[DateNormalization] = None ,formal: Optional[str | DateFormat] = None) -> None:
|
19
|
-
self.
|
21
|
+
self.original = original
|
20
22
|
self.formal = formal
|
21
23
|
|
22
24
|
self.normalized: DateNormalization | None = normalized if normalized else None
|
23
25
|
|
24
26
|
@property
|
25
27
|
def _as_dict_(self):
|
26
|
-
|
27
|
-
|
28
|
+
from .serialization import Serialization
|
29
|
+
type_as_dict = {}
|
30
|
+
if self.original:
|
31
|
+
type_as_dict['original'] = self.original
|
32
|
+
if self.formal:
|
33
|
+
type_as_dict['formal'] = self.formal
|
34
|
+
return Serialization.serialize_dict(type_as_dict)
|
28
35
|
|
29
36
|
@classmethod
|
30
|
-
def _from_json_(
|
37
|
+
def _from_json_(cls,data):
|
31
38
|
original = data.get('original',None)
|
32
39
|
formal = data.get('formal',None)
|
33
40
|
|
@@ -1,13 +1,30 @@
|
|
1
1
|
from enum import Enum
|
2
2
|
from typing import Optional, List
|
3
|
+
"""
|
4
|
+
======================================================================
|
5
|
+
Project: Gedcom-X
|
6
|
+
File: document.py
|
7
|
+
Author: David J. Cartwright
|
8
|
+
Purpose:
|
3
9
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
10
|
+
Created: 2025-08-25
|
11
|
+
Updated:
|
12
|
+
- 2025-08-31:
|
13
|
+
|
14
|
+
======================================================================
|
15
|
+
"""
|
16
|
+
|
17
|
+
"""
|
18
|
+
======================================================================
|
19
|
+
GEDCOM Module Types
|
20
|
+
======================================================================
|
21
|
+
"""
|
22
|
+
from .attribution import Attribution
|
23
|
+
from .conclusion import Conclusion, ConfidenceLevel
|
24
|
+
from .note import Note
|
25
|
+
from .resource import Resource
|
26
|
+
from .source_reference import SourceReference
|
8
27
|
|
9
|
-
from .Conclusion import Conclusion
|
10
|
-
from .Serialization import Serialization
|
11
28
|
|
12
29
|
class DocumentType(Enum):
|
13
30
|
Abstract = "http://gedcomx.org/Abstract"
|
@@ -38,7 +55,7 @@ class Document(Conclusion):
|
|
38
55
|
sources: Optional[List[SourceReference]] = None,
|
39
56
|
analysis: Optional[Resource] = None,
|
40
57
|
notes: Optional[List[Note]] = None,
|
41
|
-
confidence: Optional[
|
58
|
+
confidence: Optional[ConfidenceLevel] = None, # ConfidenceLevel
|
42
59
|
attribution: Optional[Attribution] = None,
|
43
60
|
type: Optional[DocumentType] = None,
|
44
61
|
extracted: Optional[bool] = None, # Default to False
|
@@ -53,6 +70,7 @@ class Document(Conclusion):
|
|
53
70
|
|
54
71
|
@property
|
55
72
|
def _as_dict(self):
|
73
|
+
from .serialization import Serialization
|
56
74
|
type_as_dict = super()._as_dict_
|
57
75
|
if self.type:
|
58
76
|
type_as_dict['type'] = self.type.value
|
@@ -69,5 +87,6 @@ class Document(Conclusion):
|
|
69
87
|
"""
|
70
88
|
Create a Person instance from a JSON-dict (already parsed).
|
71
89
|
"""
|
90
|
+
from .serialization import Serialization
|
72
91
|
type_as_dict = Serialization.get_class_fields('Document')
|
73
|
-
return Serialization.deserialize(
|
92
|
+
return Serialization.deserialize(type_as_dict,Document)
|
gedcomx/{Event.py → event.py}
RENAMED
@@ -1,18 +1,37 @@
|
|
1
1
|
from enum import Enum
|
2
2
|
from typing import List, Optional
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
4
|
+
"""
|
5
|
+
======================================================================
|
6
|
+
Project: Gedcom-X
|
7
|
+
File: Event.py
|
8
|
+
Author: David J. Cartwright
|
9
|
+
Purpose: Python Object representation of GedcomX Event Type, EventType, EventRole, EventRoleType Types
|
10
|
+
|
11
|
+
Created: 2025-08-25
|
12
|
+
Updated:
|
13
|
+
- 2025-08-31: fixed mutible [] in init, replaced List[Identifer] with IdentifierList
|
14
|
+
|
15
|
+
======================================================================
|
16
|
+
"""
|
17
|
+
|
18
|
+
"""
|
19
|
+
======================================================================
|
20
|
+
GEDCOM Module Type Imports
|
21
|
+
======================================================================
|
22
|
+
"""
|
23
|
+
from .attribution import Attribution
|
24
|
+
from .conclusion import ConfidenceLevel, Conclusion
|
25
|
+
from .date import Date
|
26
|
+
from .evidence_reference import EvidenceReference
|
27
|
+
from .identifier import IdentifierList
|
28
|
+
from .note import Note
|
29
|
+
from .place_reference import PlaceReference
|
30
|
+
from .resource import Resource
|
31
|
+
from .source_reference import SourceReference
|
32
|
+
from .subject import Subject
|
33
|
+
|
34
|
+
#=====================================================================
|
16
35
|
|
17
36
|
class EventRoleType(Enum):
|
18
37
|
Principal = "http://gedcomx.org/Principal"
|
@@ -23,10 +42,10 @@ class EventRoleType(Enum):
|
|
23
42
|
@property
|
24
43
|
def description(self):
|
25
44
|
descriptions = {
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
45
|
+
EventRoleType.Principal: "The person is the principal person of the event. For example, the principal of a birth event is the person that was born.",
|
46
|
+
EventRoleType.Participant: "A participant in the event.",
|
47
|
+
EventRoleType.Official: "A person officiating the event.",
|
48
|
+
EventRoleType.Witness: "A witness of the event."
|
30
49
|
}
|
31
50
|
return descriptions.get(self, "No description available.")
|
32
51
|
|
@@ -36,19 +55,64 @@ class EventRole(Conclusion):
|
|
36
55
|
|
37
56
|
def __init__(self,
|
38
57
|
id: Optional[str] = None,
|
39
|
-
lang: Optional[str] =
|
58
|
+
lang: Optional[str] = None,
|
40
59
|
sources: Optional[List[SourceReference]] = [],
|
41
60
|
analysis: Optional[Resource] = None,
|
42
61
|
notes: Optional[List[Note]] = [],
|
43
62
|
confidence: Optional[ConfidenceLevel] = None,
|
44
63
|
attribution: Optional[Attribution] = None,
|
45
|
-
person: Resource = None,
|
64
|
+
person: Optional[Resource] = None,
|
46
65
|
type: Optional[EventRoleType] = None,
|
47
66
|
details: Optional[str] = None) -> None:
|
48
67
|
super().__init__(id, lang, sources, analysis, notes, confidence, attribution)
|
49
68
|
self.person = person
|
50
69
|
self.type = type
|
51
70
|
self.details = details
|
71
|
+
|
72
|
+
def __str__(self) -> str:
|
73
|
+
parts = []
|
74
|
+
if self.type is not None:
|
75
|
+
# assume enums expose .name
|
76
|
+
parts.append(f"type={getattr(self.type, 'name', str(self.type))}")
|
77
|
+
if self.person is not None:
|
78
|
+
# assume classes have meaningful __str__
|
79
|
+
parts.append(f"person={self.person}")
|
80
|
+
if self.details:
|
81
|
+
parts.append(f"details={self.details!r}")
|
82
|
+
if getattr(self, "id", None):
|
83
|
+
parts.append(f"id={self.id!r}")
|
84
|
+
return f"EventRole({', '.join(parts)})" if parts else "EventRole()"
|
85
|
+
|
86
|
+
def __repr__(self) -> str:
|
87
|
+
# assume enums expose .name and .value
|
88
|
+
if self.type is not None:
|
89
|
+
tcls = self.type.__class__.__name__
|
90
|
+
tname = getattr(self.type, "name", str(self.type))
|
91
|
+
tval = getattr(self.type, "value", self.type)
|
92
|
+
type_repr = f"<{tcls}.{tname}: {tval!r}>"
|
93
|
+
else:
|
94
|
+
type_repr = "None"
|
95
|
+
return (
|
96
|
+
f"{self.__class__.__name__}("
|
97
|
+
f"id={getattr(self, 'id', None)!r}, "
|
98
|
+
f"lang={getattr(self, 'lang', None)!r}, "
|
99
|
+
f"type={type_repr}, "
|
100
|
+
f"person={self.person!r}, "
|
101
|
+
f"details={self.details!r})"
|
102
|
+
)
|
103
|
+
|
104
|
+
@property
|
105
|
+
def _as_dict_(self):
|
106
|
+
from .serialization import Serialization
|
107
|
+
type_as_dict = super()._as_dict_
|
108
|
+
if self.person:
|
109
|
+
type_as_dict['person'] = Resource(target=self.person)._as_dict_
|
110
|
+
if self.type is not None:
|
111
|
+
type_as_dict['type'] = getattr(self.type, 'value', self.type)
|
112
|
+
if self.details:
|
113
|
+
type_as_dict['details'] = self.details
|
114
|
+
|
115
|
+
return Serialization.serialize_dict(type_as_dict)
|
52
116
|
|
53
117
|
class EventType(Enum):
|
54
118
|
Adoption = "http://gedcomx.org/Adoption"
|
@@ -180,16 +244,17 @@ class Event(Subject):
|
|
180
244
|
|
181
245
|
def __init__(self,
|
182
246
|
id: Optional[str] = None,
|
183
|
-
lang: Optional[str] =
|
184
|
-
sources: Optional[List[SourceReference]] =
|
247
|
+
lang: Optional[str] = None,
|
248
|
+
sources: Optional[List[SourceReference]] = None,
|
185
249
|
analysis: Optional[Resource] = None,
|
186
|
-
notes: Optional[List[Note]] =
|
250
|
+
notes: Optional[List[Note]] = None,
|
187
251
|
confidence: Optional[ConfidenceLevel] = None,
|
188
252
|
attribution: Optional[Attribution] = None,
|
189
253
|
extracted: Optional[bool] = False,
|
190
|
-
evidence: Optional[List[EvidenceReference]] =
|
191
|
-
media: Optional[List[SourceReference]] =
|
192
|
-
identifiers: Optional[List[Identifier]] = [],
|
254
|
+
evidence: Optional[List[EvidenceReference]] = None,
|
255
|
+
media: Optional[List[SourceReference]] = None,
|
256
|
+
#identifiers: Optional[List[Identifier]] = [],
|
257
|
+
identifiers: Optional[IdentifierList] = None,
|
193
258
|
type: Optional[EventType] = None,
|
194
259
|
date: Optional[Date] = None,
|
195
260
|
place: Optional[PlaceReference] = None,
|
@@ -203,12 +268,22 @@ class Event(Subject):
|
|
203
268
|
|
204
269
|
@property
|
205
270
|
def _as_dict_(self):
|
206
|
-
|
271
|
+
from .serialization import Serialization
|
272
|
+
type_as_dict = super()._as_dict_
|
273
|
+
type_as_dict.update({
|
274
|
+
'type': self.type.value if self.type else None,
|
275
|
+
'date': self.date,
|
276
|
+
'place': self.place._as_dict_ if self.place else None,
|
277
|
+
'roles': [role._as_dict_ for role in self.roles],
|
278
|
+
})
|
279
|
+
|
280
|
+
return Serialization.serialize_dict(type_as_dict)
|
207
281
|
|
208
282
|
@classmethod
|
209
283
|
def _from_json_(cls, data: dict):
|
210
284
|
"""
|
211
285
|
Create a Person instance from a JSON-dict (already parsed).
|
212
286
|
"""
|
213
|
-
type_as_dict = Serialization.get_class_fields('Event')
|
214
|
-
|
287
|
+
#type_as_dict = Serialization.get_class_fields('Event')
|
288
|
+
from .serialization import Serialization
|
289
|
+
return Serialization.deserialize(data, Event)
|
gedcomx/{Fact.py → fact.py}
RENAMED
@@ -1,28 +1,38 @@
|
|
1
1
|
import difflib
|
2
2
|
import re
|
3
3
|
|
4
|
-
from datetime import datetime
|
5
4
|
from enum import Enum
|
6
5
|
from typing import List, Optional, Dict, Any
|
6
|
+
"""
|
7
|
+
======================================================================
|
8
|
+
Project: Gedcom-X
|
9
|
+
File: fact.py
|
10
|
+
Author: David J. Cartwright
|
11
|
+
Purpose:
|
7
12
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
from .SourceReference import SourceReference
|
15
|
-
from .Serialization import Serialization
|
16
|
-
from .Resource import Resource
|
13
|
+
Created: 2025-08-25
|
14
|
+
Updated:
|
15
|
+
- 2025-08-31:
|
16
|
+
|
17
|
+
======================================================================
|
18
|
+
"""
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
from
|
24
|
-
|
25
|
-
from .
|
20
|
+
"""
|
21
|
+
======================================================================
|
22
|
+
GEDCOM Module Types
|
23
|
+
======================================================================
|
24
|
+
"""
|
25
|
+
from .attribution import Attribution
|
26
|
+
from .conclusion import Conclusion, ConfidenceLevel
|
27
|
+
from .date import Date
|
28
|
+
from .document import Document
|
29
|
+
from .Extensions.rs10.rsLink import _rsLinkList
|
30
|
+
from .note import Note
|
31
|
+
from .place_reference import PlaceReference
|
32
|
+
from .qualifier import Qualifier
|
33
|
+
from .resource import Resource
|
34
|
+
from .source_reference import SourceReference
|
35
|
+
#=====================================================================
|
26
36
|
|
27
37
|
|
28
38
|
class FactType(Enum):
|
@@ -367,11 +377,9 @@ class FactType(Enum):
|
|
367
377
|
for word in words:
|
368
378
|
matches = difflib.get_close_matches(word, keywords_to_fact_type.keys(), n=1, cutoff=0.8)
|
369
379
|
if matches:
|
370
|
-
print(f"Guessed '{description} to be of fact type: {keywords_to_fact_type[matches[0]]}")
|
371
380
|
return keywords_to_fact_type[matches[0]]
|
372
381
|
return None
|
373
382
|
|
374
|
-
|
375
383
|
class FactQualifier(Enum):
|
376
384
|
Age = "http://gedcomx.org/Age"
|
377
385
|
Cause = "http://gedcomx.org/Cause"
|
@@ -390,17 +398,16 @@ class FactQualifier(Enum):
|
|
390
398
|
}
|
391
399
|
return descriptions.get(self, "No description available.")
|
392
400
|
|
393
|
-
|
394
401
|
class Fact(Conclusion):
|
395
402
|
identifier = 'http://gedcomx.org/v1/Fact'
|
396
403
|
version = 'http://gedcomx.org/conceptual-model/v1'
|
397
404
|
|
398
405
|
def __init__(self,
|
399
406
|
id: Optional[str] = None,
|
400
|
-
lang: str =
|
401
|
-
sources: Optional[List[SourceReference]] =
|
407
|
+
lang: Optional[str] = None,
|
408
|
+
sources: Optional[List[SourceReference]] = None,
|
402
409
|
analysis: Optional[Resource | Document] = None,
|
403
|
-
notes: Optional[List[Note]] =
|
410
|
+
notes: Optional[List[Note]] = None,
|
404
411
|
confidence: Optional[ConfidenceLevel] = None,
|
405
412
|
attribution: Optional[Attribution] = None,
|
406
413
|
type: Optional[FactType] = None,
|
@@ -429,24 +436,28 @@ class Fact(Conclusion):
|
|
429
436
|
|
430
437
|
@property
|
431
438
|
def _as_dict_(self):
|
432
|
-
|
439
|
+
from .serialization import Serialization
|
440
|
+
type_as_dcit = super()._as_dict_
|
433
441
|
# Only add Relationship-specific fields
|
434
|
-
|
435
|
-
'type'
|
436
|
-
|
437
|
-
'
|
438
|
-
|
439
|
-
'
|
440
|
-
|
442
|
+
if self.type:
|
443
|
+
type_as_dcit['type'] = getattr(self.type, 'value', self.type)
|
444
|
+
if self.date:
|
445
|
+
type_as_dcit['date'] = self.date._as_dict_
|
446
|
+
if self.place:
|
447
|
+
type_as_dcit['place'] = self.place._as_dict_
|
448
|
+
if self.value:
|
449
|
+
type_as_dcit['value'] = self.value
|
450
|
+
if self.qualifiers:
|
451
|
+
type_as_dcit['qualifiers'] = [getattr(q, 'value', q) for q in self.qualifiers]
|
441
452
|
|
442
|
-
return Serialization.serialize_dict(
|
453
|
+
return Serialization.serialize_dict(type_as_dcit)
|
443
454
|
|
444
455
|
@classmethod
|
445
456
|
def _from_json_(cls, data: Dict[str, Any]) -> 'Fact':
|
446
457
|
|
447
458
|
# Extract fields, no trailing commas!
|
448
459
|
id_ = data.get('id')
|
449
|
-
lang = data.get('lang',
|
460
|
+
lang = data.get('lang', None)
|
450
461
|
sources = [SourceReference._from_json_(s) for s in data.get('sources',[])]
|
451
462
|
analysis = (Resource._from_json_(data['analysis'])
|
452
463
|
if data.get('analysis') else None)
|