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/{Person.py → person.py}
RENAMED
@@ -1,22 +1,38 @@
|
|
1
|
-
from enum import Enum
|
2
1
|
from typing import List, Optional
|
3
2
|
from urllib.parse import urljoin
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
4
|
+
"""
|
5
|
+
======================================================================
|
6
|
+
Project: Gedcom-X
|
7
|
+
File: Person.py
|
8
|
+
Author: David J. Cartwright
|
9
|
+
Purpose: Python Object representation of GedcomX Person Type
|
10
|
+
|
11
|
+
Created: 2025-08-25
|
12
|
+
Updated:
|
13
|
+
- 2025-08-31: _as_dict_ to only create entries in dict for fields that hold data
|
14
|
+
|
15
|
+
======================================================================
|
16
|
+
"""
|
17
|
+
|
18
|
+
"""
|
19
|
+
======================================================================
|
20
|
+
GEDCOM Module Types
|
21
|
+
======================================================================
|
22
|
+
"""
|
23
|
+
from .attribution import Attribution
|
24
|
+
from .conclusion import ConfidenceLevel
|
25
|
+
from .date import Date
|
26
|
+
from .evidence_reference import EvidenceReference
|
19
27
|
from .Extensions.rs10.rsLink import _rsLinkList
|
28
|
+
from .fact import Fact, FactType
|
29
|
+
from .gender import Gender, GenderType
|
30
|
+
from .identifier import IdentifierList
|
31
|
+
from .name import Name, QuickName
|
32
|
+
from .note import Note
|
33
|
+
from .resource import Resource
|
34
|
+
from .source_reference import SourceReference
|
35
|
+
from .subject import Subject
|
20
36
|
|
21
37
|
class Person(Subject):
|
22
38
|
"""A person in the system.
|
@@ -40,7 +56,7 @@ class Person(Subject):
|
|
40
56
|
notes: Optional[List[Note]] = None,
|
41
57
|
confidence: Optional[ConfidenceLevel] = None,
|
42
58
|
attribution: Optional[Attribution] = None,
|
43
|
-
extracted: bool = None,
|
59
|
+
extracted: Optional[bool] = None,
|
44
60
|
evidence: Optional[List[EvidenceReference]] = None,
|
45
61
|
media: Optional[List[SourceReference]] = None,
|
46
62
|
identifiers: Optional[IdentifierList] = None,
|
@@ -77,6 +93,7 @@ class Person(Subject):
|
|
77
93
|
return False
|
78
94
|
self.facts.append(fact_to_add)
|
79
95
|
return True
|
96
|
+
return False
|
80
97
|
|
81
98
|
def add_name(self, name_to_add: Name) -> bool:
|
82
99
|
if len(self.names) > 5:
|
@@ -89,9 +106,10 @@ class Person(Subject):
|
|
89
106
|
return False
|
90
107
|
self.names.append(name_to_add)
|
91
108
|
return True
|
109
|
+
return False
|
92
110
|
|
93
111
|
def _add_relationship(self, relationship_to_add: object):
|
94
|
-
from .
|
112
|
+
from .relationship import Relationship
|
95
113
|
if isinstance(relationship_to_add,Relationship):
|
96
114
|
self._relationships.append(relationship_to_add)
|
97
115
|
else:
|
@@ -102,7 +120,7 @@ class Person(Subject):
|
|
102
120
|
"ascendancyNumber": "1",
|
103
121
|
"deathDate": "from 2001 to 2005",
|
104
122
|
"descendancyNumber": "1",
|
105
|
-
"gender": self.gender.type,
|
123
|
+
"gender": self.gender.type if self.gender else 'Unknown',
|
106
124
|
"lifespan": "-2005",
|
107
125
|
"name": self.names[0].nameForms[0].fullText
|
108
126
|
}
|
@@ -111,17 +129,20 @@ class Person(Subject):
|
|
111
129
|
|
112
130
|
@property
|
113
131
|
def _as_dict_(self):
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
'private'
|
118
|
-
|
119
|
-
'
|
120
|
-
|
121
|
-
'
|
122
|
-
|
123
|
-
|
124
|
-
|
132
|
+
from .serialization import Serialization
|
133
|
+
type_as_dict = super()._as_dict_
|
134
|
+
if self.private is not None:
|
135
|
+
type_as_dict['private'] = self.private
|
136
|
+
if self.living is not None:
|
137
|
+
type_as_dict['living'] = self.living
|
138
|
+
if self.gender:
|
139
|
+
type_as_dict['gender'] = self.gender._as_dict_
|
140
|
+
if self.names:
|
141
|
+
type_as_dict['names'] = [n._as_dict_ for n in self.names if n]
|
142
|
+
if self.facts:
|
143
|
+
type_as_dict['facts'] = [f._as_dict_ for f in self.facts if f]
|
144
|
+
if self.uri:
|
145
|
+
type_as_dict['uri'] = self.uri._as_dict_
|
125
146
|
|
126
147
|
return Serialization.serialize_dict(type_as_dict)
|
127
148
|
|
@@ -130,10 +151,12 @@ class Person(Subject):
|
|
130
151
|
"""
|
131
152
|
Create a Person instance from a JSON-dict (already parsed).
|
132
153
|
"""
|
154
|
+
from .serialization import Serialization
|
133
155
|
return Serialization.deserialize(data, Person)
|
134
156
|
|
135
157
|
@classmethod
|
136
158
|
def from_familysearch(cls, pid: str, token: str, *, base_url: Optional[str] = None):
|
159
|
+
from .serialization import Serialization
|
137
160
|
"""
|
138
161
|
Fetch a single person by PID from FamilySearch and return a Person.
|
139
162
|
- pid: e.g. "KPHP-4B4"
|
@@ -0,0 +1,123 @@
|
|
1
|
+
from typing import List, Optional
|
2
|
+
|
3
|
+
"""
|
4
|
+
======================================================================
|
5
|
+
Project: Gedcom-X
|
6
|
+
File: place_description.py
|
7
|
+
Author: David J. Cartwright
|
8
|
+
Purpose:
|
9
|
+
|
10
|
+
Created: 2025-08-25
|
11
|
+
Updated:
|
12
|
+
- 2025-09-01: filename PEP8 standard
|
13
|
+
|
14
|
+
======================================================================
|
15
|
+
"""
|
16
|
+
|
17
|
+
"""
|
18
|
+
======================================================================
|
19
|
+
GEDCOM Module Types
|
20
|
+
======================================================================
|
21
|
+
"""
|
22
|
+
from .attribution import Attribution
|
23
|
+
from .conclusion import ConfidenceLevel
|
24
|
+
from .date import Date
|
25
|
+
from .evidence_reference import EvidenceReference
|
26
|
+
from .identifier import IdentifierList
|
27
|
+
from .note import Note
|
28
|
+
from .resource import Resource
|
29
|
+
from .source_reference import SourceReference
|
30
|
+
from .subject import Subject
|
31
|
+
from .textvalue import TextValue
|
32
|
+
from .uri import URI
|
33
|
+
#=====================================================================
|
34
|
+
|
35
|
+
|
36
|
+
class PlaceDescription(Subject):
|
37
|
+
"""PlaceDescription describes the details of a place in terms of
|
38
|
+
its name and possibly its type, time period, and/or a geospatial description
|
39
|
+
functioning as a description of a place as a snapshot in time.
|
40
|
+
|
41
|
+
Encapsulates textual names, geospatial coordinates, jurisdictional context,
|
42
|
+
temporal coverage, and related resources (media, sources, evidence, etc.).
|
43
|
+
|
44
|
+
|
45
|
+
Attributes:
|
46
|
+
names (Optional[List[TextValue]]): Human-readable names or labels for
|
47
|
+
the place (e.g., “Boston, Suffolk, Massachusetts, United States”).
|
48
|
+
type (Optional[str]): A place type identifier (e.g., a URI). **TODO:**
|
49
|
+
replace with an enumeration when finalized.
|
50
|
+
place (Optional[URI]): Canonical identifier (URI) for the place.
|
51
|
+
jurisdiction (Optional[Resource|PlaceDescription]): The governing or
|
52
|
+
containing jurisdiction of this place (e.g., county for a town).
|
53
|
+
latitude (Optional[float]): Latitude in decimal degrees (WGS84).
|
54
|
+
longitude (Optional[float]): Longitude in decimal degrees (WGS84).
|
55
|
+
temporalDescription (Optional[Date]): Temporal coverage/validity window
|
56
|
+
for this description (e.g., when a jurisdictional boundary applied).
|
57
|
+
spatialDescription (Optional[Resource]): A resource describing spatial
|
58
|
+
geometry or a link to an external gazetteer/shape definition.
|
59
|
+
"""
|
60
|
+
identifier = "http://gedcomx.org/v1/PlaceDescription"
|
61
|
+
version = 'http://gedcomx.org/conceptual-model/v1'
|
62
|
+
|
63
|
+
def __init__(self, id: Optional[str] =None,
|
64
|
+
lang: Optional[str] = None,
|
65
|
+
sources: Optional[List[SourceReference]] = None,
|
66
|
+
analysis: Optional[Resource] = None,
|
67
|
+
notes: Optional[List[Note]] =None,
|
68
|
+
confidence: Optional[ConfidenceLevel] = None,
|
69
|
+
attribution: Optional[Attribution] = None,
|
70
|
+
extracted: Optional[bool] = None,
|
71
|
+
evidence: Optional[List[EvidenceReference]] = None,
|
72
|
+
media: Optional[List[SourceReference]] = None,
|
73
|
+
identifiers: Optional[IdentifierList] = None,
|
74
|
+
names: Optional[List[TextValue]] = None,
|
75
|
+
type: Optional[str] = None, #TODO This needs to be an enumerated value, work out details
|
76
|
+
place: Optional[URI] = None,
|
77
|
+
jurisdiction: Optional["Resource | PlaceDescription"] = None,
|
78
|
+
latitude: Optional[float] = None,
|
79
|
+
longitude: Optional[float] = None,
|
80
|
+
temporalDescription: Optional[Date] = None,
|
81
|
+
spatialDescription: Optional[Resource] = None,) -> None:
|
82
|
+
|
83
|
+
super().__init__(id, lang, sources, analysis, notes, confidence, attribution, extracted, evidence, media, identifiers)
|
84
|
+
self.names = names
|
85
|
+
self.type = type
|
86
|
+
self.place = place
|
87
|
+
self.jurisdiction = jurisdiction
|
88
|
+
self.latitude = latitude
|
89
|
+
self.longitude = longitude
|
90
|
+
self.temporalDescription = temporalDescription
|
91
|
+
self.spatialDescription = spatialDescription
|
92
|
+
|
93
|
+
@property
|
94
|
+
def _as_dict_(self):
|
95
|
+
from .serialization import Serialization
|
96
|
+
type_as_dict = super()._as_dict_
|
97
|
+
|
98
|
+
if self.names:
|
99
|
+
type_as_dict["names"] = [n._as_dict_ for n in self.names if n]
|
100
|
+
if self.type:
|
101
|
+
type_as_dict["type"] = self.type #TODO
|
102
|
+
if self.place:
|
103
|
+
type_as_dict["place"] = self.place._as_dict_
|
104
|
+
if self.jurisdiction:
|
105
|
+
type_as_dict["jurisdiction"] = self.jurisdiction._as_dict_
|
106
|
+
if self.latitude is not None: # include 0.0; exclude only None
|
107
|
+
type_as_dict["latitude"] = float(self.latitude)
|
108
|
+
if self.longitude is not None: # include 0.0; exclude only None
|
109
|
+
type_as_dict["longitude"] = float(self.longitude)
|
110
|
+
if self.temporalDescription:
|
111
|
+
type_as_dict["temporalDescription"] = self.temporalDescription._as_dict_
|
112
|
+
if self.spatialDescription:
|
113
|
+
type_as_dict["spatialDescription"] = self.spatialDescription._as_dict_
|
114
|
+
|
115
|
+
return Serialization.serialize_dict(type_as_dict)
|
116
|
+
|
117
|
+
@classmethod
|
118
|
+
def _from_json_(cls, data: dict):
|
119
|
+
"""
|
120
|
+
Create a PlaceDescription instance from a JSON-dict (already parsed).
|
121
|
+
"""
|
122
|
+
from .serialization import Serialization
|
123
|
+
return Serialization.deserialize(data, PlaceDescription)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import Optional, TYPE_CHECKING
|
3
|
+
if TYPE_CHECKING:
|
4
|
+
from .place_description import PlaceDescription
|
5
|
+
|
6
|
+
"""
|
7
|
+
======================================================================
|
8
|
+
Project: Gedcom-X
|
9
|
+
File: PlaceReference.py
|
10
|
+
Author: David J. Cartwright
|
11
|
+
Purpose: Python Object representation of GedcomX PlaceReference Type
|
12
|
+
|
13
|
+
Created: 2025-08-25
|
14
|
+
Updated:
|
15
|
+
- 2025-08-31: _as_dict_ to only create entries in dict for fields that hold data
|
16
|
+
|
17
|
+
======================================================================
|
18
|
+
"""
|
19
|
+
|
20
|
+
"""
|
21
|
+
======================================================================
|
22
|
+
GEDCOM Module Types
|
23
|
+
======================================================================
|
24
|
+
"""
|
25
|
+
from .resource import Resource
|
26
|
+
|
27
|
+
class PlaceReference:
|
28
|
+
"""defines a reference to a PlaceDescription.
|
29
|
+
|
30
|
+
|
31
|
+
Attributes:
|
32
|
+
original (Optional[str]): The unnormalized, user- or source-provided place text.
|
33
|
+
Keep punctuation and ordering exactly as recorded in the source.
|
34
|
+
description (Optional[Resource|PlaceDescription]): A :class:`gedcomx.PlaceDescription` Object or pointer to it. (URI/:class:`~Resource`)
|
35
|
+
|
36
|
+
"""
|
37
|
+
identifier = 'http://gedcomx.org/v1/PlaceReference'
|
38
|
+
version = 'http://gedcomx.org/conceptual-model/v1'
|
39
|
+
|
40
|
+
def __init__(self,
|
41
|
+
original: Optional[str] = None,
|
42
|
+
description: Optional["Resource | PlaceDescription"] = None) -> None:
|
43
|
+
self.original = original
|
44
|
+
self.description = description
|
45
|
+
|
46
|
+
@property
|
47
|
+
def _as_dict_(self):
|
48
|
+
from .serialization import Serialization
|
49
|
+
type_as_dict = {}
|
50
|
+
if self.original:
|
51
|
+
type_as_dict['original'] = self.original
|
52
|
+
if self.description:
|
53
|
+
type_as_dict['description'] = self.description._as_dict_
|
54
|
+
return Serialization.serialize_dict(type_as_dict)
|
55
|
+
|
56
|
+
@classmethod
|
57
|
+
def _from_json_(cls, data):
|
58
|
+
from .serialization import Serialization
|
59
|
+
return Serialization.deserialize(data, PlaceReference)
|
60
|
+
|
61
|
+
|
62
|
+
|
gedcomx/qualifier.py
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
|
3
|
+
"""
|
4
|
+
======================================================================
|
5
|
+
Project: Gedcom-X
|
6
|
+
File: Qualifier.py
|
7
|
+
Author: David J. Cartwright
|
8
|
+
Purpose: Python Object representation of GedcomX Qualifier Type
|
9
|
+
|
10
|
+
Created: 2025-08-25
|
11
|
+
Updated:
|
12
|
+
- 2025-08-31: _as_dict_ to only create entries in dict for fields that
|
13
|
+
hold data, updated _from_json
|
14
|
+
|
15
|
+
======================================================================
|
16
|
+
"""
|
17
|
+
|
18
|
+
class Qualifier:
|
19
|
+
"""defines the data structure used to supply additional details, annotations,
|
20
|
+
tags, or other qualifying data to a specific data element.
|
21
|
+
|
22
|
+
|
23
|
+
Attributes:
|
24
|
+
name str: The name of the Qualifier. *It is RECOMMENDED that the qualifier
|
25
|
+
name resolve to an element of a constrained vocabulary.*
|
26
|
+
|
27
|
+
value (Optional[str]): The value of the Qualifier. *If provided, the name
|
28
|
+
MAY give the semantic meaning of the value.*
|
29
|
+
|
30
|
+
"""
|
31
|
+
identifier = 'http://gedcomx.org/v1/Qualifier'
|
32
|
+
version = 'http://gedcomx.org/conceptual-model/v1'
|
33
|
+
|
34
|
+
def __init__(self, name: str, value: Optional[str]) -> None:
|
35
|
+
self.name = name
|
36
|
+
self.value = value
|
37
|
+
|
38
|
+
@property
|
39
|
+
def __as_dict__(self):
|
40
|
+
from .serialization import Serialization
|
41
|
+
|
42
|
+
type_as_dict = {}
|
43
|
+
if self.name:
|
44
|
+
type_as_dict["name"] = self.name
|
45
|
+
if self.value:
|
46
|
+
type_as_dict["value"] = self.value
|
47
|
+
|
48
|
+
return Serialization.serialize_dict(type_as_dict)
|
49
|
+
|
50
|
+
@classmethod
|
51
|
+
def _from_json(cls,data):
|
52
|
+
qualifier = Qualifier(name=data.get('name',"ERROR: This Qualifier require a 'name' but has none."),value=data.get('value'))
|
53
|
+
return qualifier
|
54
|
+
|
@@ -1,18 +1,36 @@
|
|
1
1
|
from enum import Enum
|
2
2
|
from typing import List, Optional
|
3
|
+
"""
|
4
|
+
======================================================================
|
5
|
+
Project: Gedcom-X
|
6
|
+
File: relationship.py
|
7
|
+
Author: David J. Cartwright
|
8
|
+
Purpose:
|
3
9
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
Created: 2025-08-25
|
11
|
+
Updated:
|
12
|
+
- 2025-09-31: filename PEP8 standard
|
13
|
+
|
14
|
+
======================================================================
|
15
|
+
"""
|
16
|
+
|
17
|
+
"""
|
18
|
+
======================================================================
|
19
|
+
GEDCOM Module Types
|
20
|
+
======================================================================
|
21
|
+
"""
|
22
|
+
from .attribution import Attribution
|
23
|
+
from .conclusion import ConfidenceLevel
|
24
|
+
from .evidence_reference import EvidenceReference
|
25
|
+
from .fact import Fact
|
26
|
+
from .identifier import Identifier
|
27
|
+
from .note import Note
|
28
|
+
from .person import Person
|
29
|
+
from .resource import Resource
|
30
|
+
from .source_reference import SourceReference
|
31
|
+
from .subject import Subject
|
32
|
+
#=====================================================================
|
14
33
|
|
15
|
-
from .Subject import Subject
|
16
34
|
|
17
35
|
class RelationshipType(Enum):
|
18
36
|
Couple = "http://gedcomx.org/Couple"
|
@@ -77,11 +95,12 @@ class Relationship(Subject):
|
|
77
95
|
|
78
96
|
@property
|
79
97
|
def _as_dict_(self):
|
98
|
+
from .serialization import Serialization
|
80
99
|
type_as_dict = super()._as_dict_
|
81
100
|
type_as_dict.update({
|
82
101
|
"type": self.type.value if isinstance(self.type, RelationshipType) else self.type,
|
83
|
-
"person1": self.person1._as_dict_ if self.person1 else None,
|
84
|
-
"person2": self.
|
102
|
+
"person1": Resource(target=self.person1)._as_dict_ if self.person1 else None,
|
103
|
+
"person2": Resource(target=self.person1)._as_dict_ if self.person2 else None,
|
85
104
|
"facts": [fact for fact in self.facts] if self.facts else None
|
86
105
|
})
|
87
106
|
return Serialization.serialize_dict(type_as_dict)
|
@@ -91,5 +110,6 @@ class Relationship(Subject):
|
|
91
110
|
"""
|
92
111
|
Create a Person instance from a JSON-dict (already parsed).
|
93
112
|
"""
|
113
|
+
from .serialization import Serialization
|
94
114
|
return Serialization.deserialize(data, Relationship)
|
95
115
|
|
gedcomx/resource.py
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
|
3
|
+
"""
|
4
|
+
======================================================================
|
5
|
+
Project: Gedcom-X
|
6
|
+
File: Resource.py
|
7
|
+
Author: David J. Cartwright
|
8
|
+
Purpose: References TopLevel Types for Serialization
|
9
|
+
|
10
|
+
Created: 2025-08-25
|
11
|
+
Updated:
|
12
|
+
- 2025-08-31: working on target=Resource and deserialization issues
|
13
|
+
|
14
|
+
======================================================================
|
15
|
+
"""
|
16
|
+
|
17
|
+
"""
|
18
|
+
======================================================================
|
19
|
+
GEDCOM Module Types
|
20
|
+
======================================================================
|
21
|
+
"""
|
22
|
+
|
23
|
+
from .uri import URI
|
24
|
+
|
25
|
+
class Resource:
|
26
|
+
"""
|
27
|
+
Class used to track and resolve URIs and references between datastores.
|
28
|
+
|
29
|
+
Parameters
|
30
|
+
----------
|
31
|
+
|
32
|
+
Raises
|
33
|
+
------
|
34
|
+
ValueError
|
35
|
+
If `id` is not a valid UUID.
|
36
|
+
"""
|
37
|
+
# TODO, Deal with a resouce being passed, as it may be unresolved.
|
38
|
+
def __init__(self,uri: Optional[URI|str] = None, id:Optional[str] = None,top_lvl_object: Optional[object] = None,target= None) -> None:
|
39
|
+
|
40
|
+
self.resource = URI.from_url(uri.value) if isinstance(uri,URI) else URI.from_url(uri) if isinstance(uri,str) else None
|
41
|
+
self.Id = id
|
42
|
+
|
43
|
+
self.type = None
|
44
|
+
self.resolved = False
|
45
|
+
self.target: object = target
|
46
|
+
self.remote: bool | None = None # is the resource pointed to persitent on a remote datastore?
|
47
|
+
|
48
|
+
if target:
|
49
|
+
if isinstance(target,Resource):
|
50
|
+
self.resource = target.resource
|
51
|
+
self.Id = target.Id
|
52
|
+
self.target = target.target
|
53
|
+
else:
|
54
|
+
self.resource = target.uri
|
55
|
+
self.Id = target.id
|
56
|
+
self.type = type(target)
|
57
|
+
|
58
|
+
@property
|
59
|
+
def uri(self):
|
60
|
+
return self.resource
|
61
|
+
|
62
|
+
@property
|
63
|
+
def _as_dict_(self):
|
64
|
+
from .serialization import Serialization
|
65
|
+
typ_as_dict = {}
|
66
|
+
if self.resource:
|
67
|
+
typ_as_dict['resource'] = self.resource.value if self.resource else None
|
68
|
+
if self.Id:
|
69
|
+
typ_as_dict['resourceId'] = self.Id
|
70
|
+
return Serialization.serialize_dict(typ_as_dict)
|
71
|
+
|
72
|
+
@classmethod
|
73
|
+
def _from_json_(cls,data):
|
74
|
+
# TODO This is not used but taken care of in Serialization
|
75
|
+
r = Resource(uri=data.get('resource'),id=data.get('resourceId',None))
|
76
|
+
#return r
|
77
|
+
|
78
|
+
def __repr__(self) -> str:
|
79
|
+
return f"Resource(uri={self.resource}, id={self.Id}, target={self.target})"
|
80
|
+
|
81
|
+
def __str__(self) -> str:
|
82
|
+
return f"{self.resource}{f', id={self.Id}' if self.Id else ''}"
|
83
|
+
|
84
|
+
|
85
|
+
|