gedcom-x 0.5.5__py3-none-any.whl → 0.5.7__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.7.dist-info/METADATA +144 -0
- gedcom_x-0.5.7.dist-info/RECORD +49 -0
- gedcomx/Address.py +13 -13
- gedcomx/Agent.py +28 -16
- gedcomx/Attribution.py +34 -7
- gedcomx/Conclusion.py +24 -13
- gedcomx/Converter.py +1034 -0
- gedcomx/Coverage.py +7 -6
- gedcomx/Date.py +11 -4
- gedcomx/Document.py +2 -1
- gedcomx/Event.py +95 -20
- gedcomx/ExtensibleEnum.py +183 -0
- gedcomx/Extensions/__init__.py +1 -0
- gedcomx/Extensions/rs10/__init__.py +1 -0
- gedcomx/Extensions/rs10/rsLink.py +116 -0
- gedcomx/Fact.py +16 -13
- gedcomx/Gedcom5x.py +115 -77
- gedcomx/GedcomX.py +184 -1034
- gedcomx/Gender.py +7 -9
- gedcomx/Identifier.py +10 -13
- gedcomx/LoggingHub.py +207 -0
- gedcomx/Mutations.py +8 -8
- gedcomx/Name.py +207 -87
- gedcomx/Note.py +16 -9
- gedcomx/Person.py +39 -18
- gedcomx/PlaceDescription.py +70 -19
- gedcomx/PlaceReference.py +40 -8
- gedcomx/Qualifier.py +39 -12
- gedcomx/Relationship.py +5 -3
- gedcomx/Resource.py +38 -28
- gedcomx/Serialization.py +773 -358
- gedcomx/SourceDescription.py +133 -74
- gedcomx/SourceReference.py +10 -9
- gedcomx/Subject.py +5 -21
- gedcomx/Translation.py +976 -1
- gedcomx/URI.py +1 -1
- gedcomx/__init__.py +4 -2
- gedcom_x-0.5.5.dist-info/METADATA +0 -17
- gedcom_x-0.5.5.dist-info/RECORD +0 -43
- {gedcom_x-0.5.5.dist-info → gedcom_x-0.5.7.dist-info}/WHEEL +0 -0
- {gedcom_x-0.5.5.dist-info → gedcom_x-0.5.7.dist-info}/top_level.txt +0 -0
gedcomx/GedcomX.py
CHANGED
@@ -1,50 +1,72 @@
|
|
1
1
|
DEBUG = False
|
2
|
-
import base64
|
3
|
-
import json
|
4
|
-
import mimetypes
|
5
|
-
import re
|
6
|
-
import uuid
|
7
|
-
import xml.etree.ElementTree as ET
|
8
2
|
|
9
|
-
|
10
|
-
|
11
|
-
|
3
|
+
import json
|
4
|
+
import random
|
5
|
+
import string
|
6
|
+
|
7
|
+
from typing import Any, Dict, Optional
|
8
|
+
|
9
|
+
"""
|
10
|
+
======================================================================
|
11
|
+
Project: Gedcom-X
|
12
|
+
File: GedcomX.py
|
13
|
+
Author: David J. Cartwright
|
14
|
+
Purpose: Object for working with Gedcom-X Data
|
15
|
+
|
16
|
+
Created: 2025-07-25
|
17
|
+
Updated:
|
18
|
+
- 2025-08-31: _as_dict_ to only create entries in dict for fields that hold data,
|
19
|
+
id_index functionality, will be used for resolution of Resources
|
20
|
+
|
21
|
+
======================================================================
|
22
|
+
"""
|
23
|
+
|
24
|
+
"""
|
25
|
+
======================================================================
|
26
|
+
GEDCOM Module Types
|
27
|
+
======================================================================
|
28
|
+
"""
|
12
29
|
from .Agent import Agent
|
13
30
|
from .Attribution import Attribution
|
14
|
-
from .Conclusion import Conclusion
|
15
|
-
from .Coverage import Coverage
|
16
|
-
from .Date import Date, date_to_timestamp
|
17
31
|
from .Document import Document
|
18
|
-
from .
|
19
|
-
from .Exceptions import TagConversionError
|
20
|
-
from .Event import Event,EventType,EventRole,EventRoleType
|
21
|
-
from .Fact import Fact, FactType, FactQualifier
|
22
|
-
from .Gedcom import Gedcom
|
23
|
-
from .Gedcom5x import GedcomRecord
|
24
|
-
from .Gender import Gender, GenderType
|
32
|
+
from .Event import Event
|
25
33
|
from .Group import Group
|
26
|
-
from .Identifier import
|
34
|
+
from .Identifier import make_uid
|
27
35
|
from .Logging import get_logger
|
28
|
-
from .Name import Name, NameType, NameForm, NamePart, NamePartType, NamePartQualifier
|
29
|
-
from .Note import Note
|
30
|
-
from .OnlineAccount import OnlineAccount
|
31
36
|
from .Person import Person
|
32
37
|
from .PlaceDescription import PlaceDescription
|
33
|
-
from .PlaceReference import PlaceReference
|
34
|
-
from .Qualifier import Qualifier
|
35
38
|
from .Relationship import Relationship, RelationshipType
|
36
|
-
from .SourceCitation import SourceCitation
|
37
|
-
from .SourceDescription import SourceDescription, ResourceType
|
38
|
-
from .SourceReference import SourceReference, KnownSourceReference
|
39
|
-
from .Subject import Subject
|
40
|
-
from .TextValue import TextValue
|
41
|
-
from .TopLevelTypeCollection import TopLevelTypeCollection
|
42
39
|
from .Resource import Resource, URI
|
40
|
+
from .SourceDescription import ResourceType, SourceDescription
|
41
|
+
from .TextValue import TextValue
|
42
|
+
#=====================================================================
|
43
43
|
|
44
|
-
import_log = get_logger('import')
|
45
|
-
convert_log = get_logger('conversion')
|
46
44
|
|
47
45
|
def TypeCollection(item_type):
|
46
|
+
"""
|
47
|
+
Factory that creates a typed, indexable collection for a specific model class.
|
48
|
+
|
49
|
+
The returned object behaves like:
|
50
|
+
- a container (append/remove, __len__, __getitem__)
|
51
|
+
- an iterator (for item in collection)
|
52
|
+
- a simple query helper via __call__(**field_equals)
|
53
|
+
- a small in-memory index on id, name (see note), and uri
|
54
|
+
|
55
|
+
Parameters
|
56
|
+
----------
|
57
|
+
item_type : type
|
58
|
+
The class/type that items in this collection must be instances of.
|
59
|
+
|
60
|
+
Returns
|
61
|
+
-------
|
62
|
+
Collection
|
63
|
+
A new, empty collection instance specialized for `item_type`.
|
64
|
+
|
65
|
+
Notes
|
66
|
+
-----
|
67
|
+
- Name indexing is currently disabled (see TODO in `_update_indexes`).
|
68
|
+
- The collection auto-assigns/normalizes an item's `uri.path` based on `item_type`.
|
69
|
+
"""
|
48
70
|
class Collection:
|
49
71
|
def __init__(self):
|
50
72
|
self._items = []
|
@@ -75,8 +97,8 @@ def TypeCollection(item_type):
|
|
75
97
|
self._id_index[item.id] = item
|
76
98
|
|
77
99
|
try:
|
78
|
-
if hasattr(item, '
|
79
|
-
self._uri_index[item.
|
100
|
+
if hasattr(item, 'uri'):
|
101
|
+
self._uri_index[item.uri.value] = item
|
80
102
|
except AttributeError as e:
|
81
103
|
print(f"type{item}")
|
82
104
|
assert False
|
@@ -93,7 +115,10 @@ def TypeCollection(item_type):
|
|
93
115
|
else:
|
94
116
|
self._name_index[name_value] = [item]
|
95
117
|
'''
|
96
|
-
|
118
|
+
@property
|
119
|
+
def id_index(self):
|
120
|
+
return self._id_index
|
121
|
+
|
97
122
|
def _remove_from_indexes(self, item):
|
98
123
|
# Remove from the id index
|
99
124
|
if hasattr(item, 'id'):
|
@@ -111,12 +136,12 @@ def TypeCollection(item_type):
|
|
111
136
|
if not self._name_index[name_value]:
|
112
137
|
del self._name_index[name_value]
|
113
138
|
|
114
|
-
def byName(self, sname: str):
|
139
|
+
def byName(self, sname: str | None):
|
115
140
|
# Use the name index for fast lookup
|
116
141
|
if sname:
|
117
142
|
sname = sname.strip()
|
118
143
|
return self._name_index.get(sname, [])
|
119
|
-
return
|
144
|
+
return []
|
120
145
|
|
121
146
|
def byId(self, id):
|
122
147
|
# Use the id index for fast lookup
|
@@ -132,12 +157,7 @@ def TypeCollection(item_type):
|
|
132
157
|
if item.uri:
|
133
158
|
item.uri.path = f'{str(item_type.__name__)}s' if (item.uri.path is None or item.uri.path == "") else item.uri.path
|
134
159
|
else:
|
135
|
-
item.uri = URI(path=f'/{item_type.__name__}s/')
|
136
|
-
|
137
|
-
|
138
|
-
#if isinstance(item,Agent):
|
139
|
-
# item._uri._path = 'Agents'
|
140
|
-
# print(item._uri._as_dict_)
|
160
|
+
item.uri = URI(path=f'/{item_type.__name__}s/',fragment=item.id)
|
141
161
|
|
142
162
|
self._items.append(item)
|
143
163
|
self._update_indexes(item)
|
@@ -234,6 +254,19 @@ class GedcomX:
|
|
234
254
|
|
235
255
|
self.default_id_generator = make_uid
|
236
256
|
|
257
|
+
@property
|
258
|
+
def contents(self):
|
259
|
+
return {
|
260
|
+
"source_descriptions": len(self.source_descriptions),
|
261
|
+
"persons": len(self.persons),
|
262
|
+
"relationships": len(self.relationships),
|
263
|
+
"agents": len(self.agents),
|
264
|
+
"events": len(self.events),
|
265
|
+
"documents": len(self.documents),
|
266
|
+
"places": len(self.places),
|
267
|
+
"groups": len(self.groups),
|
268
|
+
}
|
269
|
+
|
237
270
|
def add(self,gedcomx_type_object):
|
238
271
|
if gedcomx_type_object:
|
239
272
|
if isinstance(gedcomx_type_object,Person):
|
@@ -276,7 +309,7 @@ class GedcomX:
|
|
276
309
|
"""
|
277
310
|
if person and isinstance(person,Person):
|
278
311
|
if person.id is None:
|
279
|
-
person.id =self.
|
312
|
+
person.id =self.make_id()
|
280
313
|
self.persons.append(item=person)
|
281
314
|
else:
|
282
315
|
raise ValueError(f'person must be a Person Object not type: {type(person)}')
|
@@ -287,32 +320,33 @@ class GedcomX:
|
|
287
320
|
print("Adding unresolved Relationship")
|
288
321
|
self.relationships.append(relationship)
|
289
322
|
return
|
323
|
+
elif isinstance(relationship.person1,Person) and isinstance(relationship.person2,Person):
|
324
|
+
|
325
|
+
if relationship.person1:
|
326
|
+
if relationship.person1.id is None:
|
327
|
+
relationship.person1.id = self.make_id()
|
328
|
+
if not self.persons.byId(relationship.person1.id):
|
329
|
+
self.persons.append(relationship.person1)
|
330
|
+
if relationship.person1.id not in self.relationship_table:
|
331
|
+
self.relationship_table[relationship.person1.id] = []
|
332
|
+
self.relationship_table[relationship.person1.id].append(relationship)
|
333
|
+
relationship.person1._add_relationship(relationship)
|
334
|
+
else:
|
335
|
+
pass
|
336
|
+
|
337
|
+
if relationship.person2:
|
338
|
+
if relationship.person2.id is None:
|
339
|
+
relationship.person2.id = self.make_id() #TODO
|
340
|
+
if not self.persons.byId(relationship.person2.id):
|
341
|
+
self.persons.append(relationship.person2)
|
342
|
+
if relationship.person2.id not in self.relationship_table:
|
343
|
+
self.relationship_table[relationship.person2.id] = []
|
344
|
+
self.relationship_table[relationship.person2.id].append(relationship)
|
345
|
+
relationship.person2._add_relationship(relationship)
|
346
|
+
else:
|
347
|
+
pass
|
290
348
|
|
291
|
-
|
292
|
-
if relationship.person1.id is None:
|
293
|
-
relationship.person1.id = self.personURIgenerator()
|
294
|
-
if not self.persons.byId(relationship.person1.id):
|
295
|
-
self.persons.append(relationship.person1)
|
296
|
-
if relationship.person1.id not in self.relationship_table:
|
297
|
-
self.relationship_table[relationship.person1.id] = []
|
298
|
-
self.relationship_table[relationship.person1.id].append(relationship)
|
299
|
-
relationship.person1._add_relationship(relationship)
|
300
|
-
else:
|
301
|
-
pass
|
302
|
-
|
303
|
-
if relationship.person2:
|
304
|
-
if relationship.person2.id is None:
|
305
|
-
relationship.person2.id = self.personURIgenerator() #TODO
|
306
|
-
if not self.persons.byId(relationship.person2.id):
|
307
|
-
self.persons.append(relationship.person2)
|
308
|
-
if relationship.person2.id not in self.relationship_table:
|
309
|
-
self.relationship_table[relationship.person2.id] = []
|
310
|
-
self.relationship_table[relationship.person2.id].append(relationship)
|
311
|
-
relationship.person2._add_relationship(relationship)
|
312
|
-
else:
|
313
|
-
pass
|
314
|
-
|
315
|
-
self.relationships.append(relationship)
|
349
|
+
self.relationships.append(relationship)
|
316
350
|
else:
|
317
351
|
raise ValueError()
|
318
352
|
|
@@ -338,18 +372,24 @@ class GedcomX:
|
|
338
372
|
if agent in self.agents:
|
339
373
|
return
|
340
374
|
if agent.id is None:
|
341
|
-
agent.id =
|
375
|
+
agent.id = make_uid()
|
342
376
|
if self.agents.byId(agent.id):
|
343
|
-
|
344
|
-
|
377
|
+
pass #TODO Deal with duplicates
|
378
|
+
#raise ValueError
|
345
379
|
self.agents.append(agent)
|
346
380
|
|
347
381
|
def add_event(self,event_to_add: Event):
|
348
382
|
if event_to_add and isinstance(event_to_add,Event):
|
383
|
+
if event_to_add.id is None: event_to_add.id = make_uid()
|
349
384
|
for current_event in self.events:
|
350
385
|
if event_to_add == current_event:
|
386
|
+
print("DUPLICATE EVENT")
|
387
|
+
print(event_to_add._as_dict_)
|
388
|
+
print(current_event._as_dict_)
|
351
389
|
return
|
352
390
|
self.events.append(event_to_add)
|
391
|
+
else:
|
392
|
+
raise ValueError
|
353
393
|
|
354
394
|
def get_person_by_id(self,id: str):
|
355
395
|
filtered = [person for person in self.persons if getattr(person, 'id') == id]
|
@@ -361,6 +401,53 @@ class GedcomX:
|
|
361
401
|
if filtered: return filtered[0]
|
362
402
|
return None
|
363
403
|
|
404
|
+
@property
|
405
|
+
def id_index(self):
|
406
|
+
combined = {**self.source_descriptions.id_index,
|
407
|
+
**self.persons.id_index,
|
408
|
+
**self.relationships.id_index,
|
409
|
+
**self.agents.id_index,
|
410
|
+
**self.events.id_index,
|
411
|
+
**self.documents.id_index,
|
412
|
+
**self.places.id_index,
|
413
|
+
**self.groups.id_index
|
414
|
+
}
|
415
|
+
for i in combined.keys():
|
416
|
+
combined[i] = str(type(combined[i]).__name__)
|
417
|
+
return combined
|
418
|
+
|
419
|
+
@property
|
420
|
+
def _as_dict(self) -> dict[str, Any]:
|
421
|
+
type_as_dict: Dict[str, Any] = {}
|
422
|
+
|
423
|
+
if self.persons and len(self.persons) > 0:
|
424
|
+
type_as_dict["persons"] = [person._as_dict_ for person in self.persons]
|
425
|
+
|
426
|
+
if self.source_descriptions:
|
427
|
+
type_as_dict["sourceDescriptions"] = [
|
428
|
+
sd._as_dict_ for sd in self.source_descriptions
|
429
|
+
]
|
430
|
+
|
431
|
+
if self.relationships:
|
432
|
+
type_as_dict["relationships"] = [
|
433
|
+
rel._as_dict_ for rel in self.relationships
|
434
|
+
]
|
435
|
+
|
436
|
+
if self.agents:
|
437
|
+
type_as_dict["agents"] = [agent._as_dict_ for agent in self.agents]
|
438
|
+
|
439
|
+
if self.events:
|
440
|
+
type_as_dict["events"] = [event._as_dict_ for event in self.events]
|
441
|
+
|
442
|
+
if self.places:
|
443
|
+
type_as_dict["places"] = [place._as_dict_ for place in self.places]
|
444
|
+
|
445
|
+
if self.documents:
|
446
|
+
type_as_dict["documents"] = [doc._as_dict_ for doc in self.documents]
|
447
|
+
|
448
|
+
return type_as_dict
|
449
|
+
|
450
|
+
@property
|
364
451
|
def json(self):
|
365
452
|
"""
|
366
453
|
JSON Representation of the GedcomX Genealogy.
|
@@ -379,972 +466,35 @@ class GedcomX:
|
|
379
466
|
}
|
380
467
|
return json.dumps(gedcomx_json, indent=4)
|
381
468
|
|
382
|
-
class Translater():
|
383
|
-
def __init__(self,gedcom: Gedcom) -> None:
|
384
|
-
self.handlers = {}
|
385
|
-
self.gedcom: Gedcom = gedcom
|
386
|
-
self.gedcomx = GedcomX()
|
387
|
-
|
388
|
-
self.object_stack = []
|
389
|
-
self.object_map = {}
|
390
|
-
self.missing_handler_count = {}
|
391
|
-
|
392
|
-
self.translate()
|
393
|
-
|
394
|
-
|
395
|
-
gedcom_even_to_fact = {
|
396
|
-
# Person Fact Types
|
397
|
-
"ADOP": FactType.Adoption,
|
398
|
-
"CHR": FactType.AdultChristening,
|
399
|
-
"EVEN": FactType.Amnesty, # and other FactTypes with no direct GEDCOM tag
|
400
|
-
"BAPM": FactType.Baptism,
|
401
|
-
"BARM": FactType.BarMitzvah,
|
402
|
-
"BASM": FactType.BatMitzvah,
|
403
|
-
"BIRT": FactType.Birth,
|
404
|
-
"BIRT, CHR": FactType.Birth,
|
405
|
-
"BLES": FactType.Blessing,
|
406
|
-
"BURI": FactType.Burial,
|
407
|
-
"CAST": FactType.Caste,
|
408
|
-
"CENS": FactType.Census,
|
409
|
-
"CIRC": FactType.Circumcision,
|
410
|
-
"CONF": FactType.Confirmation,
|
411
|
-
"CREM": FactType.Cremation,
|
412
|
-
"DEAT": FactType.Death,
|
413
|
-
"EDUC": FactType.Education,
|
414
|
-
"EMIG": FactType.Emigration,
|
415
|
-
"FCOM": FactType.FirstCommunion,
|
416
|
-
"GRAD": FactType.Graduation,
|
417
|
-
"IMMI": FactType.Immigration,
|
418
|
-
"MIL": FactType.MilitaryService,
|
419
|
-
"NATI": FactType.Nationality,
|
420
|
-
"NATU": FactType.Naturalization,
|
421
|
-
"OCCU": FactType.Occupation,
|
422
|
-
"ORDN": FactType.Ordination,
|
423
|
-
"DSCR": FactType.PhysicalDescription,
|
424
|
-
"PROB": FactType.Probate,
|
425
|
-
"PROP": FactType.Property,
|
426
|
-
"RELI": FactType.Religion,
|
427
|
-
"RESI": FactType.Residence,
|
428
|
-
"WILL": FactType.Will,
|
429
|
-
|
430
|
-
# Couple Relationship Fact Types
|
431
|
-
"ANUL": FactType.Annulment,
|
432
|
-
"DIV": FactType.Divorce,
|
433
|
-
"DIVF": FactType.DivorceFiling,
|
434
|
-
"ENGA": FactType.Engagement,
|
435
|
-
"MARR": FactType.Marriage,
|
436
|
-
"MARB": FactType.MarriageBanns,
|
437
|
-
"MARC": FactType.MarriageContract,
|
438
|
-
"MARL": FactType.MarriageLicense,
|
439
|
-
"SEPA": FactType.Separation,
|
440
|
-
|
441
|
-
# Parent-Child Relationship Fact Types
|
442
|
-
# (Note: Only ADOPTION has a direct GEDCOM tag, others are under "EVEN")
|
443
|
-
"ADOP": FactType.AdoptiveParent
|
444
|
-
}
|
445
|
-
|
446
|
-
gedcom_even_to_evnt = {
|
447
|
-
# Person Fact Types
|
448
|
-
"ADOP": EventType.Adoption,
|
449
|
-
"CHR": EventType.AdultChristening,
|
450
|
-
"BAPM": EventType.Baptism,
|
451
|
-
"BARM": EventType.BarMitzvah,
|
452
|
-
"BASM": EventType.BatMitzvah,
|
453
|
-
"BIRT": EventType.Birth,
|
454
|
-
"BIRT, CHR": EventType.Birth,
|
455
|
-
"BLES": EventType.Blessing,
|
456
|
-
"BURI": EventType.Burial,
|
457
|
-
|
458
|
-
"CENS": EventType.Census,
|
459
|
-
"CIRC": EventType.Circumcision,
|
460
|
-
"CONF": EventType.Confirmation,
|
461
|
-
"CREM": EventType.Cremation,
|
462
|
-
"DEAT": EventType.Death,
|
463
|
-
"EDUC": EventType.Education,
|
464
|
-
"EMIG": EventType.Emigration,
|
465
|
-
"FCOM": EventType.FirstCommunion,
|
466
|
-
|
467
|
-
"IMMI": EventType.Immigration,
|
468
|
-
|
469
|
-
"NATU": EventType.Naturalization,
|
470
|
-
|
471
|
-
"ORDN": EventType.Ordination,
|
472
|
-
|
473
|
-
|
474
|
-
# Couple Relationship Fact Types
|
475
|
-
"ANUL": EventType.Annulment,
|
476
|
-
"DIV": EventType.Divorce,
|
477
|
-
"DIVF": EventType.DivorceFiling,
|
478
|
-
"ENGA": EventType.Engagement,
|
479
|
-
"MARR": EventType.Marriage
|
480
|
-
|
481
|
-
}
|
482
|
-
|
483
469
|
@staticmethod
|
484
|
-
def
|
485
|
-
|
486
|
-
|
487
|
-
return None
|
488
|
-
clean_text = re.sub(r'<[^>]+>', '', text)
|
489
|
-
|
490
|
-
return clean_text
|
491
|
-
|
492
|
-
def translate(self):
|
493
|
-
for n, repository in enumerate(self.gedcom.repositories):
|
494
|
-
print(f"Parsing Repository {n}")
|
495
|
-
self.parse_record(repository)
|
496
|
-
print(f"Translated {len(self.gedcomx.agents)} 'REPO' records to Agents")
|
497
|
-
for source in self.gedcom.sources:
|
498
|
-
self.parse_record(source)
|
499
|
-
print(f"Translated {len(self.gedcomx.source_descriptions)} 'SOUR' records to SourceDescription")
|
500
|
-
|
501
|
-
for object in self.gedcom.objects:
|
502
|
-
self.parse_record(object)
|
503
|
-
print(f"Translated {len(self.gedcom.objects)} 'OBJE' records to SourceDescriptions")
|
504
|
-
|
505
|
-
for individual in self.gedcom.individuals:
|
506
|
-
self.parse_record(individual)
|
507
|
-
print(f"Translated {len(self.gedcomx.persons)} 'INDI' records to Persons")
|
508
|
-
|
509
|
-
for key in self.missing_handler_count:
|
510
|
-
print(f"{key}: {self.missing_handler_count[key]}")
|
511
|
-
|
470
|
+
def from_json(data: dict):
|
471
|
+
from .Serialization import Serialization
|
472
|
+
gx = GedcomX()
|
512
473
|
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
self.handle_fam(family)
|
517
|
-
print(f"Translated {fam_count} 'FAM' records to {len(self.gedcomx.relationships)} Relationship")
|
474
|
+
source_descriptions = data.get('sourceDescriptions', [])
|
475
|
+
for source in source_descriptions:
|
476
|
+
gx.add_source_description(Serialization.deserialize(source,SourceDescription))
|
518
477
|
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
# Regular expression pattern to match URLs
|
523
|
-
url_pattern = re.compile(r'https?://[^\s]+')
|
524
|
-
# Find all URLs using the pattern
|
525
|
-
urls = url_pattern.findall(text)
|
526
|
-
return urls
|
527
|
-
|
528
|
-
@property
|
529
|
-
def event_type_conversion_table(self):
|
530
|
-
return {'BIRT':EventType.Birth,
|
531
|
-
'OBIT':FactType.Obituary}
|
532
|
-
|
533
|
-
def parse_record(self,record: GedcomRecord):
|
534
|
-
|
535
|
-
handler_name = 'handle_' + record.tag.lower()
|
536
|
-
|
537
|
-
if hasattr(self,handler_name):
|
538
|
-
convert_log.info(f'Parsing Record: {record.describe()}')
|
539
|
-
handler = getattr(self,handler_name)
|
540
|
-
handler(record)
|
541
|
-
else:
|
542
|
-
if record.tag in self.missing_handler_count:
|
543
|
-
self.missing_handler_count[record.tag] += 1
|
544
|
-
else:
|
545
|
-
self.missing_handler_count[record.tag] = 1
|
546
|
-
|
547
|
-
convert_log.error(f'Failed Parsing Record: {record.describe()}')
|
548
|
-
for sub_record in record.subRecords():
|
549
|
-
self.parse_record(sub_record)
|
550
|
-
|
551
|
-
def handle__apid(self, record: GedcomRecord):
|
552
|
-
if isinstance(self.object_map[record.level-1], SourceReference):
|
553
|
-
self.object_map[record.level-1].description.add_identifier(Identifier(value=URI.from_url('APID://' + record.value)))
|
554
|
-
elif isinstance(self.object_map[record.level-1], SourceDescription):
|
555
|
-
self.object_map[record.level-1].add_identifier(Identifier(value=URI.from_url('APID://' + record.value)))
|
556
|
-
else:
|
557
|
-
raise ValueError(f"Could not handle '_APID' tag in record {record.describe()}, last stack object {type(self.object_map[record.level-1])}")
|
558
|
-
|
559
|
-
def handle__meta(self, record: GedcomRecord):
|
560
|
-
if isinstance(self.object_map[record.level-1], SourceDescription):
|
561
|
-
gxobject = Note(text=Translater.clean_str(record.value))
|
562
|
-
self.object_map[record.level-1].add_note(gxobject)
|
563
|
-
self.object_stack.append(gxobject)
|
564
|
-
self.object_map[record.level] = gxobject
|
565
|
-
else:
|
566
|
-
raise ValueError(f"Could not handle 'WWW' tag in record {record.describe()}, last stack object {self.object_map[record.level-1]}")
|
567
|
-
|
568
|
-
def handle__wlnk(self, record: GedcomRecord):
|
569
|
-
return self.handle_sour(record)
|
570
|
-
|
571
|
-
def handle_addr(self, record: GedcomRecord):
|
572
|
-
if isinstance(self.object_map[record.level-1], Agent):
|
573
|
-
# TODO CHeck if URL?
|
574
|
-
if Translater.clean_str(record.value):
|
575
|
-
gxobject = Address(value=Translater.clean_str(record.value))
|
576
|
-
else:
|
577
|
-
gxobject = Address()
|
578
|
-
self.object_map[record.level-1].address = gxobject
|
579
|
-
self.object_stack.append(gxobject)
|
580
|
-
self.object_map[record.level] = gxobject
|
581
|
-
else:
|
582
|
-
raise ValueError(f"I do not know how to handle an 'ADDR' tag for a {type(self.object_map[record.level-1])}")
|
583
|
-
|
584
|
-
def handle_adr1(self, record: GedcomRecord):
|
585
|
-
if isinstance(self.object_map[record.level-1], Address):
|
586
|
-
if Translater.clean_str(record.value):
|
587
|
-
self.object_map[record.level-1].street = Translater.clean_str(record.value)
|
588
|
-
else:
|
589
|
-
raise ValueError(f"I do not know how to handle an 'ADR1' tag for a {type(self.object_map[record.level-1])}")
|
590
|
-
|
591
|
-
def handle_adr2(self, record: GedcomRecord):
|
592
|
-
if isinstance(self.object_map[record.level-1], Address):
|
593
|
-
if Translater.clean_str(record.value):
|
594
|
-
self.object_map[record.level-1].street2 = Translater.clean_str(record.value)
|
595
|
-
else:
|
596
|
-
raise ValueError(f"I do not know how to handle an 'ADR2' tag for a {type(self.object_map[record.level-1])}")
|
597
|
-
|
598
|
-
def handle_adr3(self, record: GedcomRecord):
|
599
|
-
if isinstance(self.object_map[record.level-1], Address):
|
600
|
-
if Translater.clean_str(record.value):
|
601
|
-
self.object_map[record.level-1].street3 = Translater.clean_str(record.value)
|
602
|
-
else:
|
603
|
-
raise ValueError(f"I do not know how to handle an 'ADR3' tag for a {type(self.object_map[record.level-1])}")
|
604
|
-
|
605
|
-
def handle_adr4(self, record: GedcomRecord):
|
606
|
-
if isinstance(self.object_map[record.level-1], Address):
|
607
|
-
if Translater.clean_str(record.value):
|
608
|
-
self.object_map[record.level-1].street4 = Translater.clean_str(record.value)
|
609
|
-
else:
|
610
|
-
raise ValueError(f"I do not know how to handle an 'ADR4' tag for a {type(self.object_map[record.level-1])}")
|
611
|
-
|
612
|
-
def handle_adr5(self, record: GedcomRecord):
|
613
|
-
if isinstance(self.object_map[record.level-1], Address):
|
614
|
-
if Translater.clean_str(record.value):
|
615
|
-
self.object_map[record.level-1].street5 = Translater.clean_str(record.value)
|
616
|
-
else:
|
617
|
-
raise ValueError(f"I do not know how to handle an 'ADR5' tag for a {type(self.object_map[record.level-1])}")
|
618
|
-
|
619
|
-
def handle_adr6(self, record: GedcomRecord):
|
620
|
-
if isinstance(self.object_map[record.level-1], Address):
|
621
|
-
if Translater.clean_str(record.value):
|
622
|
-
self.object_map[record.level-1].street5 = Translater.clean_str(record.value)
|
623
|
-
else:
|
624
|
-
raise ValueError(f"I do not know how to handle an 'ADR6' tag for a {type(self.object_map[record.level-1])}")
|
625
|
-
|
626
|
-
def handle_phon(self, record: GedcomRecord):
|
627
|
-
if isinstance(self.object_map[record.level-1], Agent):
|
628
|
-
if Translater.clean_str(record.value):
|
629
|
-
self.object_map[record.level-1].phones.append(Translater.clean_str(record.value))
|
630
|
-
else:
|
631
|
-
raise ValueError(f"I do not know how to handle an '{record.tag}' tag for a {type(self.object_map[record.level-1])}")
|
632
|
-
|
633
|
-
def handle_email(self, record: GedcomRecord):
|
634
|
-
if isinstance(self.object_map[record.level-1], Agent):
|
635
|
-
if Translater.clean_str(record.value):
|
636
|
-
self.object_map[record.level-1].emails.append(Translater.clean_str(record.value))
|
637
|
-
else:
|
638
|
-
raise ValueError(f"I do not know how to handle an '{record.tag}' tag for a {type(self.object_map[record.level-1])}")
|
639
|
-
|
640
|
-
def handle_fax(self, record: GedcomRecord):
|
641
|
-
if isinstance(self.object_map[record.level-1], Agent):
|
642
|
-
if Translater.clean_str(record.value):
|
643
|
-
self.object_map[record.level-1].emails.append('FAX:' + Translater.clean_str(record.value))
|
644
|
-
else:
|
645
|
-
raise ValueError(f"I do not know how to handle an '{record.tag}' tag for a {type(self.object_map[record.level-1])}")
|
646
|
-
|
647
|
-
def handle_adop(self, record: GedcomRecord):
|
648
|
-
if isinstance(self.object_map[record.level-1], Person):
|
649
|
-
gxobject = Fact(type=FactType.Adoption)
|
650
|
-
self.object_map[record.level-1].add_fact(gxobject)
|
651
|
-
|
652
|
-
self.object_stack.append(gxobject)
|
653
|
-
self.object_map[record.level] = gxobject
|
654
|
-
else:
|
655
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
656
|
-
|
657
|
-
def handle_auth(self, record: GedcomRecord):
|
658
|
-
if isinstance(self.object_map[record.level-1], SourceDescription):
|
659
|
-
if self.gedcomx.agents.byName(record.value):
|
660
|
-
gxobject = self.gedcomx.agents.byName(record.value)[0]
|
661
|
-
else:
|
662
|
-
gxobject = Agent(names=[TextValue(record.value)])
|
663
|
-
self.gedcomx.add_agent(gxobject)
|
664
|
-
|
665
|
-
self.object_map[record.level-1].author = gxobject
|
666
|
-
self.object_stack.append(gxobject)
|
667
|
-
self.object_map[record.level] = gxobject
|
668
|
-
else:
|
669
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
670
|
-
|
671
|
-
def handle_bapm(self, record: GedcomRecord):
|
672
|
-
if isinstance(self.object_map[record.level-1], Person):
|
673
|
-
gxobject = Fact(type=FactType.Baptism)
|
674
|
-
self.object_map[record.level-1].add_fact(gxobject)
|
675
|
-
|
676
|
-
self.object_stack.append(gxobject)
|
677
|
-
self.object_map[record.level] = gxobject
|
678
|
-
else:
|
679
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
680
|
-
|
681
|
-
def handle_birt(self, record: GedcomRecord):
|
682
|
-
if isinstance(self.object_map[record.level-1], Person):
|
683
|
-
#gxobject = Event(type=EventType.BIRTH, roles=[EventRole(person=self.object_map[record.level-1], type=EventRoleType.Principal)])
|
684
|
-
gxobject = Fact(type=FactType.Birth)
|
685
|
-
#self.gedcomx.add_event(gxobject)
|
686
|
-
self.object_map[record.level-1].add_fact(gxobject)
|
687
|
-
|
688
|
-
self.object_stack.append(gxobject)
|
689
|
-
self.object_map[record.level] = gxobject
|
690
|
-
else:
|
691
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
692
|
-
|
693
|
-
def handle_buri(self, record: GedcomRecord):
|
694
|
-
if isinstance(self.object_map[record.level-1], Person):
|
695
|
-
gxobject = Fact(type=FactType.Burial)
|
696
|
-
self.object_map[record.level-1].add_fact(gxobject)
|
697
|
-
|
698
|
-
self.object_stack.append(gxobject)
|
699
|
-
self.object_map[record.level] = gxobject
|
700
|
-
else:
|
701
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
702
|
-
|
703
|
-
def handle_caln(self, record: GedcomRecord):
|
704
|
-
if isinstance(self.object_map[record.level-1], SourceReference):
|
705
|
-
self.object_map[record.level-1].description.add_identifier(Identifier(value=URI.from_url('Call Number:' + record.value)))
|
706
|
-
elif isinstance(self.object_map[record.level-1], SourceDescription):
|
707
|
-
self.object_map[record.level-1].add_identifier(Identifier(value=URI.from_url('Call Number:' + record.value)))
|
708
|
-
elif isinstance(self.object_map[record.level-1], Agent):
|
709
|
-
pass
|
710
|
-
# TODO Why is GEDCOM so shitty? A callnumber for a repository?
|
711
|
-
else:
|
712
|
-
raise ValueError(f"Could not handle 'CALN' tag in record {record.describe()}, last stack object {type(self.object_map[record.level-1])}")
|
713
|
-
|
714
|
-
def handle_chan(self, record: GedcomRecord):
|
715
|
-
if isinstance(self.object_map[record.level-1], SourceDescription):
|
716
|
-
self.object_map[record.level-1].created = Date(record.subRecord('DATE'))
|
717
|
-
elif isinstance(self.object_map[record.level-1], Agent):
|
718
|
-
if self.object_map[record.level-1].attribution is None:
|
719
|
-
gxobject = Attribution()
|
720
|
-
self.object_map[record.level-1].attribution = gxobject
|
721
|
-
self.object_stack.append(gxobject)
|
722
|
-
self.object_map[record.level] = gxobject
|
723
|
-
else:
|
724
|
-
raise ValueError()
|
725
|
-
|
726
|
-
def handle_chr(self, record: GedcomRecord):
|
727
|
-
if isinstance(self.object_map[record.level-1], Person):
|
728
|
-
gxobject = Fact(type=FactType.Christening)
|
729
|
-
self.object_map[record.level-1].add_fact(gxobject)
|
730
|
-
|
731
|
-
self.object_stack.append(gxobject)
|
732
|
-
self.object_map[record.level] = gxobject
|
733
|
-
else:
|
734
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
735
|
-
|
736
|
-
def handle_city(self, record: GedcomRecord):
|
737
|
-
if isinstance(self.object_map[record.level-1], Address):
|
738
|
-
self.object_map[record.level-1].city = Translater.clean_str(record.value)
|
739
|
-
else:
|
740
|
-
raise ValueError(f"I do not know how to handle an 'CITY' tag for a {type(self.object_map[record.level-1])}")
|
741
|
-
|
742
|
-
def handle_conc(self, record: GedcomRecord):
|
743
|
-
if isinstance(self.object_map[record.level-1], Note):
|
744
|
-
gxobject = Translater.clean_str(str(record.value))
|
745
|
-
self.object_map[record.level-1].append(gxobject)
|
746
|
-
elif isinstance(self.object_map[record.level-1], Agent):
|
747
|
-
gxobject = str(record.value)
|
748
|
-
self.object_map[record.level-1]._append_to_name(gxobject)
|
749
|
-
elif isinstance(self.object_map[record.level-1], Qualifier):
|
750
|
-
gxobject = str(record.value)
|
751
|
-
self.object_map[record.level-2].append(gxobject)
|
752
|
-
elif isinstance(self.object_map[record.level-1], TextValue):
|
753
|
-
#gxobject = TextValue(value=Translater.clean_str(record.value))
|
754
|
-
self.object_map[record.level-1]._append_to_value(record.value)
|
755
|
-
elif isinstance(self.object_map[record.level-1], SourceReference):
|
756
|
-
self.object_map[record.level-1].append(record.value)
|
757
|
-
elif isinstance(self.object_map[record.level-1], Fact):
|
758
|
-
self.object_map[record.level-1].notes[0].text += record.value
|
759
|
-
|
760
|
-
else:
|
761
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
762
|
-
|
763
|
-
def handle_cont(self, record: GedcomRecord):
|
764
|
-
if isinstance(self.object_map[record.level-1], Note):
|
765
|
-
gxobject = str("\n" + record.value if record.value else '')
|
766
|
-
self.object_map[record.level-1].append(gxobject)
|
767
|
-
elif isinstance(self.object_map[record.level-1], Agent):
|
768
|
-
gxobject = str("\n" + record.value if record.value else '')
|
769
|
-
elif isinstance(self.object_map[record.level-1], Qualifier):
|
770
|
-
gxobject = str("\n" + record.value if record.value else '')
|
771
|
-
self.object_map[record.level-1].append(gxobject)
|
772
|
-
elif isinstance(self.object_map[record.level-1], TextValue):
|
773
|
-
#gxobject = TextValue(value="\n" + record.value)
|
774
|
-
self.object_map[record.level-1]._append_to_value(record.value if record.value else '\n')
|
775
|
-
elif isinstance(self.object_map[record.level-1], SourceReference):
|
776
|
-
self.object_map[record.level-1].append(record.value)
|
777
|
-
elif isinstance(self.object_map[record.level-1], Address):
|
778
|
-
self.object_map[record.level-1]._append(record.value)
|
779
|
-
else:
|
780
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
781
|
-
|
782
|
-
def handle_crea(self, record: GedcomRecord):
|
783
|
-
if isinstance(self.object_map[record.level-1], SourceDescription):
|
784
|
-
self.object_map[record.level-1].created = Date(original=record.subRecord('DATE'))
|
785
|
-
|
786
|
-
elif isinstance(self.object_map[record.level-1], Agent):
|
787
|
-
if self.object_map[record.level-1].attribution is None:
|
788
|
-
gxobject = Attribution()
|
789
|
-
self.object_map[record.level-1].attribution = gxobject
|
790
|
-
self.object_stack.append(gxobject)
|
791
|
-
self.object_map[record.level] = gxobject
|
792
|
-
else:
|
793
|
-
convert_log.info(f"[{record.tag}] Attribution already exists for SourceDescription with id: {self.object_map[record.level-1].id}")
|
794
|
-
else:
|
795
|
-
raise ValueError(f"Could not handle '{record.tag}' tag in record {record.describe()}, last stack object {self.object_map[record.level-1]}")
|
796
|
-
|
797
|
-
def handle_ctry(self, record: GedcomRecord):
|
798
|
-
if isinstance(self.object_map[record.level-1], Address):
|
799
|
-
self.object_map[record.level-1].country = Translater.clean_str(record.value)
|
800
|
-
else:
|
801
|
-
raise ValueError(f"I do not know how to handle an '{record.tag}' tag for a {type(self.object_map[record.level-1])}")
|
802
|
-
|
803
|
-
def handle_data(self, record: GedcomRecord) -> None:
|
804
|
-
if record.value != '' and record.value == 'None':
|
805
|
-
assert False
|
806
|
-
self.object_map[record.level] = self.object_map[record.level-1]
|
807
|
-
|
808
|
-
def handle_date(self, record: GedcomRecord):
|
809
|
-
if record.parent.tag == 'PUBL':
|
810
|
-
#gxobject = Date(original=record.value) #TODO Make a parser for solid timestamps
|
811
|
-
#self.object_map[0].published = gxobject
|
812
|
-
#self.object_map[0].published = date_to_timestamp(record.value) if record.value else None
|
813
|
-
self.object_map[0].published = record.value
|
814
|
-
#self.object_stack.append(gxobject)
|
815
|
-
#self.object_map[record.level] = gxobject
|
816
|
-
elif isinstance(self.object_map[record.level-1], Event):
|
817
|
-
self.object_map[record.level-1].date = Date(original=record.value)
|
818
|
-
elif isinstance(self.object_map[record.level-1], Fact):
|
819
|
-
self.object_map[record.level-1].date = Date(original=record.value)
|
820
|
-
elif record.parent.tag == 'DATA' and isinstance(self.object_map[record.level-2], SourceReference):
|
821
|
-
gxobject = Note(text='Date: ' + record.value)
|
822
|
-
self.object_map[record.level-2].description.add_note(gxobject)
|
823
|
-
self.object_stack.append(gxobject)
|
824
|
-
self.object_map[record.level] = gxobject
|
825
|
-
elif isinstance(self.object_map[record.level-1], SourceDescription):
|
826
|
-
|
827
|
-
self.object_map[record.level-1].ctreated = record.value #TODO String to timestamp
|
828
|
-
elif isinstance(self.object_map[record.level-1], Attribution):
|
829
|
-
if record.parent.tag == 'CREA':
|
830
|
-
self.object_map[record.level-1].created = record.value #TODO G7
|
831
|
-
elif record.parent.tag == "CHAN":
|
832
|
-
self.object_map[record.level-1].modified = record.value #TODO G7
|
833
|
-
elif record.parent.tag in ['CREA','CHAN']:
|
834
|
-
pass
|
835
|
-
|
836
|
-
else:
|
837
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
838
|
-
|
839
|
-
def handle_deat(self, record: GedcomRecord):
|
840
|
-
if isinstance(self.object_map[record.level-1], Person):
|
841
|
-
gxobject = Fact(type=FactType.Death)
|
842
|
-
self.object_map[record.level-1].add_fact(gxobject)
|
843
|
-
|
844
|
-
self.object_stack.append(gxobject)
|
845
|
-
self.object_map[record.level] = gxobject
|
846
|
-
else:
|
847
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
848
|
-
|
849
|
-
def handle_even(self, record: GedcomRecord):
|
850
|
-
# TODO If events in a @S, check if only 1 person matches?
|
851
|
-
if record.value and (not record.value.strip() == ''):
|
852
|
-
values = [value.strip() for value in record.value.split(",")]
|
853
|
-
for value in values:
|
854
|
-
if value in Translater.gedcom_even_to_fact.keys():
|
855
|
-
if isinstance(self.object_map[record.level-1], Person):
|
856
|
-
gxobject = Fact(type=Translater.gedcom_even_to_fact[value])
|
857
|
-
self.object_map[record.level-1].add_fact(gxobject)
|
858
|
-
|
859
|
-
self.object_stack.append(gxobject)
|
860
|
-
self.object_map[record.level] = gxobject
|
861
|
-
|
862
|
-
elif isinstance(self.object_map[record.level-1], SourceDescription):
|
863
|
-
gxobject = Event(type=Translater.gedcom_even_to_evnt[value],sources=[self.object_map[record.level-1]])
|
864
|
-
self.gedcomx.add_event(gxobject)
|
865
|
-
self.object_stack.append(gxobject)
|
866
|
-
self.object_map[record.level] = gxobject
|
867
|
-
else:
|
868
|
-
convert_log.warning(f"Could not convert EVEN '{value}' for object of type {type(self.object_map[record.level-1])} in record {record.describe()}")
|
869
|
-
return
|
870
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
871
|
-
assert False
|
872
|
-
# TODO: Fix, this. making an event to cacth subtags, why are these fact tied to a source? GEDCOM is horrible
|
873
|
-
gxobject = Event(type=EventType.UNKNOWN)
|
874
|
-
self.object_stack.append(gxobject)
|
875
|
-
self.object_map[record.level] = gxobject
|
876
|
-
else:
|
877
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
878
|
-
|
879
|
-
else:
|
880
|
-
possible_fact = FactType.guess(record.subRecord('TYPE')[0].value)
|
881
|
-
if possible_fact:
|
882
|
-
gxobject = Fact(type=possible_fact)
|
883
|
-
self.object_map[record.level-1].add_fact(gxobject)
|
884
|
-
|
885
|
-
self.object_stack.append(gxobject)
|
886
|
-
self.object_map[record.level] = gxobject
|
887
|
-
return
|
888
|
-
elif EventType.guess(record.subRecord('TYPE')[0].value):
|
889
|
-
if isinstance(self.object_map[record.level-1], Person):
|
890
|
-
gxobject = Event(type=EventType.guess(record.subRecord('TYPE')[0].value), roles=[EventRole(person=self.object_map[record.level-1], type=EventRoleType.Principal)])
|
891
|
-
self.gedcomx.add_event(gxobject)
|
892
|
-
self.object_stack.append(gxobject)
|
893
|
-
self.object_map[record.level] = gxobject
|
894
|
-
return
|
895
|
-
else:
|
896
|
-
if isinstance(self.object_map[record.level-1], Person):
|
897
|
-
gxobject = Event(type=None, roles=[EventRole(person=self.object_map[record.level-1], type=EventRoleType.Principal)])
|
898
|
-
gxobject.add_note(Note(subject='Event', text=record.value))
|
899
|
-
self.gedcomx.add_event(gxobject)
|
900
|
-
self.object_stack.append(gxobject)
|
901
|
-
self.object_map[record.level] = gxobject
|
902
|
-
return
|
903
|
-
|
904
|
-
else:
|
905
|
-
assert False
|
906
|
-
|
907
|
-
def handle_exid(self,record: GedcomRecord):
|
908
|
-
gxobject = Identifier(type=IdentifierType.External,value=[record.value])
|
909
|
-
self.object_map[record.level-1].add_identifier(gxobject)
|
910
|
-
|
911
|
-
self.object_stack.append(gxobject)
|
912
|
-
self.object_map[record.level] = gxobject
|
913
|
-
|
914
|
-
def handle_fam(self, record: GedcomRecord) -> None:
|
915
|
-
if record.tag != 'FAM' or record.level != 0:
|
916
|
-
raise ValueError("Invalid record: Must be a level 0 FAM record")
|
917
|
-
|
918
|
-
husband, wife, children = None, None, []
|
919
|
-
|
920
|
-
husband_record = record.subRecords('HUSB')
|
921
|
-
if husband_record:
|
922
|
-
husband = self.gedcomx.get_person_by_id(husband_record[0].xref)
|
923
|
-
|
924
|
-
wife_record = record.subRecords('WIFE')
|
925
|
-
if wife_record:
|
926
|
-
wife = self.gedcomx.get_person_by_id(wife_record[0].xref)
|
927
|
-
|
928
|
-
children_records = record.subRecords('CHIL')
|
929
|
-
if children_records:
|
930
|
-
for child_record in children_records:
|
931
|
-
child = self.gedcomx.get_person_by_id(child_record.xref)
|
932
|
-
if child:
|
933
|
-
children.append(child)
|
934
|
-
|
935
|
-
if husband:
|
936
|
-
for child in children:
|
937
|
-
relationship = Relationship(person1=husband, person2=child, type=RelationshipType.ParentChild)
|
938
|
-
self.gedcomx.add_relationship(relationship)
|
939
|
-
if wife:
|
940
|
-
for child in children:
|
941
|
-
relationship = Relationship(person1=wife, person2=child, type=RelationshipType.ParentChild)
|
942
|
-
self.gedcomx.add_relationship(relationship)
|
943
|
-
if husband and wife:
|
944
|
-
relationship = Relationship(person1=husband, person2=wife, type=RelationshipType.Couple)
|
945
|
-
self.gedcomx.add_relationship(relationship)
|
946
|
-
|
947
|
-
def handle_famc(self, record: GedcomRecord) -> None:
|
948
|
-
return
|
949
|
-
|
950
|
-
def handle_fams(self, record: GedcomRecord) -> None:
|
951
|
-
return
|
952
|
-
|
953
|
-
def handle_file(self, record: GedcomRecord):
|
954
|
-
if record.value and record.value.strip() != '':
|
955
|
-
#raise ValueError(f"I did not expect the 'FILE' tag to have a value: {record.value}")
|
956
|
-
#TODO Handle files referenced here
|
957
|
-
...
|
958
|
-
elif isinstance(self.object_map[record.level-1], SourceDescription):
|
959
|
-
...
|
960
|
-
self.object_map[record.level-1].resourceType = ResourceType.DigitalArtifact
|
961
|
-
|
962
|
-
def handle_form(self, record: GedcomRecord):
|
963
|
-
if record.parent.tag == 'FILE' and isinstance(self.object_map[record.level-2], SourceDescription):
|
964
|
-
if record.value and record.value.strip() != '':
|
965
|
-
mime_type, _ = mimetypes.guess_type('placehold.' + record.value)
|
966
|
-
if mime_type:
|
967
|
-
self.object_map[record.level-2].mediaType = mime_type
|
968
|
-
else:
|
969
|
-
print(f"Could not determing mime type from {record.value}")
|
970
|
-
elif isinstance(self.object_map[record.level-1], PlaceDescription):
|
971
|
-
self.object_map[record.level-1].names.append(TextValue(value=record.value))
|
972
|
-
elif record.parent.tag == 'TRAN':
|
973
|
-
pass #TODO
|
974
|
-
else:
|
975
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
976
|
-
|
977
|
-
def handle_givn(self, record: GedcomRecord):
|
978
|
-
if isinstance(self.object_map[record.level-1], Name):
|
979
|
-
given_name = NamePart(value=record.value, type=NamePartType.Given)
|
980
|
-
self.object_map[record.level-1]._add_name_part(given_name)
|
981
|
-
else:
|
982
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
983
|
-
|
984
|
-
def handle_indi(self, record: GedcomRecord):
|
985
|
-
person = Person(id=record.xref.replace('@',''))
|
986
|
-
self.gedcomx.add_person(person)
|
987
|
-
self.object_stack.append(person)
|
988
|
-
self.object_map[record.level] = person
|
989
|
-
|
990
|
-
def handle_immi(self, record: GedcomRecord):
|
991
|
-
if isinstance(self.object_map[record.level-1], Person):
|
992
|
-
gxobject = Fact(type=FactType.Immigration)
|
993
|
-
self.object_map[record.level-1].add_fact(gxobject)
|
994
|
-
|
995
|
-
self.object_stack.append(gxobject)
|
996
|
-
self.object_map[record.level] = gxobject
|
997
|
-
else:
|
998
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
999
|
-
|
1000
|
-
def handle_marr(self, record: GedcomRecord):
|
1001
|
-
if isinstance(self.object_map[record.level-1], Person):
|
1002
|
-
gxobject = Fact(type=FactType.Marriage)
|
1003
|
-
self.object_map[record.level-1].add_fact(gxobject)
|
1004
|
-
|
1005
|
-
self.object_stack.append(gxobject)
|
1006
|
-
self.object_map[record.level] = gxobject
|
1007
|
-
else:
|
1008
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
1009
|
-
|
1010
|
-
def handle_name(self, record: GedcomRecord):
|
1011
|
-
if isinstance(self.object_map[record.level-1], Person):
|
1012
|
-
gxobject = Name.simple(record.value)
|
1013
|
-
#gxobject = Name(nameForms=[NameForm(fullText=record.value)], type=NameType.BirthName)
|
1014
|
-
self.object_map[record.level-1].add_name(gxobject)
|
1015
|
-
|
1016
|
-
self.object_stack.append(gxobject)
|
1017
|
-
self.object_map[record.level] = gxobject
|
1018
|
-
elif isinstance(self.object_map[record.level-1], Agent):
|
1019
|
-
gxobject = TextValue(value=record.value)
|
1020
|
-
self.object_map[record.level-1].add_name(gxobject)
|
1021
|
-
else:
|
1022
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
1023
|
-
|
1024
|
-
def handle_note(self, record: GedcomRecord):
|
1025
|
-
if isinstance(self.object_map[record.level-1], SourceDescription):
|
1026
|
-
gxobject = Note(text=Translater.clean_str(record.value))
|
1027
|
-
self.object_map[record.level-1].add_note(gxobject)
|
1028
|
-
|
1029
|
-
self.object_stack.append(gxobject)
|
1030
|
-
self.object_map[record.level] = gxobject
|
1031
|
-
elif isinstance(self.object_map[record.level-1], SourceReference):
|
1032
|
-
gxobject = Note(text=Translater.clean_str(record.value))
|
1033
|
-
self.object_map[record.level-1].description.add_note(gxobject)
|
1034
|
-
|
1035
|
-
self.object_stack.append(gxobject)
|
1036
|
-
self.object_map[record.level] = gxobject
|
1037
|
-
elif isinstance(self.object_map[record.level-1], Conclusion):
|
1038
|
-
gxobject = Note(text=record.value)
|
1039
|
-
self.object_map[record.level-1].add_note(gxobject)
|
1040
|
-
|
1041
|
-
self.object_stack.append(gxobject)
|
1042
|
-
self.object_map[record.level] = gxobject
|
1043
|
-
elif isinstance(self.object_map[record.level-1], Agent):
|
1044
|
-
gxobject = Note(text=record.value)
|
1045
|
-
self.object_map[record.level-1].add_note(gxobject)
|
1046
|
-
|
1047
|
-
self.object_stack.append(gxobject)
|
1048
|
-
self.object_map[record.level] = gxobject
|
1049
|
-
elif isinstance(self.object_map[record.level-1], Attribution):
|
1050
|
-
if self.object_map[record.level-1].changeMessage is None:
|
1051
|
-
self.object_map[record.level-1].changeMessage = record.value
|
1052
|
-
else:
|
1053
|
-
self.object_map[record.level-1].changeMessage = self.object_map[record.level-1].changeMessage + '' + record.value
|
1054
|
-
|
1055
|
-
else:
|
1056
|
-
raise ValueError(f"Could not handle 'NOTE' tag in record {record.describe()}, last stack object {type(self.object_map[record.level-1])}")
|
1057
|
-
assert False
|
1058
|
-
|
1059
|
-
def handle_nsfx(self, record: GedcomRecord):
|
1060
|
-
if isinstance(self.object_map[record.level-1], Name):
|
1061
|
-
surname = NamePart(value=record.value, type=NamePartType.Suffix)
|
1062
|
-
self.object_map[record.level-1]._add_name_part(surname)
|
1063
|
-
else:
|
1064
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
1065
|
-
|
1066
|
-
def handle_occu(self, record: GedcomRecord):
|
1067
|
-
if isinstance(self.object_map[record.level-1], Person):
|
1068
|
-
gxobject = Fact(type=FactType.Occupation)
|
1069
|
-
self.object_map[record.level-1].add_fact(gxobject)
|
1070
|
-
|
1071
|
-
self.object_stack.append(gxobject)
|
1072
|
-
self.object_map[record.level] = gxobject
|
1073
|
-
else:
|
1074
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
1075
|
-
|
1076
|
-
def handle_obje(self, record: GedcomRecord):
|
1077
|
-
self.handle_sour(record)
|
1078
|
-
|
1079
|
-
def handle_page(self, record: GedcomRecord):
|
1080
|
-
if isinstance(self.object_map[record.level-1], SourceReference):
|
1081
|
-
self.object_map[record.level-1].descriptionId = record.value
|
1082
|
-
self.object_map[record.level-1].add_qualifier(KnownSourceReference(name=str(KnownSourceReference.Page),value=record.value))
|
1083
|
-
|
1084
|
-
#self.object_stack.append(gxobject)
|
1085
|
-
#self.object_map[record.level] = gxobject
|
1086
|
-
self.object_map[record.level] = self.object_map[record.level-1]
|
1087
|
-
else:
|
1088
|
-
raise ValueError(f"Could not handle 'PAGE' tag in record {record.describe()}, last stack object {self.object_map[record.level-1]}")
|
1089
|
-
|
1090
|
-
def handle_plac(self, record: GedcomRecord):
|
1091
|
-
if isinstance(self.object_map[record.level-1], Agent):
|
1092
|
-
gxobject = Address(value=record.value)
|
1093
|
-
self.object_map[record.level-1].add_address(gxobject)
|
1094
|
-
|
1095
|
-
self.object_stack.append(gxobject)
|
1096
|
-
self.object_map[record.level] = gxobject
|
1097
|
-
elif isinstance(self.object_map[record.level-1], Event):
|
1098
|
-
if self.gedcomx.places.byName(record.value):
|
1099
|
-
self.object_map[record.level-1].place = PlaceReference(original=record.value, description=self.gedcomx.places.byName(record.value)[0])
|
1100
|
-
else:
|
1101
|
-
place_des = PlaceDescription(names=[TextValue(value=record.value)])
|
1102
|
-
self.gedcomx.add_place_description(place_des)
|
1103
|
-
self.object_map[record.level-1].place = PlaceReference(original=record.value, description=place_des)
|
1104
|
-
if len(record.subRecords()) > 0:
|
1105
|
-
self.object_map[record.level]= place_des
|
1106
|
-
|
1107
|
-
elif isinstance(self.object_map[record.level-1], Fact):
|
1108
|
-
if self.gedcomx.places.byName(record.value):
|
1109
|
-
self.object_map[record.level-1].place = PlaceReference(original=record.value, description=self.gedcomx.places.byName(record.value)[0])
|
1110
|
-
else:
|
1111
|
-
place_des = PlaceDescription(names=[TextValue(value=record.value)])
|
1112
|
-
self.gedcomx.add_place_description(place_des)
|
1113
|
-
self.object_map[record.level-1].place = PlaceReference(original=record.value, description=place_des)
|
1114
|
-
elif isinstance(self.object_map[record.level-1], SourceDescription):
|
1115
|
-
gxobject = Note(text='Place: ' + record.value)
|
1116
|
-
self.object_map[record.level-1].add_note(gxobject)
|
1117
|
-
self.object_stack.append(gxobject)
|
1118
|
-
self.object_map[record.level] = gxobject
|
1119
|
-
else:
|
1120
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
1121
|
-
|
1122
|
-
def handle_post(self, record: GedcomRecord):
|
1123
|
-
if isinstance(self.object_map[record.level-1], Address):
|
1124
|
-
self.object_map[record.level-1].postalCode = Translater.clean_str(record.value)
|
1125
|
-
else:
|
1126
|
-
raise ValueError(f"I do not know how to handle an 'POST' tag for a {type(self.object_map[record.level-1])}")
|
1127
|
-
|
1128
|
-
def handle_publ(self, record: GedcomRecord):
|
1129
|
-
if isinstance(self.object_map[record.level-1], SourceDescription):
|
1130
|
-
if record.value and self.gedcomx.agents.byName(record.value):
|
1131
|
-
gxobject = self.gedcomx.agents.byName(record.value)[0]
|
1132
|
-
else:
|
1133
|
-
gxobject = Agent(names=[TextValue(record.value)])
|
1134
|
-
self.gedcomx.add_agent(gxobject)
|
1135
|
-
self.object_map[record.level-1].publisher = gxobject
|
1136
|
-
|
1137
|
-
self.object_stack.append(gxobject)
|
1138
|
-
self.object_map[record.level] = gxobject
|
1139
|
-
else:
|
1140
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
1141
|
-
|
1142
|
-
def handle_prob(self, record: GedcomRecord):
|
1143
|
-
if isinstance(self.object_map[record.level-1], Person):
|
1144
|
-
gxobject = Fact(type=FactType.Probate)
|
1145
|
-
self.object_map[record.level-1].add_fact(gxobject)
|
1146
|
-
|
1147
|
-
self.object_stack.append(gxobject)
|
1148
|
-
self.object_map[record.level] = gxobject
|
1149
|
-
else:
|
1150
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
1151
|
-
|
1152
|
-
def handle_uid(self, record: GedcomRecord):
|
1153
|
-
if isinstance(self.object_map[record.level-1], Agent):
|
1154
|
-
gxobject = Identifier(value=['UID:' + record.value],type=IdentifierType.Primary)
|
1155
|
-
self.object_map[record.level-1].add_identifier(gxobject) #NOTE GC7
|
1156
|
-
self.object_stack.append(gxobject)
|
1157
|
-
self.object_map[record.level] = gxobject
|
1158
|
-
|
1159
|
-
def handle_refn(self, record: GedcomRecord):
|
1160
|
-
if isinstance(self.object_map[record.level-1], Person) or isinstance(self.object_map[record.level-1], SourceDescription):
|
1161
|
-
gxobject = Identifier(value=[URI.from_url('Reference Number:' + record.value)])
|
1162
|
-
self.object_map[record.level-1].add_identifier(gxobject)
|
1163
|
-
self.object_stack.append(gxobject)
|
1164
|
-
self.object_map[record.level] = gxobject
|
1165
|
-
elif isinstance(self.object_map[record.level-1], Agent):
|
1166
|
-
gxobject = Identifier(value=['Reference Number:' + record.value])
|
1167
|
-
self.object_map[record.level-1].add_identifier(gxobject) #NOTE GC7
|
1168
|
-
self.object_stack.append(gxobject)
|
1169
|
-
self.object_map[record.level] = gxobject
|
1170
|
-
else:
|
1171
|
-
raise ValueError(f"Could not handle 'REFN' tag in record {record.describe()}, last stack object {type(self.object_map[record.level-1])}")
|
1172
|
-
|
1173
|
-
def handle_repo(self, record: GedcomRecord):
|
1174
|
-
|
1175
|
-
if record.level == 0:
|
1176
|
-
|
1177
|
-
gxobject = Agent(id=record.xref)
|
1178
|
-
self.gedcomx.add_agent(gxobject)
|
1179
|
-
self.object_stack.append(gxobject)
|
1180
|
-
self.object_map[record.level] = gxobject
|
1181
|
-
|
1182
|
-
elif isinstance(self.object_map[record.level-1], SourceDescription):
|
1183
|
-
if self.gedcomx.agents.byId(record.xref) is not None:
|
1184
|
-
|
1185
|
-
# TODO WHere and what to add this to?
|
1186
|
-
gxobject = self.gedcomx.agents.byId(record.xref)
|
1187
|
-
self.object_map[record.level-1].repository = gxobject
|
1188
|
-
self.object_map[record.level] = gxobject
|
1189
|
-
|
1190
|
-
else:
|
1191
|
-
print(record.describe())
|
1192
|
-
raise ValueError()
|
1193
|
-
gxobject = Agent(names=[TextValue(record.value)])
|
1194
|
-
else:
|
1195
|
-
raise ValueError(f"I do not know how to handle 'REPO' tag that is not a top-level, or sub-tag of {type(self.object_map[record.level-1])}")
|
1196
|
-
|
1197
|
-
|
1198
|
-
self.object_stack.append(gxobject)
|
1199
|
-
self.object_map[record.level] = gxobject
|
1200
|
-
|
1201
|
-
def handle_resi(self, record: GedcomRecord):
|
1202
|
-
if isinstance(self.object_map[record.level-1], Person):
|
1203
|
-
gxobject = Fact(type=FactType.Residence)
|
1204
|
-
if record.value and record.value.strip() != '':
|
1205
|
-
gxobject.add_note(Note(text=record.value))
|
1206
|
-
self.object_map[record.level-1].add_fact(gxobject)
|
1207
|
-
|
1208
|
-
self.object_stack.append(gxobject)
|
1209
|
-
self.object_map[record.level] = gxobject
|
1210
|
-
else:
|
1211
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
1212
|
-
|
1213
|
-
def handle_rin(self, record: GedcomRecord):
|
1214
|
-
if isinstance(self.object_map[record.level-1], SourceDescription):
|
1215
|
-
self.object_map[record.level-1].id = record.value
|
1216
|
-
self.object_map[record.level-1].add_note(Note(text=f"Source had RIN: of {record.value}"))
|
1217
|
-
|
1218
|
-
else:
|
1219
|
-
raise ValueError(f"Could not handle 'RIN' tag in record {record.describe()}, last stack object {type(self.object_map[record.level-1])}")
|
478
|
+
persons = data.get('persons', [])
|
479
|
+
for person in persons:
|
480
|
+
gx.add_person(Serialization.deserialize(person,Person))
|
1220
481
|
|
1221
|
-
|
482
|
+
relationships = data.get('relationships', [])
|
483
|
+
for relationship in relationships:
|
484
|
+
gx.add_relationship(Serialization.deserialize(relationship,Relationship))
|
1222
485
|
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
elif record.value == 'F':
|
1227
|
-
gxobject = Gender(type=GenderType.Female)
|
1228
|
-
else:
|
1229
|
-
gxobject = Gender(type=GenderType.Unknown)
|
1230
|
-
self.object_map[record.level-1].gender = gxobject
|
1231
|
-
|
1232
|
-
self.object_stack.append(gxobject)
|
1233
|
-
self.object_map[record.level] = gxobject
|
1234
|
-
else:
|
1235
|
-
assert False
|
486
|
+
agents = data.get('agents', [])
|
487
|
+
for agent in agents:
|
488
|
+
gx.add_agent(Serialization.deserialize(agent,Agent))
|
1236
489
|
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
self.gedcomx.add_source_description(source_description)
|
1241
|
-
self.object_stack.append(source_description)
|
1242
|
-
self.object_map[record.level] = source_description
|
1243
|
-
else:
|
1244
|
-
# This 'SOUR' is a SourceReference
|
1245
|
-
if record.xref and record.xref.strip() == '':
|
1246
|
-
import_log.warning(f"SOUR points to nothing: {record.describe()}")
|
1247
|
-
return False
|
1248
|
-
if self.gedcomx.source_descriptions.byId(record.xref):
|
1249
|
-
gxobject = SourceReference(descriptionId=record.xref, description=self.gedcomx.source_descriptions.byId(record.xref))
|
1250
|
-
else:
|
1251
|
-
import_log.warning(f'Could not find source with id: {record.xref}')
|
1252
|
-
source_description = SourceDescription(id=record.xref)
|
1253
|
-
gxobject = SourceReference(descriptionId=record.value, description=source_description)
|
1254
|
-
if isinstance(self.object_map[record.level-1],SourceReference):
|
1255
|
-
self.object_map[record.level-1].description.add_source(gxobject)
|
1256
|
-
elif record.parent.tag in ['NOTE']:
|
1257
|
-
pass
|
1258
|
-
else:
|
1259
|
-
self.object_map[record.level-1].add_source(gxobject)
|
1260
|
-
self.object_stack.append(gxobject)
|
1261
|
-
self.object_map[record.level] = gxobject
|
1262
|
-
|
1263
|
-
def handle_stae(self, record: GedcomRecord):
|
1264
|
-
if isinstance(self.object_map[record.level-1], Address):
|
1265
|
-
self.object_map[record.level-1].stateOrProvince = Translater.clean_str(record.value)
|
1266
|
-
else:
|
1267
|
-
raise ValueError(f"I do not know how to handle an 'STAE' tag for a {type(self.object_map[record.level-1])}")
|
490
|
+
events = data.get('events', [])
|
491
|
+
for event in events:
|
492
|
+
gx.add_event(Serialization.deserialize(event,Event))
|
1268
493
|
|
1269
|
-
|
1270
|
-
if isinstance(self.object_map[record.level-1], Name):
|
1271
|
-
surname = NamePart(value=record.value, type=NamePartType.Surname)
|
1272
|
-
self.object_map[record.level-1]._add_name_part(surname)
|
1273
|
-
else:
|
1274
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
1275
|
-
|
1276
|
-
def handle_text(self, record: GedcomRecord):
|
1277
|
-
if record.parent.tag == 'DATA':
|
1278
|
-
if isinstance(self.object_map[record.level-2], SourceReference):
|
1279
|
-
gxobject = TextValue(value=record.value)
|
1280
|
-
self.object_map[record.level-2].description.add_description(gxobject)
|
1281
|
-
self.object_stack.append(gxobject)
|
1282
|
-
self.object_map[record.level] = gxobject
|
1283
|
-
elif isinstance(self.object_map[record.level-1], SourceDescription):
|
1284
|
-
gxobject = Document(text=record.value)
|
1285
|
-
self.object_map[record.level-1].analysis = gxobject
|
1286
|
-
else:
|
1287
|
-
assert False
|
1288
|
-
|
1289
|
-
def handle_titl(self, record: GedcomRecord):
|
1290
|
-
if isinstance(self.object_map[record.level-1], SourceDescription):
|
1291
|
-
|
1292
|
-
gxobject = TextValue(value=Translater.clean_str(record.value))
|
1293
|
-
self.object_map[record.level-1].add_title(gxobject)
|
1294
|
-
|
1295
|
-
self.object_stack.append(gxobject)
|
1296
|
-
self.object_map[record.level] = gxobject
|
494
|
+
return gx
|
1297
495
|
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
self.object_map[record.level] = gxobject
|
1304
|
-
elif self.object_map[record.level] and isinstance(self.object_map[record.level], Name):
|
1305
|
-
gxobject = NamePart(value=record.value, qualifiers=[NamePartQualifier.Title])
|
1306
|
-
|
1307
|
-
self.object_map[record.level]._add_name_part(gxobject)
|
1308
|
-
else:
|
1309
|
-
raise TagConversionError(record=record,levelstack=self.object_map)
|
1310
|
-
|
1311
|
-
def handle_tran(self, record: GedcomRecord):
|
1312
|
-
pass
|
1313
|
-
|
1314
|
-
def handle_type(self, record: GedcomRecord):
|
1315
|
-
# peek to see if event or fact
|
1316
|
-
if isinstance(self.object_map[record.level-1], Event):
|
1317
|
-
if EventType.guess(record.value):
|
1318
|
-
self.object_map[record.level-1].type = EventType.guess(record.value)
|
1319
|
-
else:
|
1320
|
-
self.object_map[record.level-1].type = None
|
1321
|
-
self.object_map[record.level-1].add_note(Note(text=Translater.clean_str(record.value)))
|
1322
|
-
elif isinstance(self.object_map[record.level-1], Fact):
|
1323
|
-
if not self.object_map[record.level-1].type:
|
1324
|
-
self.object_map[0].type = FactType.guess(record.value)
|
1325
|
-
elif isinstance(self.object_map[record.level-1], Identifier):
|
1326
|
-
|
1327
|
-
self.object_map[record.level-1].values.append(Translater.clean_str(record.value))
|
1328
|
-
self.object_map[record.level-1].type = IdentifierType.Other
|
1329
|
-
|
1330
|
-
elif record.parent.tag == 'FORM':
|
1331
|
-
if not self.object_map[0].mediaType:
|
1332
|
-
self.object_map[0].mediaType = record.value
|
1333
|
-
|
1334
|
-
else:
|
1335
|
-
raise ValueError(f"I do not know how to handle 'TYPE' tag for {type(self.object_map[record.level-1])}")
|
1336
|
-
|
1337
|
-
def handle__url(self, record: GedcomRecord):
|
1338
|
-
if isinstance(self.object_map[record.level-2], SourceDescription):
|
1339
|
-
self.object_map[record.level-2].about = URI.from_url(record.value)
|
1340
|
-
else:
|
1341
|
-
raise ValueError(f"Could not handle '_URL' tag in record {record.describe()}, last stack object {self.object_map[record.level-1]}")
|
1342
|
-
|
1343
|
-
def handle_www(self, record: GedcomRecord):
|
1344
|
-
if isinstance(self.object_map[record.level-1], Agent):
|
1345
|
-
self.object_map[record.level-1].homepage = Translater.clean_str(record.value)
|
1346
|
-
elif isinstance(self.object_map[record.level-2], SourceReference):
|
1347
|
-
self.object_map[record.level-2].description.add_identifier(Identifier(value=URI.from_url(record.value)))
|
1348
|
-
else:
|
1349
|
-
raise ValueError(f"Could not handle 'WWW' tag in record {record.describe()}, last stack object {self.object_map[record.level-1]}")
|
1350
|
-
|
496
|
+
@staticmethod
|
497
|
+
def make_id(length: int = 12) -> str:
|
498
|
+
"""Generate a random alphanumeric ID of given length."""
|
499
|
+
alphabet = string.ascii_letters + string.digits
|
500
|
+
return ''.join(random.choices(alphabet, k=length))
|