1818#
1919
2020"""Timeline API resources."""
21- from typing import Dict , List , Tuple , Union
21+ from typing import Dict , List , Optional , Set , Tuple , Union
2222
2323from flask import abort
2424from gramps .gen .const import GRAMPS_LOCALE as glocale
2525from gramps .gen .db .base import DbReadBase
2626from gramps .gen .display .place import PlaceDisplay
2727from gramps .gen .errors import HandleError
28- from gramps .gen .lib import Date , Event , EventType , Person , Span
28+ from gramps .gen .lib import Date , Event , EventRef , EventType , Person , Span
2929from gramps .gen .relationship import get_relationship_calculator
3030from gramps .gen .utils .alive import probably_alive_range
3131from gramps .gen .utils .db import (
@@ -99,19 +99,19 @@ class Timeline:
9999 def __init__ (
100100 self ,
101101 db_handle : DbReadBase ,
102- dates : Union [str , None ] = None ,
103- events : Union [List , None ] = None ,
102+ dates : Optional [str ] = None ,
103+ events : Optional [List [ str ] ] = None ,
104104 ratings : bool = False ,
105- relatives : Union [List , None ] = None ,
106- relative_events : Union [List , None ] = None ,
105+ relatives : Optional [List [ str ] ] = None ,
106+ relative_events : Optional [List [ str ] ] = None ,
107107 discard_empty : bool = True ,
108108 omit_anchor : bool = True ,
109109 precision : int = 1 ,
110110 locale : GrampsLocale = glocale ,
111111 ):
112112 """Initialize timeline."""
113113 self .db_handle = db_handle
114- self .timeline = []
114+ self .timeline : List [ Tuple [ Event , Person , str , str ]] = []
115115 self .dates = dates
116116 self .start_date = None
117117 self .end_date = None
@@ -122,14 +122,14 @@ def __init__(
122122 self .anchor_person = None
123123 self .omit_anchor = omit_anchor
124124 self .depth = 1
125- self .eligible_events = set ([] )
126- self .event_filters = events or []
127- self .eligible_relative_events = set ([] )
128- self .relative_event_filters = relative_events or []
129- self .relative_filters = relatives or []
125+ self .eligible_events : Set [ str ] = set ()
126+ self .event_filters : List [ str ] = events or []
127+ self .eligible_relative_events : Set [ str ] = set ()
128+ self .relative_event_filters : List [ str ] = relative_events or []
129+ self .relative_filters : List [ str ] = relatives or []
130130 self .set_event_filters (self .event_filters )
131131 self .set_relative_event_filters (self .relative_event_filters )
132- self .birth_dates = {}
132+ self .birth_dates : Dict [ str , Date ] = {}
133133
134134 if dates and "-" in dates :
135135 start , end = dates .split ("-" )
@@ -172,19 +172,19 @@ def set_locale(self, locale: str):
172172 """Set optional locale for span."""
173173 self .locale = get_locale_for_language (locale , default = True )
174174
175- def set_event_filters (self , filters : Union [List , None ] = None ):
175+ def set_event_filters (self , filters : Optional [List [ str ] ] = None ):
176176 """Prepare the event filter table."""
177177 self .event_filters = filters or []
178178 self .eligible_events = self ._prepare_eligible_events (self .event_filters )
179179
180- def set_relative_event_filters (self , filters : Union [List , None ] = None ):
180+ def set_relative_event_filters (self , filters : Optional [List [ str ] ] = None ):
181181 """Prepare the relative event filter table."""
182182 self .relative_event_filters = filters or []
183183 self .eligible_relative_events = self ._prepare_eligible_events (
184184 self .relative_event_filters
185185 )
186186
187- def _prepare_eligible_events (self , event_filters : List ):
187+ def _prepare_eligible_events (self , event_filters : List [ str ] ):
188188 """Prepare an event filter list."""
189189 eligible_events = {"Birth" , "Death" }
190190 event_type = EventType ()
@@ -199,9 +199,7 @@ def _prepare_eligible_events(self, event_filters: List):
199199 eligible_events .add (key )
200200 continue
201201 if key not in EVENT_CATEGORIES :
202- raise ValueError (
203- "{} is not a valid event or event category" .format (key )
204- )
202+ raise ValueError (f"{ key } is not a valid event or event category" )
205203 for entry in event_type .get_menu_standard_xml ():
206204 event_key = entry [0 ].lower ().replace ("life events" , "vital" )
207205 if event_key in event_filters :
@@ -214,7 +212,7 @@ def _prepare_eligible_events(self, event_filters: List):
214212 eligible_events .add (event_name )
215213 return eligible_events
216214
217- def get_age (self , start_date , date ):
215+ def get_age (self , start_date : str , date : str ):
218216 """Return calculated age or empty string otherwise."""
219217 age = ""
220218 if start_date :
@@ -255,7 +253,7 @@ def is_eligible(self, event: Event, relative: bool):
255253 return True
256254 return str (event .get_type ()) in self .eligible_events
257255
258- def add_event (self , event : Tuple , relative = False ):
256+ def add_event (self , event : Tuple [ Event , Person , str , str ], relative : bool = False ):
259257 """Add event to timeline if needed."""
260258 if self .discard_empty :
261259 if event [0 ].date .sortval == 0 :
@@ -295,7 +293,8 @@ def add_person(
295293 self .birth_dates .update ({person .handle : event .date })
296294 for event_ref in person .event_ref_list :
297295 event = self .db_handle .get_event_from_handle (event_ref .ref )
298- self .add_event ((event , person , "self" ))
296+ role = event_ref .get_role ().xml_str ()
297+ self .add_event ((event , person , "self" , role ))
299298 if anchor and not self .anchor_person :
300299 self .anchor_person = person
301300 self .depth = max (ancestors , offspring ) + 1
@@ -345,28 +344,29 @@ def add_relative(self, handle: Handle, ancestors: int = 1, offspring: int = 1):
345344 if self .relative_event_filters :
346345 for event_ref in person .event_ref_list :
347346 event = self .db_handle .get_event_from_handle (event_ref .ref )
348- self .add_event ((event , person , relationship ), relative = True )
347+ role = event_ref .get_role ().xml_str ()
348+ self .add_event ((event , person , relationship , role ), relative = True )
349349
350350 event = get_birth_or_fallback (self .db_handle , person )
351351 if event :
352- self .add_event ((event , person , relationship ), relative = True )
352+ self .add_event ((event , person , relationship , "Primary" ), relative = True )
353353 if person .handle not in self .birth_dates :
354354 self .birth_dates .update ({person .handle : event .date })
355355
356356 event = get_death_or_fallback (self .db_handle , person )
357357 if event :
358- self .add_event ((event , person , relationship ), relative = True )
358+ self .add_event ((event , person , relationship , "Primary" ), relative = True )
359359
360360 for family_handle in person .family_list :
361361 family = self .db_handle .get_family_from_handle (family_handle )
362362
363363 event = get_marriage_or_fallback (self .db_handle , family )
364364 if event :
365- self .add_event ((event , person , relationship ), relative = True )
365+ self .add_event ((event , person , relationship , "Family" ), relative = True )
366366
367367 event = get_divorce_or_fallback (self .db_handle , family )
368368 if event :
369- self .add_event ((event , person , relationship ), relative = True )
369+ self .add_event ((event , person , relationship , "Family" ), relative = True )
370370
371371 if offspring > 1 :
372372 for child_ref in family .child_ref_list :
@@ -382,7 +382,7 @@ def add_relative(self, handle: Handle, ancestors: int = 1, offspring: int = 1):
382382 def add_family (
383383 self ,
384384 handle : Handle ,
385- anchor : Union [Person , None ] = None ,
385+ anchor : Optional [Person ] = None ,
386386 include_children : bool = True ,
387387 ancestors : int = 1 ,
388388 offspring : int = 1 ,
@@ -393,7 +393,8 @@ def add_family(
393393 if anchor :
394394 for event_ref in family .event_ref_list :
395395 event = self .db_handle .get_event_from_handle (event_ref .ref )
396- self .add_event ((event , anchor , "self" ))
396+ role = event_ref .get_role ().xml_str ()
397+ self .add_event ((event , anchor , "self" , role ))
397398 if events_only :
398399 return
399400 if self .anchor_person :
@@ -427,68 +428,69 @@ def profile(self, page=0, pagesize=20):
427428 if page > 0 :
428429 offset = (page - 1 ) * pagesize
429430 events = events [offset : offset + pagesize ]
430- for event in events :
431- label = self .locale .translation .sgettext (str (event [ 0 ] .type ))
431+ for ( event , person_object , relationship , role ) in events :
432+ label = self .locale .translation .sgettext (str (event .type ))
432433 if (
433- event [ 1 ]
434+ person_object
434435 and self .anchor_person
435- and self .anchor_person .handle != event [ 1 ] .handle
436- and event [ 2 ] not in ["self" , "" , None ]
436+ and self .anchor_person .handle != person_object .handle
437+ and relationship not in ["self" , "" , None ]
437438 ):
438- label = "{ } ({})" . format ( label , event [ 2 ]. title ())
439+ label = f" { label } ({ relationship . title ()} )"
439440
440441 try :
441- obj = self .db_handle .get_place_from_handle (event [ 0 ] .place )
442+ obj = self .db_handle .get_place_from_handle (event .place )
442443 place = get_place_profile_for_object (
443444 self .db_handle , obj , locale = self .locale
444445 )
445- place ["display_name" ] = pd .display_event (self .db_handle , event [ 0 ] )
446- place ["handle" ] = event [ 0 ] .place
446+ place ["display_name" ] = pd .display_event (self .db_handle , event )
447+ place ["handle" ] = event .place
447448 except HandleError :
448449 place = {}
449450
450451 age = ""
451452 person = {}
452- if event [ 1 ] is not None :
453+ if person_object is not None :
453454 person_age = ""
454455 get_person = True
455456 if self .anchor_person :
456457 if self .anchor_person .handle in self .birth_dates :
457458 age = self .get_age (
458- self .birth_dates [self .anchor_person .handle ], event [ 0 ] .date
459+ self .birth_dates [self .anchor_person .handle ], event .date
459460 )
460- if self .anchor_person .handle == event [ 1 ] .handle :
461+ if self .anchor_person .handle == person_object .handle :
461462 person_age = age
462463 if self .omit_anchor :
463464 get_person = False
464465 if get_person :
465466 person = get_person_profile_for_object (
466- self .db_handle , event [ 1 ] , {}, locale = self .locale
467+ self .db_handle , person_object , {}, locale = self .locale
467468 )
468- if not person_age and event [ 1 ] .handle in self .birth_dates :
469+ if not person_age and person_object .handle in self .birth_dates :
469470 person_age = self .get_age (
470- self .birth_dates [event [ 1 ] .handle ], event [ 0 ] .date
471+ self .birth_dates [person_object .handle ], event .date
471472 )
472473 if not age :
473474 age = person_age
474475 person ["age" ] = person_age
475476
476477 profile = {
477- "date" : self .locale .date_displayer .display (event [ 0 ] .date ),
478- "description" : event [ 0 ] .description ,
479- "gramps_id" : event [ 0 ] .gramps_id ,
480- "handle" : event [ 0 ] .handle ,
478+ "date" : self .locale .date_displayer .display (event .date ),
479+ "description" : event .description ,
480+ "gramps_id" : event .gramps_id ,
481+ "handle" : event .handle ,
481482 "label" : self .locale .translation .sgettext (label ),
482- "media" : [x .ref for x in event [ 0 ] .media_list ],
483+ "media" : [x .ref for x in event .media_list ],
483484 "person" : person ,
484485 "place" : place ,
485486 "age" : age ,
486- "type" : event [0 ].type ,
487+ "type" : event .type ,
488+ "role" : self .locale .translation .gettext (role ),
487489 }
488- profile ["person" ]["relationship" ] = str (event [ 2 ] )
490+ profile ["person" ]["relationship" ] = str (relationship )
489491 if self .ratings :
490- profile ["citations" ] = event [ 0 ] .citations
491- profile ["confidence" ] = event [ 0 ] .confidence
492+ profile ["citations" ] = event .citations
493+ profile ["confidence" ] = event .confidence
492494 profiles .append (profile )
493495 return profiles
494496
@@ -584,7 +586,7 @@ def get(self, args: Dict, handle: str):
584586 locale = locale ,
585587 )
586588 timeline .add_person (
587- handle ,
589+ Handle ( handle ) ,
588590 anchor = True ,
589591 start = args ["first" ],
590592 end = args ["last" ],
@@ -645,7 +647,7 @@ def get(self, args: Dict, handle: str):
645647 discard_empty = args ["discard_empty" ],
646648 locale = locale ,
647649 )
648- timeline .add_family (handle )
650+ timeline .add_family (Handle ( handle ) )
649651 except ValueError :
650652 abort (422 )
651653 except HandleError :
0 commit comments