gedcom-x 0.5.2__py3-none-any.whl → 0.5.6__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.
@@ -0,0 +1,144 @@
1
+ Metadata-Version: 2.4
2
+ Name: gedcom-x
3
+ Version: 0.5.6
4
+ Summary: Python implimentation of gedcom-x standard
5
+ Author-email: "David J. Cartwright" <davidcartwright@hotmail.com>
6
+ License: MIT
7
+ Keywords: gedcom,gedcomx,ged
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Environment :: Console
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Topic :: Utilities
14
+ Classifier: Topic :: Software Development :: User Interfaces
15
+ Requires-Python: >=3.6
16
+ Description-Content-Type: text/markdown
17
+ Dynamic: requires-python
18
+
19
+ # GEDCOM-X Python Toolkit (gedcom-x beta 0.5.5)
20
+
21
+ A lightweight, class-based Python implementation of the [GEDCOM-X data model](https://github.com/FamilySearch/gedcomx).
22
+
23
+ ## ⚠️ Project Status
24
+
25
+ This project is currently in **beta**.
26
+ While the core GEDCOM-X classes and serialization are functional, some features may not be fully implemented or may not behave exactly as expected.
27
+
28
+ - Certain GEDCOM 7 tags are not yet mapped
29
+ - Some classes may be missing methods or fields
30
+ - Error handling and validation are still evolving
31
+ - Backward compatibility is **not guaranteed** until the first stable release
32
+
33
+ ### ✅ What You Can Do
34
+ - Create and manipulate GEDCOM-X objects in Python
35
+ - Serialize and deserialize data to/from JSON
36
+ - Experimentally convert GEDCOM 5x & 7 files into GEDCOM-X JSON
37
+ - Extend the classes to handle new GEDCOM tags or custom attributes
38
+ - Use the library as a foundation for genealogy-related tooling or RAG pipelines
39
+
40
+ ### ❌ What You Can’t Do (Yet)
41
+ - Rely on complete coverage of all GEDCOM 7 tags
42
+ - Expect perfect compliance with the GEDCOM-X specification
43
+ - Assume strong validation or error recovery on malformed input
44
+ - Use it as a drop-in replacement for production genealogy software
45
+ - Write GEDCOM-X to GEDCOM 5x / 7
46
+ - Create Graphs from Genealogies
47
+
48
+ Contributors and testers are welcome — feedback will help stabilize the library!
49
+
50
+ ---
51
+
52
+ This library aims to provide:
53
+
54
+ - Python classes for every GEDCOM-X type (Person, Fact, Source, etc.)
55
+ - Extensibility, with current GEDCOM RS etc, extension built in
56
+ - Serialization and Deserialization to/from GEDCOM-X JSON
57
+ - Utilities to convert GEDCOM 5x & 7 GEDCOM Files into GEDCOM-X and back
58
+ - Type-safe field definitions and extensibility hooks for future tags
59
+
60
+ ---
61
+
62
+ ## Features
63
+
64
+ - **Complete GEDCOM-X Class Coverage**
65
+ Each GEDCOM-X type is represented as a Python class with fields and types.
66
+
67
+ - **Serialization / Deserialization**
68
+ Every class can serialize to JSON and reconstruct from JSON via `_as_dict_()` and `_from_json()` methods.
69
+
70
+ - **Type Checking & Enum Validation**
71
+ Uses Python type hints and enums to ensure correct values (e.g. FactType, EventType, ConfidenceLevel).
72
+
73
+ - **Composable / Nestable Classes**
74
+ Nested objects (e.g. Person → Name → NameForm → TextValue) are constructed and validated recursively.
75
+
76
+ - **GEDCOM 7 → GEDCOM-X Conversion**
77
+ Experimental parser to read GEDCOM 7 files and convert them into structured GEDCOM-X JSON.
78
+
79
+ ---
80
+
81
+ ## Installation
82
+
83
+ Clone the repository and install dependencies:
84
+
85
+ ```bash
86
+ git clone https://github.com/yourusername/gedcom-x.git
87
+ cd gedcom-x
88
+ pip install -r requirements.txt
89
+ ```
90
+ or
91
+ ```
92
+ pip install gedcom-x
93
+ ```
94
+ ---
95
+
96
+ ## Examples
97
+
98
+ <details>
99
+
100
+ <summary>Create a Person Gedcom-X Type</summary>
101
+
102
+ ```python
103
+ import json
104
+ from gedcomx import Person, Name, NameForm, TextValue
105
+
106
+ person = Person(
107
+ id="P-123",
108
+ names=[Name(
109
+ nameForms=[NameForm(
110
+ fullText=TextValue(value="John Doe")
111
+ )]
112
+ )]
113
+ )
114
+
115
+ print(json.dumps(person._as_dict_,indent=4))
116
+ ```
117
+ result
118
+ ```text
119
+ {
120
+ "id": "P-123",
121
+ "lang": "en",
122
+ "private": false,
123
+ "living": false,
124
+ "gender": {
125
+ "lang": "en",
126
+ "type": "http://gedcomx.org/Unknown"
127
+ },
128
+ "names": [
129
+ {
130
+ "lang": "en",
131
+ "nameForms": [
132
+ {
133
+ "lang": "en",
134
+ "fullText": {
135
+ "lang": "en",
136
+ "value": "John Doe"
137
+ }
138
+ }
139
+ ]
140
+ }
141
+ ]
142
+ }
143
+
144
+ </details>
@@ -0,0 +1,45 @@
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/Address.py CHANGED
@@ -61,6 +61,8 @@ class Address:
61
61
 
62
62
  @value.setter
63
63
  def value(self,value: str):
64
+ self._value = value
65
+ return
64
66
  raise NotImplementedError("Parsing of a full address is not implimented.")
65
67
 
66
68
  def _append(self,value):
gedcomx/Agent.py CHANGED
@@ -139,6 +139,14 @@ class Agent:
139
139
  }
140
140
  return Serialization.serialize_dict(type_as_dict)
141
141
 
142
+ @classmethod
143
+ def _from_json_(cls, data: dict):
144
+ """
145
+ Create a Person instance from a JSON-dict (already parsed).
146
+ """
147
+ type_as_dict = Serialization.get_class_fields('Agent')
148
+ return Serialization.deserialize(data, type_as_dict)
149
+
142
150
  def __str__(self):
143
151
  """
144
152
  Return a human-readable string representation of the Agent.
@@ -179,8 +187,7 @@ class Agent:
179
187
  self.uri == other.uri
180
188
  )
181
189
  '''
182
- print(other)
183
- print(self)
190
+
184
191
  self_names = {n.value for n in self.names if hasattr(n, "value")}
185
192
  other_names = {n.value for n in other.names if hasattr(n, "value")}
186
193
  if self_names & other_names: # intersection not empty
gedcomx/Attribution.py CHANGED
@@ -10,11 +10,11 @@ class Attribution:
10
10
  """Attribution Information for a Genealogy, Conclusion, Subject and child classes
11
11
 
12
12
  Args:
13
- contributor (Agent): Contributor to object being attributed.
14
- modified (timestamp): timestamp for when this record was modified.
15
- changeMessage (str): Birth date (YYYY-MM-DD).
13
+ contributor (Agent, optional): Contributor to object being attributed.
14
+ modified (timestamp, optional): timestamp for when this record was modified.
15
+ changeMessage (str, optional): Birth date (YYYY-MM-DD).
16
16
  creator (Agent, optional): Creator of object being attributed.
17
- created (timestamp): timestamp for when this record was created
17
+ created (timestamp, optional): timestamp for when this record was created
18
18
 
19
19
  Raises:
20
20
 
@@ -56,45 +56,9 @@ class Attribution:
56
56
  """
57
57
  # contributor
58
58
 
59
- contrib = None
60
- if 'contributor' in data:
61
- contrib_data = data['contributor']
62
-
63
- contrib = Resource(contrib_data['resource'],contrib_data['resourceId'])
64
-
65
- # creator
66
- creat = None
67
- if 'creator' in data:
68
- raw = data['creator']
69
- if isinstance(raw, dict):
70
- creat = Resource._from_json_(raw)
71
- elif isinstance(raw, str):
72
- creat = Resource(uri=raw)
73
-
74
- # parse created date
75
- raw_created = data.get('created')
76
- if isinstance(raw_created, (int, float)):
77
- created_dt = datetime.fromtimestamp(raw_created / 1000.0)
78
- elif isinstance(raw_created, str):
79
- created_dt = datetime.fromisoformat(raw_created)
80
- else:
81
- created_dt = None
82
-
83
- # parse modified date
84
- raw_modified = data.get('modified')
85
- if isinstance(raw_modified, (int, float)):
86
- modified_dt = datetime.fromtimestamp(raw_modified / 1000.0)
87
- elif isinstance(raw_modified, str):
88
- modified_dt = datetime.fromisoformat(raw_modified)
89
- else:
90
- modified_dt = None
91
-
92
- change_msg = data.get('changeMessage')
93
-
94
- return cls(
95
- contributor=contrib,
96
- created=created_dt,
97
- creator=creat,
98
- modified=modified_dt,
99
- changeMessage=change_msg
100
- )
59
+ """
60
+ Create a Person instance from a JSON-dict (already parsed).
61
+ """
62
+ from .Serialization import Serialization
63
+
64
+ return Serialization.deserialize(data, Attribution)
gedcomx/Conclusion.py CHANGED
@@ -11,7 +11,7 @@ from .Qualifier import Qualifier
11
11
  from .Serialization import Serialization
12
12
  from .SourceReference import SourceReference
13
13
  from .Resource import Resource, URI
14
- from ._Links import _LinkList, _Link
14
+ from .Extensions.rs10.rsLink import _rsLinkList, rsLink
15
15
 
16
16
  from collections.abc import Sized
17
17
 
@@ -19,15 +19,72 @@ class ConfidenceLevel(Qualifier):
19
19
  High = "http://gedcomx.org/High"
20
20
  Medium = "http://gedcomx.org/Medium"
21
21
  Low = "http://gedcomx.org/Low"
22
-
22
+
23
+ _NAME_TO_URI = {
24
+ "high": High,
25
+ "medium": Medium,
26
+ "low": Low,
27
+ }
28
+
29
+ @classmethod
30
+ def _from_json_(cls, data):
31
+ """
32
+ Accepts:
33
+ - "High" | "Medium" | "Low"
34
+ - "http://gedcomx.org/High" | ".../Medium" | ".../Low"
35
+ - {"type": "..."} or {"value": "..."} or {"confidence": "..."} or {"level": "..."} or {"uri": "..."}
36
+ - existing ConfidenceLevel instance
37
+ Returns:
38
+ ConfidenceLevel instance with .value set to the canonical URI.
39
+ """
40
+ if data is None:
41
+ return None
42
+
43
+ if isinstance(data, cls):
44
+ return data
45
+
46
+ # Extract token from dicts or use the raw scalar
47
+ if isinstance(data, dict):
48
+ token = (
49
+ data.get("confidence")
50
+ or data.get("type")
51
+ or data.get("value")
52
+ or data.get("level")
53
+ or data.get("uri")
54
+ )
55
+ else:
56
+ token = data
57
+
58
+ if token is None:
59
+ return None
60
+
61
+ token_str = str(token).strip()
62
+
63
+ # Normalize to canonical URI
64
+ if token_str.lower() in cls._NAME_TO_URI:
65
+ uri = cls._NAME_TO_URI[token_str.lower()]
66
+ elif token_str in (cls.High, cls.Medium, cls.Low):
67
+ uri = token_str
68
+ else:
69
+ raise ValueError(f"Unknown ConfidenceLevel: {token!r}")
70
+
71
+ # Create a ConfidenceLevel instance without invoking Qualifier.__init__
72
+ obj = cls.__new__(cls)
73
+ # store the canonical URI on the instance; used by description and (optionally) serialization
74
+ obj.value = uri
75
+ return obj
76
+
23
77
  @property
24
78
  def description(self):
25
79
  descriptions = {
26
- ConfidenceLevel.High: "The contributor has a high degree of confidence that the assertion is true.",
27
- ConfidenceLevel.Medium: "The contributor has a medium degree of confidence that the assertion is true.",
28
- ConfidenceLevel.Low: "The contributor has a low degree of confidence that the assertion is true."
80
+ self.High: "The contributor has a high degree of confidence that the assertion is true.",
81
+ self.Medium: "The contributor has a medium degree of confidence that the assertion is true.",
82
+ self.Low: "The contributor has a low degree of confidence that the assertion is true."
29
83
  }
30
- return descriptions.get(self, "No description available.")
84
+ # Works whether the instance holds .value or (edge-case) if `self` is compared directly
85
+ key = getattr(self, "value", self)
86
+ return descriptions.get(key, "No description available.")
87
+
31
88
 
32
89
  class Conclusion:
33
90
  """
@@ -53,13 +110,7 @@ class Conclusion:
53
110
  uri (Resource, optional): A URI reference for the conclusion. Defaults to a
54
111
  URI with the fragment set to the `id`.
55
112
  links (_LinkList, optional): A list of links associated with the conclusion.
56
- Defaults to an empty `_LinkList`.
57
-
58
- Methods:
59
- add_note(note_to_add): Adds a note if it is not a duplicate and does not
60
- exceed the maximum allowed notes.
61
- add_source(source_to_add): Adds a source reference if it is not already present.
62
- add_link(link): Adds a link to the `_LinkList`.
113
+ Defaults to an empty `_LinkList`.
63
114
  """
64
115
  identifier = 'http://gedcomx.org/v1/Conclusion'
65
116
  version = 'http://gedcomx.org/conceptual-model/v1'
@@ -75,20 +126,20 @@ class Conclusion:
75
126
  return short_uuid
76
127
 
77
128
  def __init__(self,
78
- id: Optional[str],
129
+ id: Optional[str] = None,
79
130
  lang: Optional[str] = 'en',
80
131
  sources: Optional[List[SourceReference]] = None,
81
132
  analysis: Optional[object | Resource] = None,
82
- notes: Optional[List[Note]] = [],
133
+ notes: Optional[List[Note]] = None,
83
134
  confidence: Optional[ConfidenceLevel] = None,
84
135
  attribution: Optional[Attribution] = None,
85
136
  uri: Optional[Resource] = None,
86
137
  _max_note_count: int = 20,
87
- links: Optional[_LinkList] = None) -> None:
138
+ links: Optional[_rsLinkList] = None) -> None:
88
139
 
89
140
  self._id_generator = Conclusion.default_id_generator
90
141
 
91
- self.id = id if id else self._id_generator()
142
+ self.id = id if id else None
92
143
  self.lang = lang
93
144
  self.sources = sources if sources else []
94
145
  self.analysis = analysis
@@ -96,8 +147,8 @@ class Conclusion:
96
147
  self.confidence = confidence
97
148
  self.attribution = attribution
98
149
  self.max_note_count = _max_note_count
99
- self.uri = uri if uri else URI(fragment=id)
100
- self.links = links if links else _LinkList() #NOTE This is not in specification, following FS format
150
+ self.uri = uri if uri else URI(fragment=id if id else self.id)
151
+ self.links = links if links else _rsLinkList() #NOTE This is not in specification, following FS format
101
152
 
102
153
  def add_note(self,note_to_add: Note):
103
154
  if self.notes and len(self.notes) >= self.max_note_count:
@@ -118,9 +169,22 @@ class Conclusion:
118
169
  else:
119
170
  raise ValueError()
120
171
 
121
- def add_link(self,link: _Link):
122
- if link and isinstance(link,_Link):
172
+ def add_link(self,link: rsLink) -> bool:
173
+ """
174
+ Adds a link to the Conclusion link list.
175
+
176
+ Args:
177
+ link (rsLink): The link to be added.
178
+
179
+ Returns:
180
+ bool: The return value. True for success, False otherwise.
181
+
182
+ Note: Duplicate checking not impimented at this level
183
+ """
184
+ if link and isinstance(link,rsLink):
123
185
  self.links.add(link)
186
+ return True
187
+ return False
124
188
 
125
189
  @property
126
190
  def _as_dict_(self):
gedcomx/Coverage.py CHANGED
@@ -2,6 +2,7 @@ from typing import Optional
2
2
 
3
3
  from .Date import Date
4
4
  from .PlaceReference import PlaceReference
5
+ from .Serialization import Serialization
5
6
 
6
7
  class Coverage:
7
8
  identifier = 'http://gedcomx.org/v1/Coverage'
@@ -13,6 +14,15 @@ class Coverage:
13
14
 
14
15
  # ...existing code...
15
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
+
16
26
  @classmethod
17
27
  def _from_json_(cls, data: dict):
18
28
  """
gedcomx/Date.py CHANGED
@@ -21,7 +21,8 @@ class Date:
21
21
 
22
22
  self.normalized: DateNormalization | None = normalized if normalized else None
23
23
 
24
- def _prop_dict(self):
24
+ @property
25
+ def _as_dict_(self):
25
26
  return {'original': self.orginal,
26
27
  'formal': self.formal}
27
28
 
@@ -33,12 +34,6 @@ class Date:
33
34
  return Date(original=original,formal=formal)
34
35
 
35
36
 
36
- Date._to_dict_ = lambda self: {
37
- 'original': self.orginal,
38
- 'formal': self.formal}
39
-
40
-
41
-
42
37
 
43
38
  def date_to_timestamp(date_str: str, assume_utc_if_naive: bool = True, print_definition: bool = True):
44
39
  """
gedcomx/Document.py CHANGED
@@ -1,13 +1,13 @@
1
1
  from enum import Enum
2
2
  from typing import Optional, List
3
3
 
4
- from gedcomx.Attribution import Attribution
5
- #from gedcomx.Conclusion import ConfidenceLevel
6
- from gedcomx.Note import Note
7
- from gedcomx.SourceReference import SourceReference
8
- from gedcomx.Resource import Resource
4
+ from .Attribution import Attribution
5
+ from .Note import Note
6
+ from .SourceReference import SourceReference
7
+ from .Resource import Resource
9
8
 
10
9
  from .Conclusion import Conclusion
10
+ from .Serialization import Serialization
11
11
 
12
12
  class DocumentType(Enum):
13
13
  Abstract = "http://gedcomx.org/Abstract"
@@ -49,4 +49,25 @@ class Document(Conclusion):
49
49
  self.type = type
50
50
  self.extracted = extracted
51
51
  self.textType = textType
52
- self.text = text
52
+ self.text = text
53
+
54
+ @property
55
+ def _as_dict(self):
56
+ type_as_dict = super()._as_dict_
57
+ if self.type:
58
+ type_as_dict['type'] = self.type.value
59
+ if self.extracted is not None:
60
+ type_as_dict['extracted'] = self.extracted
61
+ if self.textType:
62
+ type_as_dict['textType'] = self.textType.value
63
+ if self.text:
64
+ type_as_dict['text'] = self.text
65
+ return Serialization.serialize_dict(type_as_dict)
66
+
67
+ @classmethod
68
+ def _from_json_(cls, data: dict):
69
+ """
70
+ Create a Person instance from a JSON-dict (already parsed).
71
+ """
72
+ type_as_dict = Serialization.get_class_fields('Document')
73
+ return Serialization.deserialize(data, type_as_dict)
gedcomx/Event.py CHANGED
@@ -9,6 +9,7 @@ from .Conclusion import Conclusion, ConfidenceLevel
9
9
  from .Date import Date
10
10
  from .Note import Note
11
11
  from .PlaceReference import PlaceReference
12
+ from .Serialization import Serialization
12
13
  from .SourceReference import SourceReference
13
14
  from .Subject import Subject
14
15
  from .Resource import Resource
@@ -84,6 +85,7 @@ class EventType(Enum):
84
85
  Naturalization = "http://gedcomx.org/Naturalization"
85
86
  Ordination = "http://gedcomx.org/Ordination"
86
87
  Retirement = "http://gedcomx.org/Retirement"
88
+ MarriageSettlment = 'https://gedcom.io/terms/v7/MARS'
87
89
 
88
90
  @property
89
91
  def description(self):
@@ -192,4 +194,21 @@ class Event(Subject):
192
194
  date: Optional[Date] = None,
193
195
  place: Optional[PlaceReference] = None,
194
196
  roles: Optional[List[EventRole]] = []) -> None:
195
- super().__init__(id, lang, sources, analysis, notes, confidence, attribution, extracted, evidence, media, identifiers)
197
+ super().__init__(id, lang, sources, analysis, notes, confidence, attribution, extracted, evidence, media, identifiers)
198
+
199
+ self.type = type if type and isinstance(type, EventType) else None
200
+ self.date = date if date and isinstance(date, Date) else None
201
+ self.place = place if place and isinstance(place, PlaceReference) else None
202
+ self.roles = roles if roles and isinstance(roles, list) else []
203
+
204
+ @property
205
+ def _as_dict_(self):
206
+ raise NotImplementedError("Not implemented yet")
207
+
208
+ @classmethod
209
+ def _from_json_(cls, data: dict):
210
+ """
211
+ Create a Person instance from a JSON-dict (already parsed).
212
+ """
213
+ type_as_dict = Serialization.get_class_fields('Event')
214
+ return Serialization.deserialize(data, type_as_dict)
gedcomx/Exceptions.py CHANGED
@@ -3,6 +3,12 @@
3
3
  class GedcomXError(Exception):
4
4
  """Base for all app-specific errors."""
5
5
 
6
+ class GedcomClassAttributeError(GedcomXError):
7
+ def __init__(self, *args: object) -> None:
8
+ msg = f"This class need more information to be created: {args}"
9
+ super().__init__(msg)
10
+
11
+
6
12
  class TagConversionError(GedcomXError):
7
13
  def __init__(self, record,levelstack):
8
14
  msg = f"Cannot convert: #{record.line} TAG: {record.tag} {record.xref if record.xref else ''} Value:{record.value} STACK: {type(levelstack[record.level-1]).__name__}"