* src/RelLib.py: Remove file (replaced by the package dir).

* src/RelLib: Add directory.
* src/RelLib/__init__.py, src/RelLib/_helper.py,
src/RelLib/_secondary.py, src/RelLib/Researcher.py,
src/RelLib/GenderStats.py, src/RelLib/Person.py,
src/RelLib/Family.py, src/RelLib/Event.py, src/RelLib/Place.py,
src/RelLib/Source.py, src/RelLib/MediaObject.py,
src/RelLib/Repository.py, src/RelLib/Makefile.am,
src/RelLib/.cvsignore: Add to CVS.
* src/configure.in: Create Makefile in src/RelLib.


svn: r5587
This commit is contained in:
Alex Roitman 2005-12-20 02:38:07 +00:00
parent 835647d309
commit 849e569d45
17 changed files with 5071 additions and 4778 deletions

View File

@ -14,6 +14,17 @@
* src/GrampsBSDDB.py (gramps_upgrade_9): Provide upgrade for the * src/GrampsBSDDB.py (gramps_upgrade_9): Provide upgrade for the
changes in RelLib. changes in RelLib.
* src/RelLib.py: Remove file (replaced by the package dir).
* src/RelLib: Add directory.
* src/RelLib/__init__.py, src/RelLib/_helper.py,
src/RelLib/_secondary.py, src/RelLib/Researcher.py,
src/RelLib/GenderStats.py, src/RelLib/Person.py,
src/RelLib/Family.py, src/RelLib/Event.py, src/RelLib/Place.py,
src/RelLib/Source.py, src/RelLib/MediaObject.py,
src/RelLib/Repository.py, src/RelLib/Makefile.am,
src/RelLib/.cvsignore: Add to CVS.
* src/configure.in: Create Makefile in src/RelLib.
2005-12-19 Richard Taylor <rjt-gramps@thegrindstone.me.uk> 2005-12-19 Richard Taylor <rjt-gramps@thegrindstone.me.uk>
* src/RelLib.py: added get_backlink_handles method to PrimaryObject * src/RelLib.py: added get_backlink_handles method to PrimaryObject
* test/GrampsDbBase_Test.py: factored out common db test methods * test/GrampsDbBase_Test.py: factored out common db test methods

View File

@ -251,6 +251,7 @@ AC_CONFIG_FILES([
Makefile Makefile
src/Makefile src/Makefile
src/const.py src/const.py
src/RelLib/Makefile
src/docgen/Makefile src/docgen/Makefile
src/plugins/Makefile src/plugins/Makefile
src/dates/Makefile src/dates/Makefile

File diff suppressed because it is too large Load Diff

4
src/RelLib/.cvsignore Normal file
View File

@ -0,0 +1,4 @@
Makefile
Makefile.in
*.pyc
*.pyo

367
src/RelLib/Event.py Normal file
View File

@ -0,0 +1,367 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2005 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Event object for GRAMPS
"""
#-------------------------------------------------------------------------
#
# standard python modules
#
#-------------------------------------------------------------------------
from warnings import warn
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from _helper import PrimaryObject,SourceNote,MediaBase,DateBase,PlaceBase
class Event(PrimaryObject,SourceNote,MediaBase,DateBase,PlaceBase):
"""
Introduction
============
The Event record is used to store information about some type of
action that occurred at a particular place at a particular time,
such as a birth, death, or marriage.
"""
UNKNOWN = -1
CUSTOM = 0
MARRIAGE = 1
MARR_SETTL = 2
MARR_LIC = 3
MARR_CONTR = 4
MARR_BANNS = 5
ENGAGEMENT = 6
DIVORCE = 7
DIV_FILING = 8
ANNULMENT = 9
MARR_ALT = 10
ADOPT = 11
BIRTH = 12
DEATH = 13
ADULT_CHRISTEN = 14
BAPTISM = 15
BAR_MITZVAH = 16
BAS_MITZVAH = 17
BLESS = 18
BURIAL = 19
CAUSE_DEATH = 20
CENSUS = 21
CHRISTEN = 22
CONFIRMATION = 23
CREMATION = 24
DEGREE = 25
EDUCATION = 26
ELECTED = 27
EMIGRATION = 28
FIRST_COMMUN = 29
IMMIGRATION = 30
GRADUATION = 31
MED_INFO = 32
MILITARY_SERV = 33
NATURALIZATION = 34
NOB_TITLE = 35
NUM_MARRIAGES = 36
OCCUPATION = 37
ORDINATION = 38
PROBATE = 39
PROPERTY = 40
RELIGION = 41
RESIDENCE = 42
RETIREMENT = 43
WILL = 44
def __init__(self,source=None):
"""
Creates a new Event instance, copying from the source if present
@param source: An event used to initialize the new event
@type source: Event
"""
PrimaryObject.__init__(self,source)
SourceNote.__init__(self,source)
MediaBase.__init__(self,source)
DateBase.__init__(self,source)
PlaceBase.__init__(self,source)
if source:
self.description = source.description
self.type = source.type
self.cause = source.cause
self.ext_witness_list = source.ext_witness_list
else:
self.description = ""
self.type = (Event.CUSTOM,"")
self.cause = ""
self.ext_witness_list = []
def serialize(self):
"""
Converts the data held in the event to a Python tuple that
represents all the data elements. This method is used to convert
the object into a form that can easily be saved to a database.
These elements may be primative Python types (string, integers),
complex Python types (lists or tuples, or Python objects. If the
target database cannot handle complex types (such as objectes or
lists), the database is responsible for converting the data into
a form that it can use.
@returns: Returns a python tuple containing the data that should
be considered persistent.
@rtype: tuple
"""
return (self.handle, self.gramps_id, self.type, self.date,
self.description, self.place, self.cause, self.private,
self.source_list, self.note, self.media_list, self.change,
self.marker, self.private)
def unserialize(self,data):
"""
Converts the data held in a tuple created by the serialize method
back into the data in an Event structure.
@param data: tuple containing the persistent data associated the
Person object
@type data: tuple
"""
(self.handle, self.gramps_id, self.type, self.date,
self.description, self.place, self.cause, self.private,
self.source_list, self.note, self.media_list, self.change,
self.marker, self.private) = data
def _has_handle_reference(self,classname,handle):
if classname == 'Place':
return self.place == handle
return False
def _remove_handle_references(self,classname,handle_list):
if classname == 'Place' and self.place in handle_list:
self.place = ""
def _replace_handle_reference(self,classname,old_handle,new_handle):
if classname == 'Place' and self.place == old_handle:
self.place = new_handle
def get_text_data_list(self):
"""
Returns the list of all textual attributes of the object.
@return: Returns the list of all textual attributes of the object.
@rtype: list
"""
return [self.description,self.type[1],self.cause,self.gramps_id]
#return [self.description,self.type[1],self.cause,
# self.get_date(),self.gramps_id]
def get_text_data_child_list(self):
"""
Returns the list of child objects that may carry textual data.
@return: Returns the list of child objects that may carry textual data.
@rtype: list
"""
check_list = self.media_list + self.source_list
if self.note:
check_list.append(self.note)
return check_list
def get_sourcref_child_list(self):
"""
Returns the list of child secondary objects that may refer sources.
@return: Returns the list of child secondary child objects that may refer sources.
@rtype: list
"""
return self.media_list
def get_referenced_handles(self):
"""
Returns the list of (classname,handle) tuples for all directly
referenced primary objects.
@return: Returns the list of (classname,handle) tuples for referenced objects.
@rtype: list
"""
ret = []
if self.place:
ret.append(('Place',self.place))
return ret
def get_handle_referents(self):
"""
Returns the list of child objects which may, directly or through
their children, reference primary objects..
@return: Returns the list of objects refereincing primary objects.
@rtype: list
"""
return self.media_list + self.source_list
def is_empty(self):
"""
Returns True if the Event is an empty object (no values set).
@returns: True if the Event is empty
@rtype: bool
"""
date = self.get_date_object()
place = self.get_place_handle()
description = self.description
cause = self.cause
the_type = self.type
return (the_type == (Event.CUSTOM,"") and date.is_empty()
and not place and not description and not cause)
def are_equal(self,other):
"""
Returns True if the passed Event is equivalent to the current Event.
@param other: Event to compare against
@type other: Event
@returns: True if the Events are equal
@rtype: bool
"""
if other == None:
other = Event (None)
if self.type[0] != other.type[0] or \
(self.type[0] == Event.CUSTOM and self.type[1] != other.type[1]) or\
((self.place or other.place) and (self.place != other.place)) or \
self.description != other.description or self.cause != other.cause \
or self.private != other.private or \
(not self.get_date_object().is_equal(other.get_date_object())) or \
len(self.get_source_references()) != len(other.get_source_references()):
return False
index = 0
olist = other.get_source_references()
for a in self.get_source_references():
if not a.are_equal(olist[index]):
return False
index += 1
return True
def set_name(self,name):
warn( "Use set_type instead of set_name", DeprecationWarning, 2)
# INCOMPLETE Wrapper for old API
# remove when transitition done.
if name in range(-1,45):
the_type = (name,'')
else:
the_type = (Event.CUSTOM,name)
self.set_type(the_type)
def get_name(self):
warn( "Use get_type instead of get_name", DeprecationWarning, 2)
# INCOMPLETE Wrapper for old API
# remove when transitition done.
type = self.get_type()
return type[1]
def set_type(self,the_type):
"""
Sets the type of the Event to the passed (int,str) tuple.
@param the_type: Type to assign to the Event
@type the_type: tuple
"""
if not type(the_type) == tuple:
warn( "set_type now takes a tuple", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
if the_type in range(-1,45):
the_type = (the_type,'')
else:
the_type = (Event.CUSTOM,the_type)
self.type = the_type
def get_type(self):
"""
Returns the type of the Event.
@return: Type of the Event
@rtype: tuple
"""
return self.type
def set_cause(self,cause):
"""
Sets the cause of the Event to the passed string. The string
may contain any information.
@param cause: Cause to assign to the Event
@type cause: str
"""
self.cause = cause
def get_cause(self):
"""
Returns the cause of the Event.
@return: Returns the cause of the Event
@rtype: str
"""
return self.cause
def set_description(self,description):
"""
Sets the description of the Event to the passed string. The string
may contain any information.
@param description: Description to assign to the Event
@type description: str
"""
self.description = description
def get_description(self) :
"""
Returns the description of the Event.
@return: Returns the description of the Event
@rtype: str
"""
return self.description
def add_ext_witness(self,witness):
assert type(witness) == tuple
self.ext_witness_list.append(witness)
def remove_ext_witness(self,witness):
assert type(witness) == tuple
if witness in self.ext_witness_list:
self.ext_witness_list.remove(witness)
return True
return False
def get_ext_witness_list(self):
return self.ext_witness_list
def set_ext_witness_list(self,witness_list):
self.ext_witness_list = witness_list

464
src/RelLib/Family.py Normal file
View File

@ -0,0 +1,464 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2005 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Family object for GRAMPS
"""
#-------------------------------------------------------------------------
#
# standard python modules
#
#-------------------------------------------------------------------------
from warnings import warn
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from _helper import PrimaryObject,SourceNote,MediaBase,AttributeBase
from _secondary import EventRef
class Family(PrimaryObject,SourceNote,MediaBase,AttributeBase):
"""
Introduction
============
The Family record is the GRAMPS in-memory representation of the
relationships between people. It contains all the information
related to the relationship.
Usage
=====
Family objects are usually created in one of two ways.
1. Creating a new Family object, which is then initialized and
added to the database.
2. Retrieving an object from the database using the records
handle.
Once a Family object has been modified, it must be committed
to the database using the database object's commit_family function,
or the changes will be lost.
"""
MARRIED = 0
UNMARRIED = 1
CIVIL_UNION = 2
UNKNOWN = 3
CUSTOM = 4
def __init__(self):
"""
Creates a new Family instance. After initialization, most
data items have empty or null values, including the database
handle.
"""
PrimaryObject.__init__(self)
SourceNote.__init__(self)
MediaBase.__init__(self)
AttributeBase.__init__(self)
self.father_handle = None
self.mother_handle = None
self.child_list = []
self.type = (Family.MARRIED,'')
self.event_ref_list = []
self.lds_seal = None
self.complete = 0
def serialize(self):
"""
Converts the data held in the event to a Python tuple that
represents all the data elements. This method is used to convert
the object into a form that can easily be saved to a database.
These elements may be primative Python types (string, integers),
complex Python types (lists or tuples, or Python objects. If the
target database cannot handle complex types (such as objectes or
lists), the database is responsible for converting the data into
a form that it can use.
@returns: Returns a python tuple containing the data that should
be considered persistent.
@rtype: tuple
"""
return (self.handle, self.gramps_id, self.father_handle, self.mother_handle,
self.child_list, self.type, self.event_ref_list,
self.media_list, self.attribute_list, self.lds_seal,
self.complete, self.source_list, self.note,
self.change, self.marker, self.private)
def unserialize(self, data):
"""
Converts the data held in a tuple created by the serialize method
back into the data in a Family structure.
"""
(self.handle, self.gramps_id, self.father_handle, self.mother_handle,
self.child_list, self.type, self.event_ref_list,
self.media_list, self.attribute_list, self.lds_seal,
self.complete, self.source_list, self.note, self.change,
self.marker, self.private) = data
def _has_handle_reference(self,classname,handle):
if classname == 'Event':
return handle in [ref.ref for ref in self.event_ref_list]
elif classname == 'Person':
return handle in self.child_list + [self.father_handle,self.mother_handle]
elif classname == 'Place':
return bool(self.lds_seal) and self.lds_seal.place == handle
return False
def _remove_handle_references(self,classname,handle_list):
if classname == 'Event':
new_list = [ ref for ref in self.event_ref_list \
if ref.ref not in handle_list ]
self.event_ref_list = new_list
elif classname == 'Person':
new_list = [ handle for handle in self.child_list \
if handle not in handle_list ]
self.child_list = new_list
if self.father_handle in handle_list:
self.father_handle = None
if self.mother_handle in handle_list:
self.mother_handle = None
elif classname == 'Place':
if self.lds_seal and self.lds_seal.place in handle_list:
self.lds_seal.place = None
def _replace_handle_reference(self,classname,old_handle,new_handle):
if classname == 'Event':
handle_list = [ref.ref for ref in self.event_ref_list]
while old_handle in handle_list:
ix = handle_list(old_handle)
self.event_ref_list[ix].ref = new_handle
handle_list[ix] = ''
elif classname == 'Person':
while old_handle in self.child_list:
ix = self.child_list.index(old_handle)
self.child_list[ix] = new_handle
if self.father_handle == old_handle:
self.father_handle = new_handle
if self.mother_handle == old_handle:
self.mother_handle = new_handle
elif classname == 'Place':
if self.lds_seal and self.lds_seal.place == old_handle:
self.lds_seal.place = new_handle
def get_text_data_list(self):
"""
Returns the list of all textual attributes of the object.
@return: Returns the list of all textual attributes of the object.
@rtype: list
"""
return [self.gramps_id]
def get_text_data_child_list(self):
"""
Returns the list of child objects that may carry textual data.
@return: Returns the list of child objects that may carry textual data.
@rtype: list
"""
check_list = [self.lds_seal,self.note]
add_list = [item for item in check_list if item]
return self.media_list + self.attribute_list + \
self.source_list + add_list
def get_sourcref_child_list(self):
"""
Returns the list of child secondary objects that may refer sources.
@return: Returns the list of child secondary child objects that may refer sources.
@rtype: list
"""
check_list = self.media_list + self.attribute_list
if self.lds_seal:
check_list.append(self.lds_seal)
return check_list
def get_referenced_handles(self):
"""
Returns the list of (classname,handle) tuples for all directly
referenced primary objects.
@return: Returns the list of (classname,handle) tuples for referenced objects.
@rtype: list
"""
ret = []
ret += [('Event',ref.ref) for ref in self.event_ref_list]
ret += [('Person',handle) for handle in
self.child_list + [self.father_handle,self.mother_handle]
if handle]
return ret
def get_handle_referents(self):
"""
Returns the list of child objects which may, directly or through
their children, reference primary objects..
@return: Returns the list of objects refereincing primary objects.
@rtype: list
"""
return self.get_sourcref_child_list() + self.source_list
def set_complete_flag(self,val):
"""
Sets or clears the complete flag, which is used to indicate that the
Family's data is considered to be complete.
@param val: True indicates the Family object is considered to be
complete
@type val: bool
"""
self.complete = val
def get_complete_flag(self):
"""
Returns the complete flag, which is used to indicate that the
Family's data is considered to be complete.
@return: True indicates that the Family's record is considered to
be complete.
@rtype: bool
"""
return self.complete
def set_lds_sealing(self,lds_ord):
"""
Sets the LDS Sealing ordinance. An ordinance can be removed
by assigning to None.
@param lds_ord: L{LdsOrd} to assign as the LDS Sealing ordinance.
@type lds_ord: L{LdsOrd}
"""
self.lds_seal = lds_ord
def get_lds_sealing(self):
"""
Returns the LDS Sealing ordinance.
@returns: returns the L{LdsOrd} instance assigned as the LDS
Sealing ordinance, or None if no ordinance has been assigned.
@rtype: L{LdsOrd}
"""
return self.lds_seal
def set_relationship(self,relationship_type):
"""
Sets the relationship type between the people identified as the
father and mother in the relationship. The type is a tuple whose
first item is an integer constant and whose second item is
the string. The valid values are:
- C{Family.MARRIED} : indicates a legally recognized married
relationship between two individuals. This may be either
an opposite or a same sex relationship.
- C{Family.UNMARRIED} : indicates a relationship between two
individuals that is not a legally recognized relationship.
- C{Family.CIVIL_UNION} : indicates a legally recongnized,
non-married relationship between two individuals of the
same sex.
- C{Family.UNKNOWN} : indicates that the type of relationship
between the two individuals is not know.
- C{Family.CUSTOM} : indicates that the type of relationship
between the two individuals does not match any of the
other types.
@param relationship_type: (int,str) tuple of the relationship type
between the father and mother of the relationship.
@type relationship_type: tuple
"""
if not type(relationship_type) == tuple:
if relationship_type in [Family.MARRIED,Family.UNMARRIED,
Family.CIVIL_UNION,Family.UNKNOWN,
Family.CUSTOM]:
warn( "set_relationship now takes a tuple",
DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
relationship_type = (relationship_type,'')
else:
assert type(relationship_type) == tuple
self.type = relationship_type
def get_relationship(self):
"""
Returns the relationship type between the people identified as the
father and mother in the relationship.
"""
return self.type
def set_father_handle(self,person_handle):
"""
Sets the database handle for L{Person} that corresponds to
male of the relationship. For a same sex relationship, this
can represent either of people involved in the relationship.
@param person_handle: L{Person} database handle
@type person_handle: str
"""
self.father_handle = person_handle
def get_father_handle(self):
"""
Returns the database handle of the L{Person} identified as
the father of the Family.
@returns: L{Person} database handle
@rtype: str
"""
return self.father_handle
def set_mother_handle(self,person_handle):
"""
Sets the database handle for L{Person} that corresponds to
male of the relationship. For a same sex relationship, this
can represent either of people involved in the relationship.
@param person_handle: L{Person} database handle
@type person_handle: str
"""
self.mother_handle = person_handle
def get_mother_handle(self):
"""
Returns the database handle of the L{Person} identified as
the mother of the Family.
@returns: L{Person} database handle
@rtype: str
"""
return self.mother_handle
def add_child_handle(self,person_handle):
"""
Adds the database handle for L{Person} to the Family's list
of children.
@param person_handle: L{Person} database handle
@type person_handle: str
"""
if person_handle not in self.child_list:
self.child_list.append(person_handle)
def remove_child_handle(self,person_handle):
"""
Removes the database handle for L{Person} to the Family's list
of children if the L{Person} is already in the list.
@param person_handle: L{Person} database handle
@type person_handle: str
@return: True if the handle was removed, False if it was not
in the list.
@rtype: bool
"""
if person_handle in self.child_list:
self.child_list.remove(person_handle)
return True
else:
return False
def get_child_handle_list(self):
"""
Returns the list of L{Person} handles identifying the children
of the Family.
@return: Returns the list of L{Person} handles assocated with
the Family.
@rtype: list
"""
return self.child_list
def set_child_handle_list(self, child_list):
"""
Assigns the passed list to the Family's list children.
@param child_list: List of L{Person} handles to ba associated
as the Family's list of children.
@type child_list: list of L{Person} handles
"""
self.child_list = child_list
def add_event_handle(self,event_handle):
warn( "Use add_event_ref instead of add_event_handle", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
event_ref = EventRef()
event_ref.set_reference_handle(event_handle)
event_ref.set_role((EventRef.PRIMARY,''))
self.add_event_ref(event_ref)
def add_event_ref(self,event_ref):
"""
Adds the L{EventRef} to the Family instance's L{EventRef} list.
This is accomplished by assigning the L{EventRef} for the valid
L{Event}in the current database.
@param event_ref: the L{EventRef} to be added to the
Person's L{EventRef} list.
@type event_ref: EventRef
"""
if event_ref is not None and not isinstance(event_ref,EventRef):
raise ValueError("Expecting EventRef instance")
self.event_ref_list.append(event_ref)
def get_event_list(self) :
warn( "Use get_event_ref_list instead of get_event_list", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
event_handle_list = []
for event_ref in self.get_event_ref_list():
event_handle_list.append( event_ref.get_reference_handle())
return event_handle_list
def get_event_ref_list(self) :
"""
Returns the list of L{EventRef} objects associated with L{Event}
instances.
@returns: Returns the list of L{EventRef} objects associated with
the Family instance.
@rtype: list
"""
return self.event_ref_list
def set_event_list(self,event_list) :
warn( "Use set_event_ref_list instead of set_event_list", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
event_ref_list = []
for event_handle in event_list:
event_ref = EventRef()
event_ref.set_reference_handle(event_handle)
event_ref.set_role((EventRef.PRIMARY,''))
event_ref_list.append( event_ref)
self.set_event_ref_list(event_ref_list)
def set_event_ref_list(self,event_ref_list) :
"""
Sets the Family instance's L{EventRef} list to the passed list.
@param event_ref_list: List of valid L{EventRef} objects
@type event_ref_list: list
"""
self.event_ref_list = event_ref_list

78
src/RelLib/GenderStats.py Normal file
View File

@ -0,0 +1,78 @@
from Person import Person
class GenderStats:
"""
Class for keeping track of statistics related to Given Name vs.
Gender. This allows the tracking of the liklihood of a person's
given name indicating the gender of the person.
"""
def __init__ (self,stats={}):
if stats == None:
self.stats = {}
else:
self.stats = stats
def save_stats(self):
return self.stats
def _get_key (self, person):
name = person.get_primary_name().get_first_name()
return self._get_key_from_name (name)
def _get_key_from_name (self, name):
return name.split (' ')[0].replace ('?', '')
def name_stats (self, name):
if self.stats.has_key (name):
return self.stats[name]
return (0, 0, 0)
def count_person (self, person, db, undo = 0):
if not person:
return
# Let the Person do their own counting later
name = self._get_key (person)
if not name:
return
gender = person.get_gender()
(male, female, unknown) = self.name_stats (name)
if not undo:
increment = 1
else:
increment = -1
if gender == Person.MALE:
male += increment
elif gender == Person.FEMALE:
female += increment
elif gender == Person.UNKNOWN:
unknown += increment
self.stats[name] = (male, female, unknown)
return
def uncount_person (self, person):
return self.count_person (person, None, undo = 1)
def guess_gender (self, name):
name = self._get_key_from_name (name)
if not name or not self.stats.has_key (name):
return Person.UNKNOWN
(male, female, unknown) = self.stats[name]
if unknown == 0:
if male and not female:
return Person.MALE
if female and not male:
return Person.FEMALE
if male > (2 * female):
return Person.MALE
if female > (2 * male):
return Person.FEMALE
return Person.UNKNOWN

29
src/RelLib/Makefile.am Normal file
View File

@ -0,0 +1,29 @@
# This is the src/RelLib level Makefile for Gramps
# We could use GNU make's ':=' syntax for nice wildcard use,
# but that is not necessarily portable.
# If not using GNU make, then list all .py files individually
pkgdatadir = $(datadir)/@PACKAGE@/RelLib
pkgdata_PYTHON = \
__init__.py\
_helper.py\
_secondary.py\
Researcher.py\
GenderStats.py\
Person.py\
Family.py\
Event.py\
Place.py\
Source.py\
MediaObject.py\
Repository.py
pkgpyexecdir = @pkgpyexecdir@/RelLib
pkgpythondir = @pkgpythondir@/RelLib
GRAMPS_PY_MODPATH = "../"
pycheck:
(export PYTHONPATH=$(GRAMPS_PY_MODPATH); \
pychecker $(pkgdata_PYTHON));

178
src/RelLib/MediaObject.py Normal file
View File

@ -0,0 +1,178 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2005 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Media object for GRAMPS
"""
#-------------------------------------------------------------------------
#
# standard python modules
#
#-------------------------------------------------------------------------
import os
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from _helper import PrimaryObject,SourceNote,DateBase,AttributeBase
class MediaObject(PrimaryObject,SourceNote,DateBase,AttributeBase):
"""
Containter for information about an image file, including location,
description and privacy
"""
def __init__(self,source=None):
"""
Initialize a MediaObject. If source is not None, then object
is initialized from values of the source object.
@param source: Object used to initialize the new object
@type source: MediaObject
"""
PrimaryObject.__init__(self,source)
SourceNote.__init__(self,source)
DateBase.__init__(self,source)
AttributeBase.__init__(self,source)
if source:
self.path = source.path
self.mime = source.mime
self.desc = source.desc
self.thumb = source.thumb
else:
self.path = ""
self.mime = ""
self.desc = ""
self.thumb = None
def serialize(self):
"""
Converts the data held in the event to a Python tuple that
represents all the data elements. This method is used to convert
the object into a form that can easily be saved to a database.
These elements may be primative Python types (string, integers),
complex Python types (lists or tuples, or Python objects. If the
target database cannot handle complex types (such as objectes or
lists), the database is responsible for converting the data into
a form that it can use.
@returns: Returns a python tuple containing the data that should
be considered persistent.
@rtype: tuple
"""
return (self.handle, self.gramps_id, self.path, self.mime,
self.desc, self.attribute_list, self.source_list, self.note,
self.change, self.date, self.marker, self.private)
def unserialize(self,data):
"""
Converts the data held in a tuple created by the serialize method
back into the data in an Event structure.
@param data: tuple containing the persistent data associated the object
@type data: tuple
"""
(self.handle, self.gramps_id, self.path, self.mime, self.desc,
self.attribute_list, self.source_list, self.note, self.change,
self.date, self.marker, self.private) = data
def get_text_data_list(self):
"""
Returns the list of all textual attributes of the object.
@return: Returns the list of all textual attributes of the object.
@rtype: list
"""
return [self.path,self.mime,self.desc,self.gramps_id]
#return [self.path,self.mime,self.desc,self.get_date(),self.gramps_id]
def get_text_data_child_list(self):
"""
Returns the list of child objects that may carry textual data.
@return: Returns the list of child objects that may carry textual data.
@rtype: list
"""
check_list = self.attribute_list + self.source_list
if self.note:
check_list.append(self.note)
return check_list
def get_sourcref_child_list(self):
"""
Returns the list of child secondary objects that may refer sources.
@return: Returns the list of child secondary child objects that may refer sources.
@rtype: list
"""
return self.attribute_list
def get_handle_referents(self):
"""
Returns the list of child objects which may, directly or through
their children, reference primary objects..
@return: Returns the list of objects refereincing primary objects.
@rtype: list
"""
return self.attribute_list + self.source_list
def set_mime_type(self,type):
"""
Sets the MIME type associated with the MediaObject
@param type: MIME type to be assigned to the object
@type type: str
"""
self.mime = type
def get_mime_type(self):
"""
Returns the MIME type associated with the MediaObject
@returns: Returns the associated MIME type
@rtype: str
"""
return self.mime
def set_path(self,path):
"""set the file path to the passed path"""
self.path = os.path.normpath(path)
def get_path(self):
"""return the file path"""
return self.path
def set_description(self,text):
"""sets the description of the image"""
self.desc = text
def get_description(self):
"""returns the description of the image"""
return self.desc

828
src/RelLib/Person.py Normal file
View File

@ -0,0 +1,828 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2005 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Person object for GRAMPS
"""
#-------------------------------------------------------------------------
#
# standard python modules
#
#-------------------------------------------------------------------------
from warnings import warn
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from _helper import PrimaryObject,SourceNote,MediaBase,\
AttributeBase,AddressBase,UrlBase
from _secondary import Name,EventRef
class Person(PrimaryObject,SourceNote,
MediaBase,AttributeBase,AddressBase,UrlBase):
"""
Introduction
============
The Person record is the GRAMPS in-memory representation of an
individual person. It contains all the information related to
an individual.
Usage
=====
Person objects are usually created in one of two ways.
1. Creating a new person object, which is then initialized and
added to the database.
2. Retrieving an object from the database using the records
handle.
Once a Person object has been modified, it must be committed
to the database using the database object's commit_person function,
or the changes will be lost.
@sort: serialize, unserialize, get_*, set_*, add_*, remove_*
"""
UNKNOWN = 2
MALE = 1
FEMALE = 0
CHILD_NONE = 0
CHILD_BIRTH = 1
CHILD_ADOPTED = 2
CHILD_STEPCHILD = 3
CHILD_SPONSORED = 4
CHILD_FOSTER = 5
CHILD_UNKNOWN = 6
CHILD_CUSTOM = 7
def __init__(self,data=None):
"""
Creates a new Person instance. After initialization, most
data items have empty or null values, including the database
handle.
"""
if data:
self.unserialize(data)
else:
PrimaryObject.__init__(self)
SourceNote.__init__(self)
MediaBase.__init__(self)
AttributeBase.__init__(self)
AddressBase.__init__(self)
UrlBase.__init__(self)
self.primary_name = Name()
self.event_ref_list = []
self.family_list = []
self.parent_family_list = []
self.nickname = ""
self.alternate_names = []
self.gender = Person.UNKNOWN
self.death_ref = None
self.birth_ref = None
self.lds_bapt = None
self.lds_endow = None
self.lds_seal = None
# We hold a reference to the GrampsDB so that we can maintain
# its genderStats. It doesn't get set here, but from
# GenderStats.count_person.
def serialize(self):
"""
Converts the data held in the Person to a Python tuple that
represents all the data elements. This method is used to convert
the object into a form that can easily be saved to a database.
These elements may be primative Python types (string, integers),
complex Python types (lists or tuples, or Python objects. If the
target database cannot handle complex types (such as objectes or
lists), the database is responsible for converting the data into
a form that it can use.
@returns: Returns a python tuple containing the data that should
be considered persistent.
@rtype: tuple
"""
return (self.handle, self.gramps_id, self.gender,
self.primary_name, self.alternate_names,
unicode(self.nickname), self.death_ref, self.birth_ref,
self.event_ref_list, self.family_list, self.parent_family_list,
self.media_list, self.address_list, self.attribute_list,
self.urls, self.lds_bapt, self.lds_endow, self.lds_seal,
self.source_list, self.note, self.change, self.marker,
self.private)
def unserialize(self,data):
"""
Converts the data held in a tuple created by the serialize method
back into the data in a Person object.
@param data: tuple containing the persistent data associated the
Person object
@type data: tuple
"""
(self.handle, self.gramps_id, self.gender, self.primary_name,
self.alternate_names, self.nickname, self.death_ref,
self.birth_ref, self.event_ref_list, self.family_list,
self.parent_family_list, self.media_list, self.address_list,
self.attribute_list, self.urls, self.lds_bapt, self.lds_endow,
self.lds_seal, self.source_list, self.note, self.change,
self.marker, self.private) = (data + (False,))[0:23]
def _has_handle_reference(self,classname,handle):
if classname == 'Event':
return handle in [ref.ref for ref in
self.event_ref_list + [self.birth_ref,
self.death_ref]
if ref]
elif classname == 'Family':
return handle in self.family_list + \
[item[0] for item in self.parent_family_list ]
elif classname == 'Place':
return handle in [ordinance.place
for ordinance in [self.lds_bapt,self.lds_endow,self.lds_seal]
if ordinance]
return False
def _remove_handle_references(self,classname,handle_list):
if classname == 'Event':
new_list = [ ref for ref in self.event_ref_list \
if ref and ref.ref not in handle_list ]
self.event_ref_list = new_list
if self.death_ref and self.death_ref.ref in handle_list:
self.death_ref = None
if self.birth_ref and self.birth_ref.ref in handle_list:
self.birth_ref = None
elif classname == 'Family':
new_list = [ handle for handle in self.family_list \
if handle not in handle_list ]
self.family_list = new_list
new_list = [ item for item in self.parent_family_list \
if item[0] not in handle_list ]
self.parent_family_list = new_list
elif classname == 'Place':
for ordinance in [self.lds_bapt,self.lds_endow,self.lds_seal]:
if ordinance.place in handle_list:
ordinance.place == None
def _replace_handle_reference(self,classname,old_handle,new_handle):
if classname == 'Event':
handle_list = [ref.ref for ref in self.event_ref_list]
while old_handle in handle_list:
ix = handle_list.index(old_handle)
self.event_ref_list[ix].ref = new_handle
handle_list[ix] = ''
if self.death_ref and self.death_ref.ref == old_handle:
self.death_ref.ref = new_handle
if self.birth_ref and self.birth_ref.ref == old_handle:
self.birth_ref.ref = new_handle
elif classname == 'Family':
while old_handle in self.family_list:
ix = self.family_list.index(old_handle)
self.family_list[ix] = new_handle
new_list = []
for item in self.parent_family_list:
if item[0] == old_handle:
new_list.append((new_handle,item[1],item[2]))
else:
new_list.append(item)
self.parent_family_list = new_list
elif classname == 'Place':
for ordinance in [self.lds_bapt,self.lds_endow,self.lds_seal]:
if ordinance.place == old_handle:
ordinance.place == new_handle
def get_text_data_list(self):
"""
Returns the list of all textual attributes of the object.
@return: Returns the list of all textual attributes of the object.
@rtype: list
"""
return [self.nickname,self.gramps_id]
def get_text_data_child_list(self):
"""
Returns the list of child objects that may carry textual data.
@return: Returns the list of child objects that may carry textual data.
@rtype: list
"""
check_list = [self.lds_bapt,self.lds_endow,self.lds_seal,self.note]
add_list = [item for item in check_list if item]
return [self.primary_name] + self.media_list + \
self.alternate_names + self.address_list + \
self.attribute_list + self.urls + \
self.source_list + self.event_ref_list + add_list
def get_sourcref_child_list(self):
"""
Returns the list of child secondary objects that may refer sources.
@return: Returns the list of child secondary child objects that may refer sources.
@rtype: list
"""
lds_list = [self.lds_bapt,self.lds_endow,self.lds_seal]
lds_check_list = [item for item in lds_list if item]
return [self.primary_name] + self.media_list + \
self.alternate_names + self.address_list + \
self.attribute_list + lds_check_list
def get_referenced_handles(self):
"""
Returns the list of (classname,handle) tuples for all directly
referenced primary objects.
@return: Returns the list of (classname,handle) tuples for referenced objects.
@rtype: list
"""
return [('Family',handle) for handle in self.family_list
+ [item[0] for item in self.parent_family_list]]
def get_handle_referents(self):
"""
Returns the list of child objects which may, directly or through
their children, reference primary objects..
@return: Returns the list of objects refereincing primary objects.
@rtype: list
"""
return self.get_sourcref_child_list() + self.source_list \
+ self.event_ref_list
def set_complete_flag(self,val):
warn( "Use set_marker instead of set_complete_flag", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
if val:
self.marker = (PrimaryObject.MARKER_COMPLETE, "")
else:
self.marker = (PrimaryObject.MARKER_NONE, "")
def get_complete_flag(self):
warn( "Use get_marker instead of get_complete_flag", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
return self.marker[0] == PrimaryObject.MARKER_COMPLETE
def set_primary_name(self,name):
"""
Sets the primary name of the Person to the specified
L{Name} instance
@param name: L{Name} to be assigned to the person
@type name: L{Name}
"""
self.primary_name = name
def get_primary_name(self):
"""
Returns the L{Name} instance marked as the Person's primary name
@return: Returns the primary name
@rtype: L{Name}
"""
return self.primary_name
def get_alternate_names(self):
"""
Returns the list of alternate L{Name} instances
@return: List of L{Name} instances
@rtype: list
"""
return self.alternate_names
def set_alternate_names(self,alt_name_list):
"""
Changes the list of alternate names to the passed list.
@param alt_name_list: List of L{Name} instances
@type alt_name_list: list
"""
self.alternate_names = alt_name_list
def add_alternate_name(self,name):
"""
Adds a L{Name} instance to the list of alternative names
@param name: L{Name} to add to the list
@type name: L{Name}
"""
self.alternate_names.append(name)
def set_nick_name(self,name):
"""
Sets the nickname field for the Person
@param name: Nickname to be assigned
@type name: str
"""
self.nickname = name
def get_nick_name(self) :
"""
Returns the nickname for the Person
@returns: Returns the nickname associated with the Person
@rtype str
"""
return self.nickname
def set_gender(self,gender) :
"""
Sets the gender of the Person.
@param gender: Assigns the Person's gender to one of the
following constants::
Person.MALE
Person.FEMALE
Person.UNKNOWN
@type gender: int
"""
self.gender = gender
def get_gender(self) :
"""
Returns the gender of the Person
@returns: Returns one of the following constants::
Person.MALE
Person.FEMALE
Person.UNKNOWN
@rtype: int
"""
return self.gender
def set_birth_handle(self,event_handle):
warn( "Use set_birth_ref instead of set_birth_handle", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
event_ref = EventRef()
event_ref.set_reference_handle(event_handle)
event_ref.set_role((EventRef.PRIMARY,''))
self.set_birth_ref( event_ref)
def set_birth_ref(self,event_ref):
"""
Assigns the birth event to the Person object. This is accomplished
by assigning the L{EventRef} of the birth event in the current
database.
@param event_ref: the L{EventRef} object associated with
the Person's birth.
@type event_handle: EventRef
"""
if event_ref is not None and not isinstance(event_ref,EventRef):
raise ValueError("Expecting EventRef instance")
self.birth_ref = event_ref
def set_death_handle(self,event_handle):
warn( "Use set_death_ref instead of set_death_handle", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
event_ref = EventRef()
event_ref.set_reference_handle(event_handle)
event_ref.set_role((EventRef.PRIMARY,''))
self.set_death_ref( event_ref)
def set_death_ref(self,event_ref):
"""
Assigns the death event to the Person object. This is accomplished
by assigning the L{EventRef} of the death event in the current
database.
@param event_ref: the L{EventRef} object associated with
the Person's death.
@type event_handle: EventRef
"""
if event_ref is not None and not isinstance(event_ref,EventRef):
raise ValueError("Expecting EventRef instance")
self.death_ref = event_ref
def get_birth_handle(self):
warn( "Use get_birth_ref instead of get_birth_handle", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
event_ref = self.get_birth_ref()
if event_ref:
return event_ref.get_reference_handle()
return ""
def get_birth_ref(self):
"""
Returns the L{EventRef} for Person's birth event. This
should correspond to an L{Event} in the database's L{Event} list.
@returns: Returns the birth L{EventRef} or None if no birth
L{Event} has been assigned.
@rtype: EventRef
"""
return self.birth_ref
def get_death_handle(self):
warn( "Use get_death_ref instead of get_death_handle", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
event_ref = self.get_death_ref()
if event_ref:
return event_ref.get_reference_handle()
return ""
def get_death_ref(self):
"""
Returns the L{EventRef} for the Person's death event. This
should correspond to an L{Event} in the database's L{Event} list.
@returns: Returns the death L{EventRef} or None if no death
L{Event} has been assigned.
@rtype: event_ref
"""
return self.death_ref
def add_event_handle(self,event_handle):
warn( "Use add_event_ref instead of add_event_handle", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
event_ref = EventRef()
event_ref.set_reference_handle(event_handle)
event_ref.set_role((EventRef.PRIMARY,''))
self.add_event_ref( event_ref)
def add_event_ref(self,event_ref):
"""
Adds the L{EventRef} to the Person instance's L{EventRef} list.
This is accomplished by assigning the L{EventRef} of a valid
L{Event} in the current database.
@param event_ref: the L{EventRef} to be added to the
Person's L{EventRef} list.
@type event_ref: EventRef
"""
if event_ref is not None and not isinstance(event_ref,EventRef):
raise ValueError("Expecting EventRef instance")
self.event_ref_list.append(event_ref)
def get_event_list(self):
warn( "Use get_event_ref_list instead of get_event_list", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
event_handle_list = []
for event_ref in self.get_event_ref_list():
event_handle_list.append( event_ref.get_reference_handle())
return event_handle_list
def get_event_ref_list(self):
"""
Returns the list of L{EventRef} objects associated with L{Event}
instances.
@returns: Returns the list of L{EventRef} objects associated with
the Person instance.
@rtype: list
"""
return self.event_ref_list
def set_event_list(self,event_list):
warn( "Use set_event_ref_list instead of set_event_list", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
event_ref_list = []
for event_handle in event_list:
event_ref = EventRef()
event_ref.set_reference_handle(event_handle)
event_ref.set_role((EventRef.PRIMARY,''))
event_ref_list.append( event_ref)
self.set_event_ref_list(event_ref_list)
def set_event_ref_list(self,event_ref_list):
"""
Sets the Person instance's L{EventRef} list to the passed list.
@param event_ref_list: List of valid L{EventRef} objects
@type event_ref_list: list
"""
self.event_ref_list = event_ref_list
def add_family_handle(self,family_handle):
"""
Adds the L{Family} handle to the Person instance's L{Family} list.
This is accomplished by assigning the handle of a valid L{Family}
in the current database.
Adding a L{Family} handle to a Person does not automatically update
the corresponding L{Family}. The developer is responsible to make
sure that when a L{Family} is added to Person, that the Person is
assigned to either the father or mother role in the L{Family}.
@param family_handle: handle of the L{Family} to be added to the
Person's L{Family} list.
@type family_handle: str
"""
self.family_list.append(family_handle)
def set_preferred_family_handle(self,family_handle):
"""
Sets the family_handle specified to be the preferred L{Family}.
The preferred L{Family} is determined by the first L{Family} in the
L{Family} list, and is typically used to indicate the preferred
L{Family} for navigation or reporting.
The family_handle must already be in the list, or the function
call has no effect.
@param family_handle: Handle of the L{Family} to make the preferred
L{Family}.
@type family_handle: str
@returns: True if the call succeeded, False if the family_handle
was not already in the L{Family} list
@rtype: bool
"""
if family_handle in self.family_list:
self.family_list.remove(family_handle)
self.family_list = [family_handle] + self.family_list
return True
else:
return False
def get_family_handle_list(self) :
"""
Returns the list of L{Family} handles in which the person is a
parent or spouse.
@return: Returns the list of handles corresponding to the
L{Family} records with which the person is associated.
@rtype: list
"""
return self.family_list
def set_family_handle_list(self,family_list) :
"""
Assigns the passed list to the Person's list of families in
which it is a parent or spouse.
@param family_list: List of L{Family} handles to ba associated
with the Person
@type family_list: list
"""
self.family_list = family_list
def clear_family_handle_list(self):
"""
Removes all L{Family} handles from the L{Family} list.
"""
self.family_list = []
def remove_family_handle(self,family_handle):
"""
Removes the specified L{Family} handle from the list
of marriages/partnerships. If the handle does not
exist in the list, the operation has no effect.
@param family_handle: L{Family} handle to remove from the list
@type family_handle: str
@return: True if the handle was removed, False if it was not
in the list.
@rtype: bool
"""
if family_handle in self.family_list:
self.family_list.remove(family_handle)
return True
else:
return False
def get_parent_family_handle_list(self):
"""
Returns the list of L{Family} handles in which the person is a
child.
@return: Returns the list of handles corresponding to the
L{Family} records with which the person is a child.
@rtype: list
"""
return self.parent_family_list
def add_parent_family_handle(self,family_handle,mrel,frel):
"""
Adds the L{Family} handle to the Person instance's list of
families in which it is a child. This is accomplished by
assigning the handle of a valid L{Family} in the current database.
Adding a L{Family} handle to a Person does not automatically update
the corresponding L{Family}. The developer is responsible to make
sure that when a L{Family} is added to Person, that the Person is
added to the L{Family} instance's child list.
@param family_handle: handle of the L{Family} to be added to the
Person's L{Family} list.
@type family_handle: str
@param mrel: relationship between the Person and its mother
@type mrel: tuple
@param frel: relationship between the Person and its father
@type frel: tuple
"""
if not type(mrel) == tuple:
if mrel in range(0,8):
warn( "add_parent_family_handle now takes a tuple", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
mrel = (mrel,'')
else:
assert type(mrel) == tuple
if not type(frel) == tuple:
if frel in range(0,8):
warn( "add_parent_family_handle now takes a tuple", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
frel = (frel,'')
else:
assert type(frel) == tuple
self.parent_family_list.append((family_handle,mrel,frel))
def clear_parent_family_handle_list(self):
"""
Removes all L{Family} handles from the parent L{Family} list.
"""
self.parent_family_list = []
def remove_parent_family_handle(self,family_handle):
"""
Removes the specified L{Family} handle from the list of parent
families (families in which the parent is a child). If the
handle does not exist in the list, the operation has no effect.
@param family_handle: L{Family} handle to remove from the list
@type family_handle: str
@return: Returns a tuple of three strings, consisting of the
removed handle, relationship to mother, and relationship
to father. None is returned if the handle is not in the
list.
@rtype: tuple
"""
for f in self.parent_family_list[:]:
if f[0] == family_handle:
self.parent_family_list.remove(f)
return f
else:
return None
def change_parent_family_handle(self,family_handle,mrel,frel):
"""
Changes the relationships of the L{Family} handle in the Person
instance's list of families in which it is a child. The handle
is assumed to already be in the list.
@param family_handle: handle of the L{Family} to be added to the
Person's L{Family} list.
@type family_handle: str
@param mrel: relationship between the Person and its mother
@type mrel: tuple
@param frel: relationship between the Person and its father
@type frel: tuple
"""
index=0
for f in self.parent_family_list[:]:
if f[0] == family_handle:
self.parent_family_list[index] = (family_handle,mrel,frel)
return True
index += 1
return False
def get_parent_family(self,family_handle):
"""
Finds the L{Family} and relationships associated with passed
family_handle.
@param family_handle: L{Family} handle used to search the parent
family list.
@type family_handle: str
@return: Returns a tuple consisting of the L{Family} handle, the
mother relationship, and father relationship
@rtype: tuple
"""
for f in self.parent_family_list:
if f[0] == family_handle:
return f
else:
return None
def set_main_parent_family_handle(self,family_handle):
"""
Sets the main L{Family} in which the Person is a child. The
main L{Family} is the L{Family} typically used for reports and
navigation. This is accomplished by moving the L{Family} to
the beginning of the list. The family_handle must be in
the list for this to have any effect.
@param family_handle: handle of the L{Family} to be marked
as the main L{Family}
@type family_handle: str
@return: Returns True if the assignment has successful
@rtype: bool
"""
f = self.remove_parent_family_handle(family_handle)
if f:
self.parent_family_list = [f] + self.parent_family_list
return True
else:
return False
def get_main_parents_family_handle(self):
"""
Returns the handle of the L{Family} considered to be the main
L{Family} in which the Person is a child.
@return: Returns the family_handle if a family_handle exists,
If no L{Family} is assigned, None is returned
@rtype: str
"""
if len(self.parent_family_list) == 0:
return None
else:
return self.parent_family_list[0][0]
def set_lds_baptism(self,lds_ord):
"""
Sets the LDS Baptism ordinance. An ordinance can be removed
by assigning to None.
@param lds_ord: L{LdsOrd} to assign as the LDS Baptism ordinance.
@type lds_ord: L{LdsOrd}
"""
self.lds_bapt = lds_ord
def get_lds_baptism(self):
"""
Returns the LDS Baptism ordinance.
@returns: returns the L{LdsOrd} instance assigned as the LDS
Baptism ordinance, or None if no ordinance has been assigned.
@rtype: L{LdsOrd}
"""
return self.lds_bapt
def set_lds_endowment(self,lds_ord):
"""
Sets the LDS Endowment ordinance. An ordinance can be removed
by assigning to None.
@param lds_ord: L{LdsOrd} to assign as the LDS Endowment ordinance.
@type lds_ord: L{LdsOrd}
"""
self.lds_endow = lds_ord
def get_lds_endowment(self):
"""
Returns the LDS Endowment ordinance.
@returns: returns the L{LdsOrd} instance assigned as the LDS
Endowment ordinance, or None if no ordinance has been assigned.
@rtype: L{LdsOrd}
"""
return self.lds_endow
def set_lds_sealing(self,lds_ord):
"""
Sets the LDS Sealing ordinance. An ordinance can be removed
by assigning to None.
@param lds_ord: L{LdsOrd} to assign as the LDS Sealing ordinance.
@type lds_ord: L{LdsOrd}
"""
self.lds_seal = lds_ord
def get_lds_sealing(self):
"""
Returns the LDS Sealing ordinance.
@returns: returns the L{LdsOrd} instance assigned as the LDS
Sealing ordinance, or None if no ordinance has been assigned.
@rtype: L{LdsOrd}
"""
return self.lds_seal

271
src/RelLib/Place.py Normal file
View File

@ -0,0 +1,271 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2005 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Place object for GRAMPS
"""
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from _helper import PrimaryObject,SourceNote,MediaBase,UrlBase
from _secondary import Location
class Place(PrimaryObject,SourceNote,MediaBase,UrlBase):
"""
Contains information related to a place, including multiple address
information (since place names can change with time), longitude, latitude,
a collection of images and URLs, a note and a source
"""
def __init__(self,source=None):
"""
Creates a new Place object, copying from the source if present.
@param source: A Place object used to initialize the new Place
@type source: Place
"""
PrimaryObject.__init__(self,source)
SourceNote.__init__(self,source)
MediaBase.__init__(self,source)
UrlBase.__init__(self,source)
if source:
self.long = source.long
self.lat = source.lat
self.title = source.title
self.main_loc = Location(source.main_loc)
self.alt_loc = []
for loc in source.alt_loc:
self.alt_loc = Location(loc)
else:
self.long = ""
self.lat = ""
self.title = ""
self.main_loc = None
self.alt_loc = []
def serialize(self):
"""
Converts the data held in the Place to a Python tuple that
represents all the data elements. This method is used to convert
the object into a form that can easily be saved to a database.
These elements may be primative Python types (string, integers),
complex Python types (lists or tuples, or Python objects. If the
target database cannot handle complex types (such as objectes or
lists), the database is responsible for converting the data into
a form that it can use.
@returns: Returns a python tuple containing the data that should
be considered persistent.
@rtype: tuple
"""
return (self.handle, self.gramps_id, self.title, self.long, self.lat,
self.main_loc, self.alt_loc, self.urls, self.media_list,
self.source_list, self.note, self.change, self.marker,
self.private)
def unserialize(self,data):
"""
Converts the data held in a tuple created by the serialize method
back into the data in a Place object.
@param data: tuple containing the persistent data associated the
Person object
@type data: tuple
"""
(self.handle, self.gramps_id, self.title, self.long, self.lat,
self.main_loc, self.alt_loc, self.urls, self.media_list,
self.source_list, self.note, self.change, self.marker,
self.private) = data
def get_text_data_list(self):
"""
Returns the list of all textual attributes of the object.
@return: Returns the list of all textual attributes of the object.
@rtype: list
"""
return [self.long,self.lat,self.title,self.gramps_id]
def get_text_data_child_list(self):
"""
Returns the list of child objects that may carry textual data.
@return: Returns the list of child objects that may carry textual data.
@rtype: list
"""
check_list = [self.main_loc,self.note]
add_list = [item for item in check_list if item]
return self.media_list + self.source_list + self.alt_loc \
+ self.urls + add_list
def get_sourcref_child_list(self):
"""
Returns the list of child secondary objects that may refer sources.
@return: Returns the list of child secondary child objects that may refer sources.
@rtype: list
"""
return self.media_list
def get_handle_referents(self):
"""
Returns the list of child objects which may, directly or through
their children, reference primary objects..
@return: Returns the list of objects refereincing primary objects.
@rtype: list
"""
return self.media_list + self.source_list
def set_title(self,title):
"""
Sets the descriptive title of the Place object
@param title: descriptive title to assign to the Place
@type title: str
"""
self.title = title
def get_title(self):
"""
Returns the descriptive title of the Place object
@returns: Returns the descriptive title of the Place
@rtype: str
"""
return self.title
def set_longitude(self,longitude):
"""
Sets the longitude of the Place object
@param longitude: longitude to assign to the Place
@type longitude: str
"""
self.long = longitude
def get_longitude(self):
"""
Returns the longitude of the Place object
@returns: Returns the longitude of the Place
@rtype: str
"""
return self.long
def set_latitude(self,latitude):
"""
Sets the latitude of the Place object
@param latitude: latitude to assign to the Place
@type latitude: str
"""
self.lat = latitude
def get_latitude(self):
"""
Returns the latitude of the Place object
@returns: Returns the latitude of the Place
@rtype: str
"""
return self.lat
def get_main_location(self):
"""
Returns the L{Location} object representing the primary information for the
Place instance. If a L{Location} hasn't been assigned yet, an empty one is
created.
@returns: Returns the L{Location} instance representing the primary location
information about the Place
@rtype: L{Location}
"""
if not self.main_loc:
self.main_loc = Location()
return self.main_loc
def set_main_location(self,location):
"""
Assigns the main location information about the Place to the L{Location}
object passed
@param location: L{Location} instance to assign to as the main information for
the Place
@type location: L{Location}
"""
self.main_loc = location
def get_alternate_locations(self):
"""
Returns a list of alternate L{Location} objects the present alternate information
about the current Place. A Place can have more than one L{Location}, since names
and jurisdictions can change over time for the same place.
@returns: Returns the alternate L{Location}s for the Place
@rtype: list of L{Location} objects
"""
return self.alt_loc
def set_alternate_locations(self,location_list):
"""
Replaces the current alternate L{Location} object list with the new one.
@param location_list: The list of L{Location} objects to assign to the Place's
internal list
@type location_list: list of L{Location} objects
"""
self.alt_loc = location_list
def add_alternate_locations(self,location):
"""
Adds a L{Location} object to the alternate location list
@param location: L{Location} instance to add
@type location: L{Location}
"""
if location not in self.alt_loc:
self.alt_loc.append(location)
def get_display_info(self):
"""Gets the display information associated with the object. This includes
the information that is used for display and for sorting. Returns a list
consisting of 13 strings. These are: Place Title, Place ID, Main Location
Parish, Main Location County, Main Location City, Main Location State/Province,
Main Location Country, upper case Place Title, upper case Parish, upper
case city, upper case county, upper case state, upper case country"""
if self.main_loc:
return [self.title,self.gramps_id,self.main_loc.parish,self.main_loc.city,
self.main_loc.county,self.main_loc.state,self.main_loc.country,
self.title.upper(), self.main_loc.parish.upper(),
self.main_loc.city.upper(), self.main_loc.county.upper(),
self.main_loc.state.upper(), self.main_loc.country.upper()]
else:
return [self.title,self.gramps_id,'','','','','',
self.title.upper(), '','','','','']

167
src/RelLib/Repository.py Normal file
View File

@ -0,0 +1,167 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2005 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Repository object for GRAMPS
"""
#-------------------------------------------------------------------------
#
# standard python modules
#
#-------------------------------------------------------------------------
from warnings import warn
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from _helper import PrimaryObject,NoteBase,AddressBase,UrlBase
class Repository(PrimaryObject,NoteBase,AddressBase,UrlBase):
"""A location where collections of Sources are found"""
UNKNOWN = -1
CUSTOM = 0
LIBRARY = 1
CEMETERY = 2
CHURCH = 3
ARCHIVE = 4
ALBUM = 5
WEBSITE = 6
BOOKSTORE = 7
COLLECTION = 8
SAFE = 9
def __init__(self):
"""creates a new Repository instance"""
PrimaryObject.__init__(self)
NoteBase.__init__(self)
AddressBase.__init__(self)
UrlBase.__init__(self)
self.type = (Repository.LIBRARY,"")
self.name = ""
def serialize(self):
return (self.handle, self.gramps_id, self.type, unicode(self.name),
self.note, self.address_list, self.urls,self.marker,
self.private)
def unserialize(self,data):
"""
Converts the data held in a tuple created by the serialize method
back into the data in an Repository structure.
"""
(self.handle, self.gramps_id, self.type, self.name, self.note,
self.address_list, self.urls ,self.marker, self.private) = data
def get_text_data_list(self):
"""
Returns the list of all textual attributes of the object.
@return: Returns the list of all textual attributes of the object.
@rtype: list
"""
return [self.name,self.type[1]]
def get_text_data_child_list(self):
"""
Returns the list of child objects that may carry textual data.
@return: Returns the list of child objects that may carry textual data.
@rtype: list
"""
check_list = self.address_list + self.urls
if self.note:
check_list.append(self.note)
return check_list
def has_source_reference(self,src_handle) :
"""
Returns True if any of the child objects has reference
to this source handle.
@param src_handle: The source handle to be checked.
@type src_handle: str
@return: Returns whether any of it's child objects has reference to this source handle.
@rtype: bool
"""
return False
def remove_source_references(self,src_handle_list):
"""
Removes references to all source handles in the list
in all child objects.
@param src_handle_list: The list of source handles to be removed.
@type src_handle_list: list
"""
pass
def replace_source_references(self,old_handle,new_handle):
"""
Replaces references to source handles in the list
in this object and all child objects.
@param old_handle: The source handle to be replaced.
@type old_handle: str
@param new_handle: The source handle to replace the old one with.
@type new_handle: str
"""
pass
def set_type(self,the_type):
"""
@param type: descriptive type of the Repository
@type type: str
"""
if not type(the_type) == tuple:
warn( "set_type now takes a tuple", DeprecationWarning, 2)
# Wrapper for old API
# remove when transitition done.
if the_type in range(-1,10):
the_type = (the_type,'')
else:
the_type = (Repository.CUSTOM,the_type)
self.type = the_type
def get_type(self):
"""
@returns: the descriptive type of the Repository
@rtype: str
"""
return self.type
def set_name(self,name):
"""
@param name: descriptive name of the Repository
@type name: str
"""
self.name = name
def get_name(self):
"""
@returns: the descriptive name of the Repository
@rtype: str
"""
return self.name

65
src/RelLib/Researcher.py Normal file
View File

@ -0,0 +1,65 @@
class Researcher:
"""Contains the information about the owner of the database"""
def __init__(self):
"""Initializes the Researcher object"""
self.name = ""
self.addr = ""
self.city = ""
self.state = ""
self.country = ""
self.postal = ""
self.phone = ""
self.email = ""
def get_name(self):
"""returns the database owner's name"""
return self.name
def get_address(self):
"""returns the database owner's address"""
return self.addr
def get_city(self):
"""returns the database owner's city"""
return self.city
def get_state(self):
"""returns the database owner's state"""
return self.state
def get_country(self):
"""returns the database owner's country"""
return self.country
def get_postal_code(self):
"""returns the database owner's postal code"""
return self.postal
def get_phone(self):
"""returns the database owner's phone number"""
return self.phone
def get_email(self):
"""returns the database owner's email"""
return self.email
def set(self,name,addr,city,state,country,postal,phone,email):
"""sets the information about the database owner"""
if name:
self.name = name.strip()
if addr:
self.addr = addr.strip()
if city:
self.city = city.strip()
if state:
self.state = state.strip()
if country:
self.country = country.strip()
if postal:
self.postal = postal.strip()
if phone:
self.phone = phone.strip()
if email:
self.email = email.strip()

269
src/RelLib/Source.py Normal file
View File

@ -0,0 +1,269 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2005 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Source object for GRAMPS
"""
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from _helper import PrimaryObject,MediaBase,NoteBase
from _secondary import Note
class Source(PrimaryObject,MediaBase,NoteBase):
"""A record of a source of information"""
def __init__(self):
"""creates a new Source instance"""
PrimaryObject.__init__(self)
MediaBase.__init__(self)
NoteBase.__init__(self)
self.title = ""
self.author = ""
self.pubinfo = ""
self.note = Note()
self.datamap = {}
self.abbrev = ""
self.reporef_list = []
def serialize(self):
return (self.handle, self.gramps_id, unicode(self.title),
unicode(self.author), unicode(self.pubinfo),
self.note, self.media_list, unicode(self.abbrev),
self.change,self.datamap,self.reporef_list, self.marker,
self.private)
def unserialize(self,data):
"""
Converts the data held in a tuple created by the serialize method
back into the data in an Event structure.
"""
(self.handle, self.gramps_id, self.title, self.author,
self.pubinfo, self.note, self.media_list,
self.abbrev, self.change, self.datamap, self.reporef_list,
self.marker, self.private) = data
def get_text_data_list(self):
"""
Returns the list of all textual attributes of the object.
@return: Returns the list of all textual attributes of the object.
@rtype: list
"""
return [self.title,self.author,self.pubinfo,self.abbrev,self.gramps_id]\
+ self.datamap.keys() + self.datamap.values()
def get_text_data_child_list(self):
"""
Returns the list of child objects that may carry textual data.
@return: Returns the list of child objects that may carry textual data.
@rtype: list
"""
check_list = self.media_list + self.reporef_list
if self.note:
check_list.append(self.note)
return check_list
def get_sourcref_child_list(self):
"""
Returns the list of child secondary objects that may refer sources.
@return: Returns the list of child secondary child objects that may refer sources.
@rtype: list
"""
return self.media_list
def get_handle_referents(self):
"""
Returns the list of child objects which may, directly or through
their children, reference primary objects..
@return: Returns the list of objects refereincing primary objects.
@rtype: list
"""
return self.media_list
def has_source_reference(self,src_handle) :
"""
Returns True if any of the child objects has reference
to this source handle.
@param src_handle: The source handle to be checked.
@type src_handle: str
@return: Returns whether any of it's child objects has reference to this source handle.
@rtype: bool
"""
for item in self.get_sourcref_child_list():
if item.has_source_reference(src_handle):
return True
return False
def remove_source_references(self,src_handle_list):
"""
Removes references to all source handles in the list
in all child objects.
@param src_handle_list: The list of source handles to be removed.
@type src_handle_list: list
"""
for item in self.get_sourcref_child_list():
item.remove_source_references(src_handle_list)
def replace_source_references(self,old_handle,new_handle):
"""
Replaces references to source handles in the list
in this object and all child objects.
@param old_handle: The source handle to be replaced.
@type old_handle: str
@param new_handle: The source handle to replace the old one with.
@type new_handle: str
"""
for item in self.get_sourcref_child_list():
item.replace_source_references(old_handle,new_handle)
def get_data_map(self):
"""Returns the data map of attributes for the source"""
return self.datamap
def set_data_map(self,datamap):
"""Sets the data map of attributes for the source"""
self.datamap = datamap
def set_data_item(self,key,value):
"""Sets the particular data item in the attribute data map"""
self.datamap[key] = value
def set_title(self,title):
"""
Sets the descriptive title of the Source object
@param title: descriptive title to assign to the Source
@type title: str
"""
self.title = title
def get_title(self):
"""
Returns the descriptive title of the Place object
@returns: Returns the descriptive title of the Place
@rtype: str
"""
return self.title
def set_author(self,author):
"""sets the author of the Source"""
self.author = author
def get_author(self):
"""returns the author of the Source"""
return self.author
def set_publication_info(self,text):
"""sets the publication information of the Source"""
self.pubinfo = text
def get_publication_info(self):
"""returns the publication information of the Source"""
return self.pubinfo
def set_abbreviation(self,abbrev):
"""sets the title abbreviation of the Source"""
self.abbrev = abbrev
def get_abbreviation(self):
"""returns the title abbreviation of the Source"""
return self.abbrev
def add_repo_reference(self,repo_ref):
"""
Adds a L{RepoRef} instance to the Source's reporef list.
@param repo_ref: L{RepoRef} instance to be added to the object's reporef list.
@type repo_ref: L{RepoRef}
"""
self.reporef_list.append(repo_ref)
def get_reporef_list(self):
"""
Returns the list of L{RepoRef} instances associated with the Source.
@returns: list of L{RepoRef} instances associated with the Source
@rtype: list
"""
return self.reporef_list
def set_reporef_list(self,reporef_list):
"""
Sets the list of L{RepoRef} instances associated with the Source.
It replaces the previous list.
@param reporef_list: list of L{RepoRef} instances to be assigned to the Source.
@type reporef_list: list
"""
self.reporef_list = reporef_list
def has_repo_reference(self,repo_handle):
"""
Returns True if the Source has reference to this Repository handle.
@param repo_handle: The Repository handle to be checked.
@type repo_handle: str
@return: Returns whether the Source has reference to this Repository handle.
@rtype: bool
"""
return repo_handle in [repo_ref.ref for repo_ref in self.reporef_list]
def remove_repo_references(self,repo_handle_list):
"""
Removes references to all Repository handles in the list.
@param repo_handle_list: The list of Repository handles to be removed.
@type repo_handle_list: list
"""
new_reporef_list = [ repo_ref for repo_ref in self.reporef_list \
if repo_ref.ref not in repo_handle_list ]
self.reporef_list = new_reporef_list
def replace_repo_references(self,old_handle,new_handle):
"""
Replaces all references to old Repository handle with the new handle.
@param old_handle: The Repository handle to be replaced.
@type old_handle: str
@param new_handle: The Repository handle to replace the old one with.
@type new_handle: str
"""
refs_list = [ repo_ref.ref for repo_ref in self.reporef_list ]
n_replace = refs_list.count(old_handle)
for ix_replace in xrange(n_replace):
ix = refs_list.index(old_handle)
self.reporef_list[ix].ref = new_handle
refs_list.pop(ix)

37
src/RelLib/__init__.py Normal file
View File

@ -0,0 +1,37 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2005 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""The core library of GRAMPS objects"""
__author__ = "Donald N. Allingham"
__version__ = "$Revision$"
from _secondary import *
from Person import Person
from Family import Family
from Event import Event
from Place import Place
from Source import Source
from MediaObject import MediaObject
from Repository import Repository
from GenderStats import GenderStats
from Researcher import Researcher

1019
src/RelLib/_helper.py Normal file

File diff suppressed because it is too large Load Diff

1283
src/RelLib/_secondary.py Normal file

File diff suppressed because it is too large Load Diff