gedcom-x 0.5.1__py3-none-any.whl → 0.5.5__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.1.dist-info → gedcom_x-0.5.5.dist-info}/METADATA +1 -1
- gedcom_x-0.5.5.dist-info/RECORD +43 -0
- gedcomx/Address.py +42 -11
- gedcomx/Agent.py +136 -23
- gedcomx/Attribution.py +39 -91
- gedcomx/Conclusion.py +132 -53
- gedcomx/Coverage.py +10 -0
- gedcomx/Date.py +47 -11
- gedcomx/Document.py +43 -12
- gedcomx/Event.py +24 -5
- gedcomx/EvidenceReference.py +2 -2
- gedcomx/Exceptions.py +16 -0
- gedcomx/Fact.py +73 -50
- gedcomx/Gedcom.py +40 -333
- gedcomx/Gedcom5x.py +558 -0
- gedcomx/GedcomX.py +439 -194
- gedcomx/Gender.py +27 -8
- gedcomx/Group.py +3 -3
- gedcomx/Identifier.py +192 -55
- gedcomx/Logging.py +19 -0
- gedcomx/Mutations.py +228 -0
- gedcomx/Name.py +73 -38
- gedcomx/Note.py +5 -4
- gedcomx/OnlineAccount.py +2 -2
- gedcomx/Person.py +106 -92
- gedcomx/PlaceDescription.py +39 -16
- gedcomx/PlaceReference.py +14 -15
- gedcomx/Relationship.py +35 -56
- gedcomx/Resource.py +75 -0
- gedcomx/Serialization.py +394 -30
- gedcomx/SourceCitation.py +6 -1
- gedcomx/SourceDescription.py +89 -75
- gedcomx/SourceReference.py +33 -88
- gedcomx/Subject.py +12 -10
- gedcomx/TextValue.py +2 -1
- gedcomx/Translation.py +219 -0
- gedcomx/URI.py +96 -61
- gedcomx/Zip.py +1 -0
- gedcomx/__init__.py +11 -3
- gedcom_x-0.5.1.dist-info/RECORD +0 -37
- gedcomx/_Resource.py +0 -11
- {gedcom_x-0.5.1.dist-info → gedcom_x-0.5.5.dist-info}/WHEEL +0 -0
- {gedcom_x-0.5.1.dist-info → gedcom_x-0.5.5.dist-info}/top_level.txt +0 -0
gedcomx/GedcomX.py
CHANGED
@@ -13,16 +13,18 @@ from .Agent import Agent
|
|
13
13
|
from .Attribution import Attribution
|
14
14
|
from .Conclusion import Conclusion
|
15
15
|
from .Coverage import Coverage
|
16
|
-
from .Date import Date
|
16
|
+
from .Date import Date, date_to_timestamp
|
17
17
|
from .Document import Document
|
18
18
|
from .EvidenceReference import EvidenceReference
|
19
|
+
from .Exceptions import TagConversionError
|
19
20
|
from .Event import Event,EventType,EventRole,EventRoleType
|
20
21
|
from .Fact import Fact, FactType, FactQualifier
|
21
22
|
from .Gedcom import Gedcom
|
22
|
-
from .
|
23
|
+
from .Gedcom5x import GedcomRecord
|
23
24
|
from .Gender import Gender, GenderType
|
24
25
|
from .Group import Group
|
25
|
-
from .Identifier import Identifier, IdentifierType
|
26
|
+
from .Identifier import Identifier, IdentifierType, make_uid, IdentifierList
|
27
|
+
from .Logging import get_logger
|
26
28
|
from .Name import Name, NameType, NameForm, NamePart, NamePartType, NamePartQualifier
|
27
29
|
from .Note import Note
|
28
30
|
from .OnlineAccount import OnlineAccount
|
@@ -37,7 +39,10 @@ from .SourceReference import SourceReference, KnownSourceReference
|
|
37
39
|
from .Subject import Subject
|
38
40
|
from .TextValue import TextValue
|
39
41
|
from .TopLevelTypeCollection import TopLevelTypeCollection
|
40
|
-
from .
|
42
|
+
from .Resource import Resource, URI
|
43
|
+
|
44
|
+
import_log = get_logger('import')
|
45
|
+
convert_log = get_logger('conversion')
|
41
46
|
|
42
47
|
def TypeCollection(item_type):
|
43
48
|
class Collection:
|
@@ -108,8 +113,10 @@ def TypeCollection(item_type):
|
|
108
113
|
|
109
114
|
def byName(self, sname: str):
|
110
115
|
# Use the name index for fast lookup
|
111
|
-
|
112
|
-
|
116
|
+
if sname:
|
117
|
+
sname = sname.strip()
|
118
|
+
return self._name_index.get(sname, [])
|
119
|
+
return None
|
113
120
|
|
114
121
|
def byId(self, id):
|
115
122
|
# Use the id index for fast lookup
|
@@ -122,7 +129,12 @@ def TypeCollection(item_type):
|
|
122
129
|
def append(self, item):
|
123
130
|
if not isinstance(item, item_type):
|
124
131
|
raise TypeError(f"Expected item of type {item_type.__name__}, got {type(item).__name__}")
|
125
|
-
|
132
|
+
if item.uri:
|
133
|
+
item.uri.path = f'{str(item_type.__name__)}s' if (item.uri.path is None or item.uri.path == "") else item.uri.path
|
134
|
+
else:
|
135
|
+
item.uri = URI(path=f'/{item_type.__name__}s/')
|
136
|
+
|
137
|
+
|
126
138
|
#if isinstance(item,Agent):
|
127
139
|
# item._uri._path = 'Agents'
|
128
140
|
# print(item._uri._as_dict_)
|
@@ -163,30 +175,52 @@ def TypeCollection(item_type):
|
|
163
175
|
|
164
176
|
@property
|
165
177
|
def _items_as_dict(self) -> dict:
|
166
|
-
|
167
|
-
|
168
|
-
#return {f'{str(item_type.__name__)}s': [item._as_dict_ for item in self._items]}
|
169
|
-
return {f'{str(item_type.__name__)}s': [item._as_dict_ for item in self._items]}
|
170
|
-
|
171
|
-
@property
|
172
|
-
def json(self):
|
173
|
-
return json.dumps(self._as_dict, indent=4)
|
178
|
+
return {f'{str(item_type.__name__)}s': [item._as_dict_ for item in self._items]}
|
174
179
|
|
175
180
|
@property
|
176
181
|
def _as_dict_(self):
|
177
|
-
return {
|
182
|
+
return {f'{str(item_type.__name__).lower()}s': [item._as_dict_ for item in self._items]}
|
183
|
+
|
184
|
+
@property
|
185
|
+
def json(self) -> str:
|
186
|
+
|
187
|
+
return json.dumps(self._as_dict_, indent=4)
|
178
188
|
|
179
189
|
return Collection()
|
180
190
|
|
181
191
|
class GedcomX:
|
192
|
+
"""
|
193
|
+
Main GedcomX Object representing a Genealogy. Stores collections of Top Level Gedcom-X Types.
|
194
|
+
complies with GEDCOM X Conceptual Model V1 (http://gedcomx.org/conceptual-model/v1)
|
195
|
+
|
196
|
+
Parameters
|
197
|
+
----------
|
198
|
+
id : str
|
199
|
+
Unique identifier for this Genealogy.
|
200
|
+
attribution : Attribution Object
|
201
|
+
Attribution information for the Genealogy
|
202
|
+
filepath : str
|
203
|
+
Not Implimented.
|
204
|
+
description : str
|
205
|
+
Description of the Genealogy: ex. 'My Family Tree'
|
206
|
+
|
207
|
+
Raises
|
208
|
+
------
|
209
|
+
ValueError
|
210
|
+
If `id` is not a valid UUID.
|
211
|
+
"""
|
182
212
|
version = 'http://gedcomx.org/conceptual-model/v1'
|
183
213
|
|
184
|
-
def __init__(self, id: str = None,
|
214
|
+
def __init__(self, id: Optional[str] = None,
|
215
|
+
attribution: Optional[Attribution] = None,
|
216
|
+
filepath: Optional[str] = None,
|
217
|
+
description: Optional[str] = None) -> None:
|
218
|
+
|
185
219
|
self.id = id
|
186
220
|
self.attribution = attribution
|
187
|
-
|
188
221
|
self._filepath = None
|
189
222
|
|
223
|
+
self.description = description
|
190
224
|
self.source_descriptions = TypeCollection(SourceDescription)
|
191
225
|
self.persons = TypeCollection(Person)
|
192
226
|
self.relationships = TypeCollection(Relationship)
|
@@ -196,10 +230,11 @@ class GedcomX:
|
|
196
230
|
self.places = TypeCollection(PlaceDescription)
|
197
231
|
self.groups = TypeCollection(Group)
|
198
232
|
|
199
|
-
self.
|
233
|
+
self.relationship_table = {}
|
234
|
+
|
235
|
+
self.default_id_generator = make_uid
|
200
236
|
|
201
|
-
def
|
202
|
-
#print(type(gedcomx_type_object))
|
237
|
+
def add(self,gedcomx_type_object):
|
203
238
|
if gedcomx_type_object:
|
204
239
|
if isinstance(gedcomx_type_object,Person):
|
205
240
|
self.add_person(gedcomx_type_object)
|
@@ -228,16 +263,27 @@ class GedcomX:
|
|
228
263
|
raise ValueError(f"When adding a SourceDescription, value must be of type SourceDescription, type {type(sourceDescription)} was provided")
|
229
264
|
|
230
265
|
def add_person(self,person: Person):
|
266
|
+
"""Add a Person object to the Genealogy
|
267
|
+
|
268
|
+
Args:
|
269
|
+
person: Person Object
|
270
|
+
|
271
|
+
Returns:
|
272
|
+
None
|
273
|
+
|
274
|
+
Raises:
|
275
|
+
ValueError: If `person` is not of type Person.
|
276
|
+
"""
|
231
277
|
if person and isinstance(person,Person):
|
232
278
|
if person.id is None:
|
233
279
|
person.id =self.personURIgenerator()
|
234
280
|
self.persons.append(item=person)
|
235
281
|
else:
|
236
|
-
raise ValueError()
|
282
|
+
raise ValueError(f'person must be a Person Object not type: {type(person)}')
|
237
283
|
|
238
284
|
def add_relationship(self,relationship: Relationship):
|
239
285
|
if relationship and isinstance(relationship,Relationship):
|
240
|
-
if isinstance(relationship.person1,
|
286
|
+
if isinstance(relationship.person1,Resource) and isinstance(relationship.person2,Resource):
|
241
287
|
print("Adding unresolved Relationship")
|
242
288
|
self.relationships.append(relationship)
|
243
289
|
return
|
@@ -247,24 +293,24 @@ class GedcomX:
|
|
247
293
|
relationship.person1.id = self.personURIgenerator()
|
248
294
|
if not self.persons.byId(relationship.person1.id):
|
249
295
|
self.persons.append(relationship.person1)
|
250
|
-
if relationship.person1.id not in self.
|
251
|
-
self.
|
252
|
-
self.
|
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)
|
253
299
|
relationship.person1._add_relationship(relationship)
|
254
300
|
else:
|
255
|
-
|
301
|
+
pass
|
256
302
|
|
257
303
|
if relationship.person2:
|
258
304
|
if relationship.person2.id is None:
|
259
305
|
relationship.person2.id = self.personURIgenerator() #TODO
|
260
306
|
if not self.persons.byId(relationship.person2.id):
|
261
307
|
self.persons.append(relationship.person2)
|
262
|
-
if relationship.person2.id not in self.
|
263
|
-
self.
|
264
|
-
self.
|
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)
|
265
311
|
relationship.person2._add_relationship(relationship)
|
266
312
|
else:
|
267
|
-
|
313
|
+
pass
|
268
314
|
|
269
315
|
self.relationships.append(relationship)
|
270
316
|
else:
|
@@ -273,13 +319,25 @@ class GedcomX:
|
|
273
319
|
def add_place_description(self,placeDescription: PlaceDescription):
|
274
320
|
if placeDescription and isinstance(placeDescription,PlaceDescription):
|
275
321
|
if placeDescription.id is None:
|
276
|
-
|
322
|
+
Warning("PlaceDescription has no id")
|
277
323
|
self.places.append(placeDescription)
|
278
324
|
|
279
325
|
def add_agent(self,agent: Agent):
|
326
|
+
"""Add a Agent object to the Genealogy
|
327
|
+
|
328
|
+
Args:
|
329
|
+
agent: Agent Object
|
330
|
+
|
331
|
+
Returns:
|
332
|
+
None
|
333
|
+
|
334
|
+
Raises:
|
335
|
+
ValueError: If `agent` is not of type Agent.
|
336
|
+
"""
|
280
337
|
if agent and isinstance(agent,Agent):
|
338
|
+
if agent in self.agents:
|
339
|
+
return
|
281
340
|
if agent.id is None:
|
282
|
-
raise("Empty ID")
|
283
341
|
agent.id = Agent.default_id_generator()
|
284
342
|
if self.agents.byId(agent.id):
|
285
343
|
raise ValueError
|
@@ -293,7 +351,7 @@ class GedcomX:
|
|
293
351
|
return
|
294
352
|
self.events.append(event_to_add)
|
295
353
|
|
296
|
-
def
|
354
|
+
def get_person_by_id(self,id: str):
|
297
355
|
filtered = [person for person in self.persons if getattr(person, 'id') == id]
|
298
356
|
if filtered: return filtered[0]
|
299
357
|
return None
|
@@ -303,11 +361,28 @@ class GedcomX:
|
|
303
361
|
if filtered: return filtered[0]
|
304
362
|
return None
|
305
363
|
|
364
|
+
def json(self):
|
365
|
+
"""
|
366
|
+
JSON Representation of the GedcomX Genealogy.
|
367
|
+
|
368
|
+
Returns:
|
369
|
+
str: JSON Representation of the GedcomX Genealogy in the GEDCOM X JSON Serialization Format
|
370
|
+
"""
|
371
|
+
gedcomx_json = {
|
372
|
+
'persons': [person._as_dict_ for person in self.persons],
|
373
|
+
'sourceDescriptions' : [sourceDescription._as_dict_ for sourceDescription in self.source_descriptions],
|
374
|
+
'relationships': [relationship._as_dict_ for relationship in self.relationships],
|
375
|
+
'agents': [agent._as_dict_ for agent in self.agents],
|
376
|
+
'events': [event._as_dict_ for event in self.events],
|
377
|
+
'places': [place._as_dict_ for place in self.places],
|
378
|
+
'documents': [document._as_dict_ for document in self.documents],
|
379
|
+
}
|
380
|
+
return json.dumps(gedcomx_json, indent=4)
|
306
381
|
|
307
382
|
class Translater():
|
308
|
-
def __init__(self,gedcom) -> None:
|
383
|
+
def __init__(self,gedcom: Gedcom) -> None:
|
309
384
|
self.handlers = {}
|
310
|
-
self.gedcom: Gedcom = gedcom
|
385
|
+
self.gedcom: Gedcom = gedcom
|
311
386
|
self.gedcomx = GedcomX()
|
312
387
|
|
313
388
|
self.object_stack = []
|
@@ -316,6 +391,7 @@ class Translater():
|
|
316
391
|
|
317
392
|
self.translate()
|
318
393
|
|
394
|
+
|
319
395
|
gedcom_even_to_fact = {
|
320
396
|
# Person Fact Types
|
321
397
|
"ADOP": FactType.Adoption,
|
@@ -367,15 +443,55 @@ class Translater():
|
|
367
443
|
"ADOP": FactType.AdoptiveParent
|
368
444
|
}
|
369
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
|
+
}
|
370
482
|
|
483
|
+
@staticmethod
|
371
484
|
def clean_str(text: str) -> str:
|
372
485
|
# Regular expression to match HTML/XML tags
|
486
|
+
if text is None or text.strip() == '':
|
487
|
+
return None
|
373
488
|
clean_text = re.sub(r'<[^>]+>', '', text)
|
374
489
|
|
375
490
|
return clean_text
|
376
491
|
|
377
492
|
def translate(self):
|
378
|
-
for repository in self.gedcom.repositories:
|
493
|
+
for n, repository in enumerate(self.gedcom.repositories):
|
494
|
+
print(f"Parsing Repository {n}")
|
379
495
|
self.parse_record(repository)
|
380
496
|
print(f"Translated {len(self.gedcomx.agents)} 'REPO' records to Agents")
|
381
497
|
for source in self.gedcom.sources:
|
@@ -402,7 +518,7 @@ class Translater():
|
|
402
518
|
|
403
519
|
print(f"Translated {len(self.gedcomx.events)} 'EVEN' records to Events")
|
404
520
|
|
405
|
-
def find_urls(
|
521
|
+
def find_urls(self,text: str):
|
406
522
|
# Regular expression pattern to match URLs
|
407
523
|
url_pattern = re.compile(r'https?://[^\s]+')
|
408
524
|
# Find all URLs using the pattern
|
@@ -411,37 +527,36 @@ class Translater():
|
|
411
527
|
|
412
528
|
@property
|
413
529
|
def event_type_conversion_table(self):
|
414
|
-
return {'BIRT':EventType.
|
415
|
-
'OBIT':FactType.
|
530
|
+
return {'BIRT':EventType.Birth,
|
531
|
+
'OBIT':FactType.Obituary}
|
416
532
|
|
417
533
|
def parse_record(self,record: GedcomRecord):
|
418
|
-
|
419
|
-
if DEBUG: print(record.describe())
|
534
|
+
|
420
535
|
handler_name = 'handle_' + record.tag.lower()
|
421
536
|
|
422
|
-
if hasattr(self,handler_name):
|
423
|
-
|
424
|
-
handler = getattr(self,handler_name)
|
537
|
+
if hasattr(self,handler_name):
|
538
|
+
convert_log.info(f'Parsing Record: {record.describe()}')
|
539
|
+
handler = getattr(self,handler_name)
|
425
540
|
handler(record)
|
426
541
|
else:
|
427
542
|
if record.tag in self.missing_handler_count:
|
428
543
|
self.missing_handler_count[record.tag] += 1
|
429
544
|
else:
|
430
545
|
self.missing_handler_count[record.tag] = 1
|
431
|
-
|
432
|
-
|
546
|
+
|
547
|
+
convert_log.error(f'Failed Parsing Record: {record.describe()}')
|
433
548
|
for sub_record in record.subRecords():
|
434
549
|
self.parse_record(sub_record)
|
435
|
-
|
436
|
-
def handle__apid(self, record):
|
550
|
+
|
551
|
+
def handle__apid(self, record: GedcomRecord):
|
437
552
|
if isinstance(self.object_map[record.level-1], SourceReference):
|
438
|
-
self.object_map[record.level-1].
|
553
|
+
self.object_map[record.level-1].description.add_identifier(Identifier(value=URI.from_url('APID://' + record.value)))
|
439
554
|
elif isinstance(self.object_map[record.level-1], SourceDescription):
|
440
555
|
self.object_map[record.level-1].add_identifier(Identifier(value=URI.from_url('APID://' + record.value)))
|
441
556
|
else:
|
442
557
|
raise ValueError(f"Could not handle '_APID' tag in record {record.describe()}, last stack object {type(self.object_map[record.level-1])}")
|
443
558
|
|
444
|
-
def handle__meta(self, record):
|
559
|
+
def handle__meta(self, record: GedcomRecord):
|
445
560
|
if isinstance(self.object_map[record.level-1], SourceDescription):
|
446
561
|
gxobject = Note(text=Translater.clean_str(record.value))
|
447
562
|
self.object_map[record.level-1].add_note(gxobject)
|
@@ -450,14 +565,14 @@ class Translater():
|
|
450
565
|
else:
|
451
566
|
raise ValueError(f"Could not handle 'WWW' tag in record {record.describe()}, last stack object {self.object_map[record.level-1]}")
|
452
567
|
|
453
|
-
def handle__wlnk(self, record):
|
568
|
+
def handle__wlnk(self, record: GedcomRecord):
|
454
569
|
return self.handle_sour(record)
|
455
570
|
|
456
|
-
def handle_addr(self, record):
|
571
|
+
def handle_addr(self, record: GedcomRecord):
|
457
572
|
if isinstance(self.object_map[record.level-1], Agent):
|
458
573
|
# TODO CHeck if URL?
|
459
574
|
if Translater.clean_str(record.value):
|
460
|
-
gxobject =
|
575
|
+
gxobject = Address(value=Translater.clean_str(record.value))
|
461
576
|
else:
|
462
577
|
gxobject = Address()
|
463
578
|
self.object_map[record.level-1].address = gxobject
|
@@ -466,26 +581,80 @@ class Translater():
|
|
466
581
|
else:
|
467
582
|
raise ValueError(f"I do not know how to handle an 'ADDR' tag for a {type(self.object_map[record.level-1])}")
|
468
583
|
|
469
|
-
def handle_adr1(self, record):
|
584
|
+
def handle_adr1(self, record: GedcomRecord):
|
470
585
|
if isinstance(self.object_map[record.level-1], Address):
|
471
586
|
if Translater.clean_str(record.value):
|
472
|
-
self.object_map[record.level-1].street = Translater.clean_str(record.value)
|
473
|
-
|
587
|
+
self.object_map[record.level-1].street = Translater.clean_str(record.value)
|
474
588
|
else:
|
475
|
-
raise ValueError(f"I do not know how to handle an '
|
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])}")
|
476
646
|
|
477
|
-
def handle_adop(self, record):
|
647
|
+
def handle_adop(self, record: GedcomRecord):
|
478
648
|
if isinstance(self.object_map[record.level-1], Person):
|
479
|
-
gxobject = Fact(type=FactType.
|
649
|
+
gxobject = Fact(type=FactType.Adoption)
|
480
650
|
self.object_map[record.level-1].add_fact(gxobject)
|
481
651
|
|
482
652
|
self.object_stack.append(gxobject)
|
483
653
|
self.object_map[record.level] = gxobject
|
484
654
|
else:
|
485
|
-
|
486
|
-
assert False
|
655
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
487
656
|
|
488
|
-
def handle_auth(self, record):
|
657
|
+
def handle_auth(self, record: GedcomRecord):
|
489
658
|
if isinstance(self.object_map[record.level-1], SourceDescription):
|
490
659
|
if self.gedcomx.agents.byName(record.value):
|
491
660
|
gxobject = self.gedcomx.agents.byName(record.value)[0]
|
@@ -497,10 +666,9 @@ class Translater():
|
|
497
666
|
self.object_stack.append(gxobject)
|
498
667
|
self.object_map[record.level] = gxobject
|
499
668
|
else:
|
500
|
-
|
501
|
-
assert False
|
669
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
502
670
|
|
503
|
-
def handle_bapm(self, record):
|
671
|
+
def handle_bapm(self, record: GedcomRecord):
|
504
672
|
if isinstance(self.object_map[record.level-1], Person):
|
505
673
|
gxobject = Fact(type=FactType.Baptism)
|
506
674
|
self.object_map[record.level-1].add_fact(gxobject)
|
@@ -508,10 +676,9 @@ class Translater():
|
|
508
676
|
self.object_stack.append(gxobject)
|
509
677
|
self.object_map[record.level] = gxobject
|
510
678
|
else:
|
511
|
-
|
512
|
-
assert False
|
679
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
513
680
|
|
514
|
-
def handle_birt(self, record):
|
681
|
+
def handle_birt(self, record: GedcomRecord):
|
515
682
|
if isinstance(self.object_map[record.level-1], Person):
|
516
683
|
#gxobject = Event(type=EventType.BIRTH, roles=[EventRole(person=self.object_map[record.level-1], type=EventRoleType.Principal)])
|
517
684
|
gxobject = Fact(type=FactType.Birth)
|
@@ -521,10 +688,9 @@ class Translater():
|
|
521
688
|
self.object_stack.append(gxobject)
|
522
689
|
self.object_map[record.level] = gxobject
|
523
690
|
else:
|
524
|
-
|
525
|
-
assert False
|
691
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
526
692
|
|
527
|
-
def handle_buri(self, record):
|
693
|
+
def handle_buri(self, record: GedcomRecord):
|
528
694
|
if isinstance(self.object_map[record.level-1], Person):
|
529
695
|
gxobject = Fact(type=FactType.Burial)
|
530
696
|
self.object_map[record.level-1].add_fact(gxobject)
|
@@ -532,10 +698,9 @@ class Translater():
|
|
532
698
|
self.object_stack.append(gxobject)
|
533
699
|
self.object_map[record.level] = gxobject
|
534
700
|
else:
|
535
|
-
|
536
|
-
assert False
|
701
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
537
702
|
|
538
|
-
def handle_caln(self, record):
|
703
|
+
def handle_caln(self, record: GedcomRecord):
|
539
704
|
if isinstance(self.object_map[record.level-1], SourceReference):
|
540
705
|
self.object_map[record.level-1].description.add_identifier(Identifier(value=URI.from_url('Call Number:' + record.value)))
|
541
706
|
elif isinstance(self.object_map[record.level-1], SourceDescription):
|
@@ -546,7 +711,19 @@ class Translater():
|
|
546
711
|
else:
|
547
712
|
raise ValueError(f"Could not handle 'CALN' tag in record {record.describe()}, last stack object {type(self.object_map[record.level-1])}")
|
548
713
|
|
549
|
-
def
|
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):
|
550
727
|
if isinstance(self.object_map[record.level-1], Person):
|
551
728
|
gxobject = Fact(type=FactType.Christening)
|
552
729
|
self.object_map[record.level-1].add_fact(gxobject)
|
@@ -554,16 +731,15 @@ class Translater():
|
|
554
731
|
self.object_stack.append(gxobject)
|
555
732
|
self.object_map[record.level] = gxobject
|
556
733
|
else:
|
557
|
-
|
558
|
-
assert False
|
734
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
559
735
|
|
560
|
-
def handle_city(self, record):
|
736
|
+
def handle_city(self, record: GedcomRecord):
|
561
737
|
if isinstance(self.object_map[record.level-1], Address):
|
562
738
|
self.object_map[record.level-1].city = Translater.clean_str(record.value)
|
563
739
|
else:
|
564
740
|
raise ValueError(f"I do not know how to handle an 'CITY' tag for a {type(self.object_map[record.level-1])}")
|
565
741
|
|
566
|
-
def handle_conc(self, record):
|
742
|
+
def handle_conc(self, record: GedcomRecord):
|
567
743
|
if isinstance(self.object_map[record.level-1], Note):
|
568
744
|
gxobject = Translater.clean_str(str(record.value))
|
569
745
|
self.object_map[record.level-1].append(gxobject)
|
@@ -582,69 +758,85 @@ class Translater():
|
|
582
758
|
self.object_map[record.level-1].notes[0].text += record.value
|
583
759
|
|
584
760
|
else:
|
585
|
-
|
586
|
-
assert False
|
761
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
587
762
|
|
588
|
-
def handle_cont(self, record):
|
763
|
+
def handle_cont(self, record: GedcomRecord):
|
589
764
|
if isinstance(self.object_map[record.level-1], Note):
|
590
|
-
gxobject = str("\n" + record.value)
|
765
|
+
gxobject = str("\n" + record.value if record.value else '')
|
591
766
|
self.object_map[record.level-1].append(gxobject)
|
592
767
|
elif isinstance(self.object_map[record.level-1], Agent):
|
593
|
-
gxobject = str("\n" + record.value)
|
768
|
+
gxobject = str("\n" + record.value if record.value else '')
|
594
769
|
elif isinstance(self.object_map[record.level-1], Qualifier):
|
595
|
-
gxobject = str("\n" + record.value)
|
770
|
+
gxobject = str("\n" + record.value if record.value else '')
|
596
771
|
self.object_map[record.level-1].append(gxobject)
|
597
772
|
elif isinstance(self.object_map[record.level-1], TextValue):
|
598
773
|
#gxobject = TextValue(value="\n" + record.value)
|
599
|
-
self.object_map[record.level-1]._append_to_value(record.value)
|
774
|
+
self.object_map[record.level-1]._append_to_value(record.value if record.value else '\n')
|
600
775
|
elif isinstance(self.object_map[record.level-1], SourceReference):
|
601
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)
|
602
779
|
else:
|
603
|
-
|
604
|
-
assert False
|
780
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
605
781
|
|
606
|
-
def
|
782
|
+
def handle_crea(self, record: GedcomRecord):
|
607
783
|
if isinstance(self.object_map[record.level-1], SourceDescription):
|
608
|
-
self.object_map[record.level-1].created = Date(original=record.
|
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}")
|
609
794
|
else:
|
610
|
-
raise ValueError(f"Could not handle '
|
795
|
+
raise ValueError(f"Could not handle '{record.tag}' tag in record {record.describe()}, last stack object {self.object_map[record.level-1]}")
|
611
796
|
|
612
|
-
def handle_ctry(self, record):
|
797
|
+
def handle_ctry(self, record: GedcomRecord):
|
613
798
|
if isinstance(self.object_map[record.level-1], Address):
|
614
799
|
self.object_map[record.level-1].country = Translater.clean_str(record.value)
|
615
800
|
else:
|
616
|
-
raise ValueError(f"I do not know how to handle an '
|
801
|
+
raise ValueError(f"I do not know how to handle an '{record.tag}' tag for a {type(self.object_map[record.level-1])}")
|
617
802
|
|
618
803
|
def handle_data(self, record: GedcomRecord) -> None:
|
619
|
-
if record.value != '':
|
804
|
+
if record.value != '' and record.value == 'None':
|
620
805
|
assert False
|
621
|
-
self.object_map[record.level] =
|
806
|
+
self.object_map[record.level] = self.object_map[record.level-1]
|
622
807
|
|
623
808
|
def handle_date(self, record: GedcomRecord):
|
624
809
|
if record.parent.tag == 'PUBL':
|
625
|
-
gxobject = Date(original=record.value)
|
626
|
-
self.object_map[0].published = gxobject
|
627
|
-
|
628
|
-
self.
|
629
|
-
self.
|
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
|
630
816
|
elif isinstance(self.object_map[record.level-1], Event):
|
631
817
|
self.object_map[record.level-1].date = Date(original=record.value)
|
632
818
|
elif isinstance(self.object_map[record.level-1], Fact):
|
633
819
|
self.object_map[record.level-1].date = Date(original=record.value)
|
634
820
|
elif record.parent.tag == 'DATA' and isinstance(self.object_map[record.level-2], SourceReference):
|
635
821
|
gxobject = Note(text='Date: ' + record.value)
|
636
|
-
self.object_map[record.level-2].
|
822
|
+
self.object_map[record.level-2].description.add_note(gxobject)
|
637
823
|
self.object_stack.append(gxobject)
|
638
824
|
self.object_map[record.level] = gxobject
|
639
825
|
elif isinstance(self.object_map[record.level-1], SourceDescription):
|
640
826
|
|
641
827
|
self.object_map[record.level-1].ctreated = record.value #TODO String to timestamp
|
642
|
-
|
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
|
+
|
643
836
|
else:
|
644
|
-
|
645
|
-
assert False
|
837
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
646
838
|
|
647
|
-
def handle_deat(self, record):
|
839
|
+
def handle_deat(self, record: GedcomRecord):
|
648
840
|
if isinstance(self.object_map[record.level-1], Person):
|
649
841
|
gxobject = Fact(type=FactType.Death)
|
650
842
|
self.object_map[record.level-1].add_fact(gxobject)
|
@@ -652,12 +844,11 @@ class Translater():
|
|
652
844
|
self.object_stack.append(gxobject)
|
653
845
|
self.object_map[record.level] = gxobject
|
654
846
|
else:
|
655
|
-
|
656
|
-
assert False
|
847
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
657
848
|
|
658
849
|
def handle_even(self, record: GedcomRecord):
|
659
850
|
# TODO If events in a @S, check if only 1 person matches?
|
660
|
-
if not record.value.strip() == '':
|
851
|
+
if record.value and (not record.value.strip() == ''):
|
661
852
|
values = [value.strip() for value in record.value.split(",")]
|
662
853
|
for value in values:
|
663
854
|
if value in Translater.gedcom_even_to_fact.keys():
|
@@ -667,18 +858,23 @@ class Translater():
|
|
667
858
|
|
668
859
|
self.object_stack.append(gxobject)
|
669
860
|
self.object_map[record.level] = gxobject
|
670
|
-
|
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
|
671
867
|
else:
|
672
|
-
|
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)
|
673
871
|
assert False
|
674
872
|
# TODO: Fix, this. making an event to cacth subtags, why are these fact tied to a source? GEDCOM is horrible
|
675
873
|
gxobject = Event(type=EventType.UNKNOWN)
|
676
874
|
self.object_stack.append(gxobject)
|
677
875
|
self.object_map[record.level] = gxobject
|
678
876
|
else:
|
679
|
-
|
680
|
-
|
681
|
-
print("This event does not look like a Fact")
|
877
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
682
878
|
|
683
879
|
else:
|
684
880
|
possible_fact = FactType.guess(record.subRecord('TYPE')[0].value)
|
@@ -708,6 +904,13 @@ class Translater():
|
|
708
904
|
else:
|
709
905
|
assert False
|
710
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
|
+
|
711
914
|
def handle_fam(self, record: GedcomRecord) -> None:
|
712
915
|
if record.tag != 'FAM' or record.level != 0:
|
713
916
|
raise ValueError("Invalid record: Must be a level 0 FAM record")
|
@@ -716,16 +919,16 @@ class Translater():
|
|
716
919
|
|
717
920
|
husband_record = record.subRecords('HUSB')
|
718
921
|
if husband_record:
|
719
|
-
husband = self.gedcomx.
|
922
|
+
husband = self.gedcomx.get_person_by_id(husband_record[0].xref)
|
720
923
|
|
721
924
|
wife_record = record.subRecords('WIFE')
|
722
925
|
if wife_record:
|
723
|
-
wife = self.gedcomx.
|
926
|
+
wife = self.gedcomx.get_person_by_id(wife_record[0].xref)
|
724
927
|
|
725
928
|
children_records = record.subRecords('CHIL')
|
726
929
|
if children_records:
|
727
930
|
for child_record in children_records:
|
728
|
-
child = self.gedcomx.
|
931
|
+
child = self.gedcomx.get_person_by_id(child_record.xref)
|
729
932
|
if child:
|
730
933
|
children.append(child)
|
731
934
|
|
@@ -748,41 +951,43 @@ class Translater():
|
|
748
951
|
return
|
749
952
|
|
750
953
|
def handle_file(self, record: GedcomRecord):
|
751
|
-
if record.value.strip() != '':
|
954
|
+
if record.value and record.value.strip() != '':
|
752
955
|
#raise ValueError(f"I did not expect the 'FILE' tag to have a value: {record.value}")
|
753
956
|
#TODO Handle files referenced here
|
754
957
|
...
|
755
958
|
elif isinstance(self.object_map[record.level-1], SourceDescription):
|
756
959
|
...
|
757
960
|
self.object_map[record.level-1].resourceType = ResourceType.DigitalArtifact
|
758
|
-
|
759
|
-
|
961
|
+
|
760
962
|
def handle_form(self, record: GedcomRecord):
|
761
963
|
if record.parent.tag == 'FILE' and isinstance(self.object_map[record.level-2], SourceDescription):
|
762
|
-
if record.value.strip() != '':
|
964
|
+
if record.value and record.value.strip() != '':
|
763
965
|
mime_type, _ = mimetypes.guess_type('placehold.' + record.value)
|
764
966
|
if mime_type:
|
765
967
|
self.object_map[record.level-2].mediaType = mime_type
|
766
968
|
else:
|
767
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
|
768
974
|
else:
|
769
|
-
raise
|
975
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
770
976
|
|
771
|
-
def handle_givn(self, record):
|
977
|
+
def handle_givn(self, record: GedcomRecord):
|
772
978
|
if isinstance(self.object_map[record.level-1], Name):
|
773
979
|
given_name = NamePart(value=record.value, type=NamePartType.Given)
|
774
980
|
self.object_map[record.level-1]._add_name_part(given_name)
|
775
981
|
else:
|
776
|
-
|
777
|
-
assert False
|
982
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
778
983
|
|
779
|
-
def handle_indi(self, record):
|
984
|
+
def handle_indi(self, record: GedcomRecord):
|
780
985
|
person = Person(id=record.xref.replace('@',''))
|
781
986
|
self.gedcomx.add_person(person)
|
782
987
|
self.object_stack.append(person)
|
783
988
|
self.object_map[record.level] = person
|
784
989
|
|
785
|
-
def handle_immi(self, record):
|
990
|
+
def handle_immi(self, record: GedcomRecord):
|
786
991
|
if isinstance(self.object_map[record.level-1], Person):
|
787
992
|
gxobject = Fact(type=FactType.Immigration)
|
788
993
|
self.object_map[record.level-1].add_fact(gxobject)
|
@@ -790,10 +995,9 @@ class Translater():
|
|
790
995
|
self.object_stack.append(gxobject)
|
791
996
|
self.object_map[record.level] = gxobject
|
792
997
|
else:
|
793
|
-
|
794
|
-
assert False
|
998
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
795
999
|
|
796
|
-
def handle_marr(self, record):
|
1000
|
+
def handle_marr(self, record: GedcomRecord):
|
797
1001
|
if isinstance(self.object_map[record.level-1], Person):
|
798
1002
|
gxobject = Fact(type=FactType.Marriage)
|
799
1003
|
self.object_map[record.level-1].add_fact(gxobject)
|
@@ -801,10 +1005,9 @@ class Translater():
|
|
801
1005
|
self.object_stack.append(gxobject)
|
802
1006
|
self.object_map[record.level] = gxobject
|
803
1007
|
else:
|
804
|
-
|
805
|
-
assert False
|
1008
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
806
1009
|
|
807
|
-
def handle_name(self, record):
|
1010
|
+
def handle_name(self, record: GedcomRecord):
|
808
1011
|
if isinstance(self.object_map[record.level-1], Person):
|
809
1012
|
gxobject = Name.simple(record.value)
|
810
1013
|
#gxobject = Name(nameForms=[NameForm(fullText=record.value)], type=NameType.BirthName)
|
@@ -816,10 +1019,9 @@ class Translater():
|
|
816
1019
|
gxobject = TextValue(value=record.value)
|
817
1020
|
self.object_map[record.level-1].add_name(gxobject)
|
818
1021
|
else:
|
819
|
-
|
820
|
-
assert False
|
1022
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
821
1023
|
|
822
|
-
def handle_note(self, record):
|
1024
|
+
def handle_note(self, record: GedcomRecord):
|
823
1025
|
if isinstance(self.object_map[record.level-1], SourceDescription):
|
824
1026
|
gxobject = Note(text=Translater.clean_str(record.value))
|
825
1027
|
self.object_map[record.level-1].add_note(gxobject)
|
@@ -828,7 +1030,7 @@ class Translater():
|
|
828
1030
|
self.object_map[record.level] = gxobject
|
829
1031
|
elif isinstance(self.object_map[record.level-1], SourceReference):
|
830
1032
|
gxobject = Note(text=Translater.clean_str(record.value))
|
831
|
-
self.object_map[record.level-1].
|
1033
|
+
self.object_map[record.level-1].description.add_note(gxobject)
|
832
1034
|
|
833
1035
|
self.object_stack.append(gxobject)
|
834
1036
|
self.object_map[record.level] = gxobject
|
@@ -838,19 +1040,30 @@ class Translater():
|
|
838
1040
|
|
839
1041
|
self.object_stack.append(gxobject)
|
840
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
|
+
|
841
1055
|
else:
|
842
1056
|
raise ValueError(f"Could not handle 'NOTE' tag in record {record.describe()}, last stack object {type(self.object_map[record.level-1])}")
|
843
1057
|
assert False
|
844
1058
|
|
845
|
-
def handle_nsfx(self, record):
|
1059
|
+
def handle_nsfx(self, record: GedcomRecord):
|
846
1060
|
if isinstance(self.object_map[record.level-1], Name):
|
847
1061
|
surname = NamePart(value=record.value, type=NamePartType.Suffix)
|
848
1062
|
self.object_map[record.level-1]._add_name_part(surname)
|
849
1063
|
else:
|
850
|
-
|
851
|
-
assert False
|
1064
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
852
1065
|
|
853
|
-
def handle_occu(self, record):
|
1066
|
+
def handle_occu(self, record: GedcomRecord):
|
854
1067
|
if isinstance(self.object_map[record.level-1], Person):
|
855
1068
|
gxobject = Fact(type=FactType.Occupation)
|
856
1069
|
self.object_map[record.level-1].add_fact(gxobject)
|
@@ -858,16 +1071,15 @@ class Translater():
|
|
858
1071
|
self.object_stack.append(gxobject)
|
859
1072
|
self.object_map[record.level] = gxobject
|
860
1073
|
else:
|
861
|
-
|
862
|
-
assert False
|
1074
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
863
1075
|
|
864
1076
|
def handle_obje(self, record: GedcomRecord):
|
865
1077
|
self.handle_sour(record)
|
866
1078
|
|
867
|
-
def handle_page(self, record):
|
1079
|
+
def handle_page(self, record: GedcomRecord):
|
868
1080
|
if isinstance(self.object_map[record.level-1], SourceReference):
|
869
1081
|
self.object_map[record.level-1].descriptionId = record.value
|
870
|
-
self.object_map[record.level-1].add_qualifier(KnownSourceReference.Page)
|
1082
|
+
self.object_map[record.level-1].add_qualifier(KnownSourceReference(name=str(KnownSourceReference.Page),value=record.value))
|
871
1083
|
|
872
1084
|
#self.object_stack.append(gxobject)
|
873
1085
|
#self.object_map[record.level] = gxobject
|
@@ -875,7 +1087,7 @@ class Translater():
|
|
875
1087
|
else:
|
876
1088
|
raise ValueError(f"Could not handle 'PAGE' tag in record {record.describe()}, last stack object {self.object_map[record.level-1]}")
|
877
1089
|
|
878
|
-
def handle_plac(self, record):
|
1090
|
+
def handle_plac(self, record: GedcomRecord):
|
879
1091
|
if isinstance(self.object_map[record.level-1], Agent):
|
880
1092
|
gxobject = Address(value=record.value)
|
881
1093
|
self.object_map[record.level-1].add_address(gxobject)
|
@@ -884,36 +1096,38 @@ class Translater():
|
|
884
1096
|
self.object_map[record.level] = gxobject
|
885
1097
|
elif isinstance(self.object_map[record.level-1], Event):
|
886
1098
|
if self.gedcomx.places.byName(record.value):
|
887
|
-
self.object_map[record.level-1].place = PlaceReference(original=record.value,
|
1099
|
+
self.object_map[record.level-1].place = PlaceReference(original=record.value, description=self.gedcomx.places.byName(record.value)[0])
|
888
1100
|
else:
|
889
1101
|
place_des = PlaceDescription(names=[TextValue(value=record.value)])
|
890
1102
|
self.gedcomx.add_place_description(place_des)
|
891
|
-
self.object_map[record.level-1].place = PlaceReference(original=record.value,
|
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
|
+
|
892
1107
|
elif isinstance(self.object_map[record.level-1], Fact):
|
893
1108
|
if self.gedcomx.places.byName(record.value):
|
894
|
-
self.object_map[record.level-1].place = PlaceReference(original=record.value,
|
1109
|
+
self.object_map[record.level-1].place = PlaceReference(original=record.value, description=self.gedcomx.places.byName(record.value)[0])
|
895
1110
|
else:
|
896
1111
|
place_des = PlaceDescription(names=[TextValue(value=record.value)])
|
897
1112
|
self.gedcomx.add_place_description(place_des)
|
898
|
-
self.object_map[record.level-1].place = PlaceReference(original=record.value,
|
1113
|
+
self.object_map[record.level-1].place = PlaceReference(original=record.value, description=place_des)
|
899
1114
|
elif isinstance(self.object_map[record.level-1], SourceDescription):
|
900
1115
|
gxobject = Note(text='Place: ' + record.value)
|
901
1116
|
self.object_map[record.level-1].add_note(gxobject)
|
902
1117
|
self.object_stack.append(gxobject)
|
903
1118
|
self.object_map[record.level] = gxobject
|
904
1119
|
else:
|
905
|
-
|
906
|
-
assert False
|
1120
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
907
1121
|
|
908
|
-
def handle_post(self, record):
|
1122
|
+
def handle_post(self, record: GedcomRecord):
|
909
1123
|
if isinstance(self.object_map[record.level-1], Address):
|
910
1124
|
self.object_map[record.level-1].postalCode = Translater.clean_str(record.value)
|
911
1125
|
else:
|
912
1126
|
raise ValueError(f"I do not know how to handle an 'POST' tag for a {type(self.object_map[record.level-1])}")
|
913
1127
|
|
914
|
-
def handle_publ(self, record):
|
1128
|
+
def handle_publ(self, record: GedcomRecord):
|
915
1129
|
if isinstance(self.object_map[record.level-1], SourceDescription):
|
916
|
-
if self.gedcomx.agents.byName(record.value):
|
1130
|
+
if record.value and self.gedcomx.agents.byName(record.value):
|
917
1131
|
gxobject = self.gedcomx.agents.byName(record.value)[0]
|
918
1132
|
else:
|
919
1133
|
gxobject = Agent(names=[TextValue(record.value)])
|
@@ -923,10 +1137,9 @@ class Translater():
|
|
923
1137
|
self.object_stack.append(gxobject)
|
924
1138
|
self.object_map[record.level] = gxobject
|
925
1139
|
else:
|
926
|
-
|
927
|
-
assert False
|
1140
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
928
1141
|
|
929
|
-
def handle_prob(self, record):
|
1142
|
+
def handle_prob(self, record: GedcomRecord):
|
930
1143
|
if isinstance(self.object_map[record.level-1], Person):
|
931
1144
|
gxobject = Fact(type=FactType.Probate)
|
932
1145
|
self.object_map[record.level-1].add_fact(gxobject)
|
@@ -934,28 +1147,46 @@ class Translater():
|
|
934
1147
|
self.object_stack.append(gxobject)
|
935
1148
|
self.object_map[record.level] = gxobject
|
936
1149
|
else:
|
937
|
-
|
938
|
-
assert False
|
1150
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
939
1151
|
|
940
|
-
def
|
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):
|
941
1160
|
if isinstance(self.object_map[record.level-1], Person) or isinstance(self.object_map[record.level-1], SourceDescription):
|
942
|
-
|
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
|
943
1170
|
else:
|
944
1171
|
raise ValueError(f"Could not handle 'REFN' tag in record {record.describe()}, last stack object {type(self.object_map[record.level-1])}")
|
945
1172
|
|
946
|
-
def handle_repo(self, record):
|
1173
|
+
def handle_repo(self, record: GedcomRecord):
|
1174
|
+
|
947
1175
|
if record.level == 0:
|
948
1176
|
|
949
|
-
gxobject = Agent(id=record.
|
1177
|
+
gxobject = Agent(id=record.xref)
|
950
1178
|
self.gedcomx.add_agent(gxobject)
|
951
1179
|
self.object_stack.append(gxobject)
|
952
1180
|
self.object_map[record.level] = gxobject
|
953
1181
|
|
954
1182
|
elif isinstance(self.object_map[record.level-1], SourceDescription):
|
955
|
-
if self.gedcomx.agents.byId(record.
|
1183
|
+
if self.gedcomx.agents.byId(record.xref) is not None:
|
1184
|
+
|
956
1185
|
# TODO WHere and what to add this to?
|
957
|
-
gxobject = self.gedcomx.agents.byId(record.
|
1186
|
+
gxobject = self.gedcomx.agents.byId(record.xref)
|
958
1187
|
self.object_map[record.level-1].repository = gxobject
|
1188
|
+
self.object_map[record.level] = gxobject
|
1189
|
+
|
959
1190
|
else:
|
960
1191
|
print(record.describe())
|
961
1192
|
raise ValueError()
|
@@ -967,20 +1198,19 @@ class Translater():
|
|
967
1198
|
self.object_stack.append(gxobject)
|
968
1199
|
self.object_map[record.level] = gxobject
|
969
1200
|
|
970
|
-
def handle_resi(self, record):
|
1201
|
+
def handle_resi(self, record: GedcomRecord):
|
971
1202
|
if isinstance(self.object_map[record.level-1], Person):
|
972
1203
|
gxobject = Fact(type=FactType.Residence)
|
973
|
-
if record.value.strip() != '':
|
1204
|
+
if record.value and record.value.strip() != '':
|
974
1205
|
gxobject.add_note(Note(text=record.value))
|
975
1206
|
self.object_map[record.level-1].add_fact(gxobject)
|
976
1207
|
|
977
1208
|
self.object_stack.append(gxobject)
|
978
1209
|
self.object_map[record.level] = gxobject
|
979
1210
|
else:
|
980
|
-
|
981
|
-
assert False
|
1211
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
982
1212
|
|
983
|
-
def handle_rin(self, record):
|
1213
|
+
def handle_rin(self, record: GedcomRecord):
|
984
1214
|
if isinstance(self.object_map[record.level-1], SourceDescription):
|
985
1215
|
self.object_map[record.level-1].id = record.value
|
986
1216
|
self.object_map[record.level-1].add_note(Note(text=f"Source had RIN: of {record.value}"))
|
@@ -1004,51 +1234,59 @@ class Translater():
|
|
1004
1234
|
else:
|
1005
1235
|
assert False
|
1006
1236
|
|
1007
|
-
def handle_sour(self, record):
|
1237
|
+
def handle_sour(self, record: GedcomRecord):
|
1008
1238
|
if record.level == 0 or record.tag == '_WLNK' or (record.level == 0 and record.tag == 'OBJE'):
|
1009
|
-
source_description = SourceDescription(id=record.xref)
|
1239
|
+
source_description = SourceDescription(id=record.xref.replace('@','') if record.xref else None)
|
1010
1240
|
self.gedcomx.add_source_description(source_description)
|
1011
1241
|
self.object_stack.append(source_description)
|
1012
1242
|
self.object_map[record.level] = source_description
|
1013
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
|
1014
1248
|
if self.gedcomx.source_descriptions.byId(record.xref):
|
1015
1249
|
gxobject = SourceReference(descriptionId=record.xref, description=self.gedcomx.source_descriptions.byId(record.xref))
|
1016
1250
|
else:
|
1251
|
+
import_log.warning(f'Could not find source with id: {record.xref}')
|
1017
1252
|
source_description = SourceDescription(id=record.xref)
|
1018
1253
|
gxobject = SourceReference(descriptionId=record.value, description=source_description)
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
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)
|
1023
1260
|
self.object_stack.append(gxobject)
|
1024
1261
|
self.object_map[record.level] = gxobject
|
1025
|
-
|
1026
|
-
|
1027
|
-
def handle_stae(self, record):
|
1262
|
+
|
1263
|
+
def handle_stae(self, record: GedcomRecord):
|
1028
1264
|
if isinstance(self.object_map[record.level-1], Address):
|
1029
1265
|
self.object_map[record.level-1].stateOrProvince = Translater.clean_str(record.value)
|
1030
1266
|
else:
|
1031
1267
|
raise ValueError(f"I do not know how to handle an 'STAE' tag for a {type(self.object_map[record.level-1])}")
|
1032
1268
|
|
1033
|
-
def handle_surn(self, record):
|
1269
|
+
def handle_surn(self, record: GedcomRecord):
|
1034
1270
|
if isinstance(self.object_map[record.level-1], Name):
|
1035
1271
|
surname = NamePart(value=record.value, type=NamePartType.Surname)
|
1036
1272
|
self.object_map[record.level-1]._add_name_part(surname)
|
1037
1273
|
else:
|
1038
|
-
|
1039
|
-
assert False
|
1274
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
1040
1275
|
|
1041
1276
|
def handle_text(self, record: GedcomRecord):
|
1042
1277
|
if record.parent.tag == 'DATA':
|
1043
1278
|
if isinstance(self.object_map[record.level-2], SourceReference):
|
1044
1279
|
gxobject = TextValue(value=record.value)
|
1045
|
-
self.object_map[record.level-2].
|
1280
|
+
self.object_map[record.level-2].description.add_description(gxobject)
|
1046
1281
|
self.object_stack.append(gxobject)
|
1047
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
|
1048
1286
|
else:
|
1049
1287
|
assert False
|
1050
1288
|
|
1051
|
-
def handle_titl(self, record):
|
1289
|
+
def handle_titl(self, record: GedcomRecord):
|
1052
1290
|
if isinstance(self.object_map[record.level-1], SourceDescription):
|
1053
1291
|
|
1054
1292
|
gxobject = TextValue(value=Translater.clean_str(record.value))
|
@@ -1068,12 +1306,12 @@ class Translater():
|
|
1068
1306
|
|
1069
1307
|
self.object_map[record.level]._add_name_part(gxobject)
|
1070
1308
|
else:
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1309
|
+
raise TagConversionError(record=record,levelstack=self.object_map)
|
1310
|
+
|
1311
|
+
def handle_tran(self, record: GedcomRecord):
|
1312
|
+
pass
|
1075
1313
|
|
1076
|
-
def handle_type(self, record):
|
1314
|
+
def handle_type(self, record: GedcomRecord):
|
1077
1315
|
# peek to see if event or fact
|
1078
1316
|
if isinstance(self.object_map[record.level-1], Event):
|
1079
1317
|
if EventType.guess(record.value):
|
@@ -1084,6 +1322,11 @@ class Translater():
|
|
1084
1322
|
elif isinstance(self.object_map[record.level-1], Fact):
|
1085
1323
|
if not self.object_map[record.level-1].type:
|
1086
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
|
+
|
1087
1330
|
elif record.parent.tag == 'FORM':
|
1088
1331
|
if not self.object_map[0].mediaType:
|
1089
1332
|
self.object_map[0].mediaType = record.value
|
@@ -1091,15 +1334,17 @@ class Translater():
|
|
1091
1334
|
else:
|
1092
1335
|
raise ValueError(f"I do not know how to handle 'TYPE' tag for {type(self.object_map[record.level-1])}")
|
1093
1336
|
|
1094
|
-
def handle__url(self, record):
|
1337
|
+
def handle__url(self, record: GedcomRecord):
|
1095
1338
|
if isinstance(self.object_map[record.level-2], SourceDescription):
|
1096
1339
|
self.object_map[record.level-2].about = URI.from_url(record.value)
|
1097
1340
|
else:
|
1098
1341
|
raise ValueError(f"Could not handle '_URL' tag in record {record.describe()}, last stack object {self.object_map[record.level-1]}")
|
1099
1342
|
|
1100
|
-
def handle_www(self, record):
|
1101
|
-
if isinstance(self.object_map[record.level-
|
1102
|
-
self.object_map[record.level-
|
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)))
|
1103
1348
|
else:
|
1104
1349
|
raise ValueError(f"Could not handle 'WWW' tag in record {record.describe()}, last stack object {self.object_map[record.level-1]}")
|
1105
1350
|
|