1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """
24 Person object for GRAMPS.
25 """
26
27
28
29
30
31 from types import InstanceType
32
33
34
35
36
37
38 from gen.lib.primaryobj import PrimaryObject
39 from gen.lib.srcbase import SourceBase
40 from gen.lib.notebase import NoteBase
41 from gen.lib.mediabase import MediaBase
42 from gen.lib.attrbase import AttributeBase
43 from gen.lib.addressbase import AddressBase
44 from gen.lib.ldsordbase import LdsOrdBase
45 from gen.lib.urlbase import UrlBase
46 from gen.lib.name import Name
47 from gen.lib.eventref import EventRef
48 from gen.lib.personref import PersonRef
49 from gen.lib.attrtype import AttributeType
50 from gen.lib.eventroletype import EventRoleType
51 from gen.lib.markertype import MarkerType
52
53
54
55
56
57
58 -class Person(SourceBase, NoteBase, AttributeBase, MediaBase,
59 AddressBase, UrlBase, LdsOrdBase, PrimaryObject):
60 """
61 Introduction
62 ============
63 The Person record is the GRAMPS in-memory representation of an
64 individual person. It contains all the information related to
65 an individual.
66
67 Usage
68 =====
69 Person objects are usually created in one of two ways.
70
71 1. Creating a new person object, which is then initialized and added to
72 the database.
73 2. Retrieving an object from the database using the records handle.
74
75 Once a Person object has been modified, it must be committed
76 to the database using the database object's commit_person function,
77 or the changes will be lost.
78
79 """
80
81 UNKNOWN = 2
82 MALE = 1
83 FEMALE = 0
84
113
114
115
116
117
119 """
120 Convert the data held in the Person to a Python tuple that
121 represents all the data elements.
122
123 This method is used to convert the object into a form that can easily
124 be saved to a database.
125
126 These elements may be primative Python types (string, integers),
127 complex Python types (lists or tuples, or Python objects. If the
128 target database cannot handle complex types (such as objectes or
129 lists), the database is responsible for converting the data into
130 a form that it can use.
131
132 @returns: Returns a python tuple containing the data that should
133 be considered persistent.
134 @rtype: tuple
135 """
136 return (
137 self.handle,
138 self.gramps_id,
139 self.gender,
140 self.primary_name.serialize(),
141 [name.serialize() for name in self.alternate_names],
142 self.death_ref_index,
143 self.birth_ref_index,
144 [er.serialize() for er in self.event_ref_list],
145 self.family_list,
146 self.parent_family_list,
147 MediaBase.serialize(self),
148 AddressBase.serialize(self),
149 AttributeBase.serialize(self),
150 UrlBase.serialize(self),
151 LdsOrdBase.serialize(self),
152 SourceBase.serialize(self),
153 NoteBase.serialize(self),
154 self.change,
155 self.marker.serialize(),
156 self.private,
157 [pr.serialize() for pr in self.person_ref_list]
158 )
159
161 """
162 Convert the data held in a tuple created by the serialize method
163 back into the data in a Person object.
164
165 @param data: tuple containing the persistent data associated the
166 Person object
167 @type data: tuple
168 """
169 (self.handle,
170 self.gramps_id,
171 self.gender,
172 primary_name,
173 alternate_names,
174 self.death_ref_index,
175 self.birth_ref_index,
176 event_ref_list,
177 self.family_list,
178 self.parent_family_list,
179 media_list,
180 address_list,
181 attribute_list,
182 urls,
183 lds_ord_list,
184 source_list,
185 note_list,
186 self.change,
187 marker,
188 self.private,
189 person_ref_list,
190 ) = data
191
192 self.marker = InstanceType(MarkerType)
193 self.marker.unserialize(marker)
194 self.primary_name = InstanceType(Name)
195 self.primary_name.unserialize(primary_name)
196 self.alternate_names = [InstanceType(Name).unserialize(name)
197 for name in alternate_names]
198 self.event_ref_list = [InstanceType(EventRef).unserialize(er)
199 for er in event_ref_list]
200 self.person_ref_list = [InstanceType(PersonRef).unserialize(pr)
201 for pr in person_ref_list]
202 MediaBase.unserialize(self, media_list)
203 LdsOrdBase.unserialize(self, lds_ord_list)
204 AddressBase.unserialize(self, address_list)
205 AttributeBase.unserialize(self, attribute_list)
206 UrlBase.unserialize(self, urls)
207 SourceBase.unserialize(self, source_list)
208 NoteBase.unserialize(self, note_list)
209
211 """
212 Return True if the object has reference to a given handle of given
213 primary object type.
214
215 @param classname: The name of the primary object class.
216 @type classname: str
217 @param handle: The handle to be checked.
218 @type handle: str
219 @return: Returns whether the object has reference to this handle of
220 this object type.
221 @rtype: bool
222 """
223 if classname == 'Event':
224 return handle in [ref.ref for ref in self.event_ref_list]
225 elif classname == 'Person':
226 return handle in [ref.ref for ref in self.person_ref_list]
227 elif classname == 'Family':
228 return handle in (self.family_list + self.parent_family_list)
229 elif classname == 'Place':
230 return handle in [ordinance.place for ordinance
231 in self.lds_ord_list]
232 return False
233
235 if classname == 'Event':
236
237 birth_ref = self.get_birth_ref()
238 death_ref = self.get_death_ref()
239
240 new_list = [ref for ref in self.event_ref_list
241 if ref.ref not in handle_list]
242
243
244 if (self.birth_ref_index != -1) \
245 and (self.event_ref_list[self.birth_ref_index]
246 in handle_list):
247 self.birth_ref_index = -1
248 if (self.death_ref_index != -1) \
249 and (self.event_ref_list[self.death_ref_index]
250 in handle_list):
251 self.death_ref_index = -1
252 self.event_ref_list = new_list
253
254
255 if (self.birth_ref_index != -1):
256 self.set_birth_ref(birth_ref)
257 if (self.death_ref_index != -1):
258 self.set_death_ref(death_ref)
259 elif classname == 'Person':
260 new_list = [ref for ref in self.person_ref_list
261 if ref.ref not in handle_list]
262 self.person_ref_list = new_list
263 elif classname == 'Family':
264 new_list = [ handle for handle in self.family_list
265 if handle not in handle_list ]
266 self.family_list = new_list
267 new_list = [ handle for handle in self.parent_family_list \
268 if handle not in handle_list ]
269 self.parent_family_list = new_list
270 elif classname == 'Place':
271 for ordinance in self.lds_ord_list:
272 if ordinance.place in handle_list:
273 ordinance.place = None
274
276 if classname == 'Event':
277 handle_list = [ref.ref for ref in self.event_ref_list]
278 while old_handle in handle_list:
279 ix = handle_list.index(old_handle)
280 self.event_ref_list[ix].ref = new_handle
281 handle_list[ix] = ''
282 elif classname == 'Person':
283 handle_list = [ref.ref for ref in self.person_ref_list]
284 while old_handle in handle_list:
285 ix = handle_list.index(old_handle)
286 self.person_ref_list[ix].ref = new_handle
287 handle_list[ix] = ''
288 elif classname == 'Family':
289 while old_handle in self.family_list:
290 ix = self.family_list.index(old_handle)
291 self.family_list[ix] = new_handle
292
293 while old_handle in self.parent_family_list:
294 ix = self.parent_family_list.index(old_handle)
295 self.parent_family_list[ix] = new_handle
296 elif classname == 'Place':
297 handle_list = [ordinance.place for ordinance in self.lds_ord_list]
298 while old_handle in handle_list:
299 ix = handle_list.index(old_handle)
300 self.lds_ord_list[ix].place = new_handle
301 handle_list[ix] = ''
302
304 """
305 Return the list of all textual attributes of the object.
306
307 @return: Returns the list of all textual attributes of the object.
308 @rtype: list
309 """
310 return [self.gramps_id]
311
313 """
314 Return the list of child objects that may carry textual data.
315
316 @return: Returns the list of child objects that may carry textual data.
317 @rtype: list
318 """
319 check_list = self.lds_ord_list
320 add_list = [item for item in check_list if item]
321 return [self.primary_name] + self.media_list + \
322 self.alternate_names + self.address_list + \
323 self.attribute_list + self.urls + \
324 self.source_list + self.event_ref_list + add_list + \
325 self.person_ref_list
326
328 """
329 Return the list of child secondary objects that may refer sources.
330
331 @return: Returns the list of child secondary child objects that may
332 refer sources.
333 @rtype: list
334 """
335 return [self.primary_name] + self.media_list + \
336 self.alternate_names + self.address_list + \
337 self.attribute_list + self.lds_ord_list + \
338 self.person_ref_list + self.event_ref_list
339
341 """
342 Return the list of child secondary objects that may refer notes.
343
344 @return: Returns the list of child secondary child objects that may
345 refer notes.
346 @rtype: list
347 """
348 return [self.primary_name] + self.media_list + \
349 self.alternate_names + self.address_list + \
350 self.attribute_list + self.lds_ord_list + \
351 self.person_ref_list + self.source_list + \
352 self.event_ref_list
353
355 """
356 Return the list of (classname, handle) tuples for all directly
357 referenced primary objects.
358
359 @return: List of (classname, handle) tuples for referenced objects.
360 @rtype: list
361 """
362 return [('Family', handle) for handle in
363 (self.family_list + self.parent_family_list)] \
364 + self.get_referenced_note_handles()
365
367 """
368 Return the list of child objects which may, directly or through
369 their children, reference primary objects.
370
371 @return: Returns the list of objects refereincing primary objects.
372 @rtype: list
373 """
374
375 return self.get_sourcref_child_list() + self.source_list
376
378 """
379 Set the primary name of the Person to the specified L{Name} instance.
380
381 @param name: L{Name} to be assigned to the person
382 @type name: L{Name}
383 """
384 self.primary_name = name
385
387 """
388 Return the L{Name} instance marked as the Person's primary name.
389
390 @return: Returns the primary name
391 @rtype: L{Name}
392 """
393 return self.primary_name
394
396 """
397 Return the list of alternate L{Name} instances.
398
399 @return: List of L{Name} instances
400 @rtype: list
401 """
402 return self.alternate_names
403
405 """
406 Change the list of alternate names to the passed list.
407
408 @param alt_name_list: List of L{Name} instances
409 @type alt_name_list: list
410 """
411 self.alternate_names = alt_name_list
412
414 """
415 Add a L{Name} instance to the list of alternative names.
416
417 @param name: L{Name} to add to the list
418 @type name: L{Name}
419 """
420 self.alternate_names.append(name)
421
423 nicks = [ attr for attr in self.attribute_list \
424 if int(attr.type) == AttributeType.NICKNAME ]
425 if len(nicks) == 0:
426 return u''
427 else:
428 return nicks[0].get_value()
429
431 """
432 Set the gender of the Person.
433
434 @param gender: Assigns the Person's gender to one of the
435 following constants::
436 Person.MALE
437 Person.FEMALE
438 Person.UNKNOWN
439 @type gender: int
440 """
441 self.gender = gender
442
444 """
445 Return the gender of the Person.
446
447 @returns: Returns one of the following constants::
448 Person.MALE
449 Person.FEMALE
450 Person.UNKNOWN
451 @rtype: int
452 """
453 return self.gender
454
456 """
457 Assign the birth event to the Person object.
458
459 This is accomplished by assigning the L{EventRef} of the birth event
460 in the current database.
461
462 @param event_ref: the L{EventRef} object associated with
463 the Person's birth.
464 @type event_ref: EventRef
465 """
466 if event_ref and not isinstance(event_ref, EventRef):
467 raise ValueError("Expecting EventRef instance")
468 if event_ref is None:
469 self.birth_ref_index = -1
470 return
471
472 matches = [event_ref.is_equal(ref) for ref in self.event_ref_list]
473 try:
474 self.birth_ref_index = matches.index(True)
475 except ValueError:
476 self.event_ref_list.append(event_ref)
477 self.birth_ref_index = len(self.event_ref_list)-1
478
480 """
481 Assign the death event to the Person object.
482
483 This is accomplished by assigning the L{EventRef} of the death event
484 in the current database.
485
486 @param event_ref: the L{EventRef} object associated with
487 the Person's death.
488 @type event_ref: EventRef
489 """
490 if event_ref and not isinstance(event_ref, EventRef):
491 raise ValueError("Expecting EventRef instance")
492 if event_ref is None:
493 self.death_ref_index = -1
494 return
495
496 matches = [event_ref.is_equal(ref) for ref in self.event_ref_list]
497 try:
498 self.death_ref_index = matches.index(True)
499 except ValueError:
500 self.event_ref_list.append(event_ref)
501 self.death_ref_index = len(self.event_ref_list)-1
502
504 """
505 Return the L{EventRef} for Person's birth event.
506
507 This should correspond to an L{Event} in the database's L{Event} list.
508
509 @returns: Returns the birth L{EventRef} or None if no birth
510 L{Event} has been assigned.
511 @rtype: EventRef
512 """
513 if self.birth_ref_index == -1:
514 return None
515 else:
516 try:
517 return self.event_ref_list[self.birth_ref_index]
518 except IndexError:
519 return None
520
522 """
523 Return the L{EventRef} for the Person's death event.
524
525 This should correspond to an L{Event} in the database's L{Event} list.
526
527 @returns: Returns the death L{EventRef} or None if no death
528 L{Event} has been assigned.
529 @rtype: event_ref
530 """
531 if self.death_ref_index == -1:
532 return None
533 else:
534 try:
535 return self.event_ref_list[self.death_ref_index]
536 except IndexError:
537 return None
538
540 """
541 Add the L{EventRef} to the Person instance's L{EventRef} list.
542
543 This is accomplished by assigning the L{EventRef} of a valid
544 L{Event} in the current database.
545
546 @param event_ref: the L{EventRef} to be added to the
547 Person's L{EventRef} list.
548 @type event_ref: EventRef
549 """
550 if event_ref and not isinstance(event_ref, EventRef):
551 raise ValueError("Expecting EventRef instance")
552
553 matches = [event_ref.is_equal(ref) for ref in self.event_ref_list]
554 if matches.count(True) == 0:
555 self.event_ref_list.append(event_ref)
556
558 """
559 Return the list of L{EventRef} objects associated with L{Event}
560 instances.
561
562 @returns: Returns the list of L{EventRef} objects associated with
563 the Person instance.
564 @rtype: list
565 """
566 return self.event_ref_list
567
569 """
570 Return the list of L{EventRef} objects associated with L{Event}
571 instances that have been marked as primary events.
572
573 @returns: Returns the list of L{EventRef} objects associated with
574 the Person instance.
575 @rtype: list
576 """
577 return [ ref for ref in self.event_ref_list \
578 if ref.get_role() == EventRoleType.PRIMARY ]
579
581 """
582 Set the Person instance's L{EventRef} list to the passed list.
583
584 @param event_ref_list: List of valid L{EventRef} objects
585 @type event_ref_list: list
586 """
587 self.event_ref_list = event_ref_list
588
590 """
591 Add the L{Family} handle to the Person instance's L{Family} list.
592
593 This is accomplished by assigning the handle of a valid L{Family}
594 in the current database.
595
596 Adding a L{Family} handle to a Person does not automatically update
597 the corresponding L{Family}. The developer is responsible to make
598 sure that when a L{Family} is added to Person, that the Person is
599 assigned to either the father or mother role in the L{Family}.
600
601 @param family_handle: handle of the L{Family} to be added to the
602 Person's L{Family} list.
603 @type family_handle: str
604 """
605 if family_handle not in self.family_list:
606 self.family_list.append(family_handle)
607
609 """
610 Set the family_handle specified to be the preferred L{Family}.
611
612 The preferred L{Family} is determined by the first L{Family} in the
613 L{Family} list, and is typically used to indicate the preferred
614 L{Family} for navigation or reporting.
615
616 The family_handle must already be in the list, or the function
617 call has no effect.
618
619 @param family_handle: Handle of the L{Family} to make the preferred
620 L{Family}.
621 @type family_handle: str
622 @returns: True if the call succeeded, False if the family_handle
623 was not already in the L{Family} list
624 @rtype: bool
625 """
626 if family_handle in self.family_list:
627 self.family_list.remove(family_handle)
628 self.family_list = [family_handle] + self.family_list
629 return True
630 else:
631 return False
632
634 """
635 Return the list of L{Family} handles in which the person is a parent
636 or spouse.
637
638 @return: Returns the list of handles corresponding to the
639 L{Family} records with which the person is associated.
640 @rtype: list
641 """
642 return self.family_list
643
645 """
646 Assign the passed list to the Person's list of families in which it is
647 a parent or spouse.
648
649 @param family_list: List of L{Family} handles to be associated
650 with the Person
651 @type family_list: list
652 """
653 self.family_list = family_list
654
656 """
657 Remove all L{Family} handles from the L{Family} list.
658 """
659 self.family_list = []
660
662 """
663 Remove the specified L{Family} handle from the list of
664 marriages/partnerships.
665
666 If the handle does not exist in the list, the operation has no effect.
667
668 @param family_handle: L{Family} handle to remove from the list
669 @type family_handle: str
670
671 @return: True if the handle was removed, False if it was not
672 in the list.
673 @rtype: bool
674 """
675 if family_handle in self.family_list:
676 self.family_list.remove(family_handle)
677 return True
678 else:
679 return False
680
682 """
683 Return the list of L{Family} handles in which the person is a child.
684
685 @return: Returns the list of handles corresponding to the
686 L{Family} records with which the person is a child.
687 @rtype: list
688 """
689 return self.parent_family_list
690
692 """
693 Return the list of L{Family} handles in which the person is a child.
694
695 @return: Returns the list of handles corresponding to the
696 L{Family} records with which the person is a child.
697 @rtype: list
698 """
699 self.parent_family_list = family_list
700
702 """
703 Add the L{Family} handle to the Person instance's list of families in
704 which it is a child.
705
706 This is accomplished by assigning the handle of a valid L{Family} in
707 the current database.
708
709 Adding a L{Family} handle to a Person does not automatically update
710 the corresponding L{Family}. The developer is responsible to make
711 sure that when a L{Family} is added to Person, that the Person is
712 added to the L{Family} instance's child list.
713
714 @param family_handle: handle of the L{Family} to be added to the
715 Person's L{Family} list.
716 @type family_handle: str
717 """
718 if type(family_handle) not in (str, unicode):
719 raise ValueError("expecting handle")
720 if family_handle not in self.parent_family_list:
721 self.parent_family_list.append(family_handle)
722
724 """
725 Remove all L{Family} handles from the parent L{Family} list.
726 """
727 self.parent_family_list = []
728
730 """
731 Remove the specified L{Family} handle from the list of parent
732 families (families in which the parent is a child).
733
734 If the handle does not exist in the list, the operation has no effect.
735
736 @param family_handle: L{Family} handle to remove from the list
737 @type family_handle: str
738
739 @return: Returns a tuple of three strings, consisting of the
740 removed handle, relationship to mother, and relationship
741 to father. None is returned if the handle is not in the
742 list.
743 @rtype: tuple
744 """
745 if family_handle in self.parent_family_list:
746 self.parent_family_list.remove(family_handle)
747 return True
748 else:
749 return False
750
751 - def set_main_parent_family_handle(self, family_handle):
752 """
753 Set the main L{Family} in which the Person is a child.
754
755 The main L{Family} is the L{Family} typically used for reports and
756 navigation. This is accomplished by moving the L{Family} to the
757 beginning of the list. The family_handle must be in the list for this
758 to have any effect.
759
760 @param family_handle: handle of the L{Family} to be marked
761 as the main L{Family}
762 @type family_handle: str
763 @return: Returns True if the assignment has successful
764 @rtype: bool
765 """
766 if family_handle in self.parent_family_list:
767 self.parent_family_list.remove(family_handle)
768 self.parent_family_list = [family_handle] + self.parent_family_list
769 return True
770 else:
771 return False
772
774 """
775 Return the handle of the L{Family} considered to be the main L{Family}
776 in which the Person is a child.
777
778 @return: Returns the family_handle if a family_handle exists,
779 If no L{Family} is assigned, None is returned
780 @rtype: str
781 """
782 if len(self.parent_family_list) == 0:
783 return None
784 else:
785 return self.parent_family_list[0]
786
788 """
789 Add the L{PersonRef} to the Person instance's L{PersonRef} list.
790
791 @param person_ref: the L{PersonRef} to be added to the
792 Person's L{PersonRef} list.
793 @type person_ref: PersonRef
794 """
795 if person_ref and not isinstance(person_ref, PersonRef):
796 raise ValueError("Expecting PersonRef instance")
797 self.person_ref_list.append(person_ref)
798
800 """
801 Return the list of L{PersonRef} objects.
802
803 @returns: Returns the list of L{PersonRef} objects.
804 @rtype: list
805 """
806 return self.person_ref_list
807
809 """
810 Set the Person instance's L{PersonRef} list to the passed list.
811
812 @param person_ref_list: List of valid L{PersonRef} objects
813 @type person_ref_list: list
814 """
815 self.person_ref_list = person_ref_list
816