diff --git a/src/Utils.py b/src/Utils.py index 475181e5b..3c6348a76 100644 --- a/src/Utils.py +++ b/src/Utils.py @@ -56,23 +56,6 @@ from const import TEMP_DIR, USER_HOME, GRAMPS_UUID, IMAGE_DIR from gen.constfunc import mac, win from gen.ggettext import sgettext as _ -#------------------------------------------------------------------------- -# -# Constants from config .ini keys -# -#------------------------------------------------------------------------- -# cache values; use refresh_constants() if they change -try: - from gen.config import config - _MAX_AGE_PROB_ALIVE = config.get('behavior.max-age-prob-alive') - _MAX_SIB_AGE_DIFF = config.get('behavior.max-sib-age-diff') - _AVG_GENERATION_GAP = config.get('behavior.avg-generation-gap') -except ImportError: - # Utils used as module not part of GRAMPS - _MAX_AGE_PROB_ALIVE = 110 - _MAX_SIB_AGE_DIFF = 20 - _AVG_GENERATION_GAP = 20 - #------------------------------------------------------------------------- # # Integer to String mappings for constants @@ -507,447 +490,6 @@ def create_uid(self, handle=None): uid = uuid.uuid4() return uid.hex.upper() -class ProbablyAlive(object): - """ - An object to hold the parameters for considering someone alive. - """ - - def __init__(self, - db, - max_sib_age_diff=None, - max_age_prob_alive=None, - avg_generation_gap=None): - self.db = db - if max_sib_age_diff is None: - max_sib_age_diff = _MAX_SIB_AGE_DIFF - if max_age_prob_alive is None: - max_age_prob_alive = _MAX_AGE_PROB_ALIVE - if avg_generation_gap is None: - avg_generation_gap = _AVG_GENERATION_GAP - self.MAX_SIB_AGE_DIFF = max_sib_age_diff - self.MAX_AGE_PROB_ALIVE = max_age_prob_alive - self.AVG_GENERATION_GAP = avg_generation_gap - - def probably_alive_range(self, person, is_spouse=False): - # FIXME: some of these computed dates need to be a span. For - # example, if a person could be born +/- 20 yrs around - # a date then it should be a span, and yr_offset should - # deal with it as well ("between 1920 and 1930" + 10 = - # "between 1930 and 1940") - if person is None: - return (None, None, "", None) - birth_ref = person.get_birth_ref() - death_ref = person.get_death_ref() - death_date = None - birth_date = None - explain = "" - # If the recorded death year is before current year then - # things are simple. - if death_ref and death_ref.get_role().is_primary(): - if death_ref: - death = self.db.get_event_from_handle(death_ref.ref) - if death and death.get_date_object().get_start_date() != gen.lib.Date.EMPTY: - death_date = death.get_date_object() - - # Look for Cause Of Death, Burial or Cremation events. - # These are fairly good indications that someone's not alive. - if not death_date: - for ev_ref in person.get_primary_event_ref_list(): - if ev_ref: - ev = self.db.get_event_from_handle(ev_ref.ref) - if ev and ev.type.is_death_fallback(): - death_date = ev.get_date_object() - explain = _("death-related evidence") - - # If they were born within X years before current year then - # assume they are alive (we already know they are not dead). - if not birth_date: - if birth_ref and birth_ref.get_role().is_primary(): - birth = self.db.get_event_from_handle(birth_ref.ref) - if birth and birth.get_date_object().get_start_date() != gen.lib.Date.EMPTY: - birth_date = birth.get_date_object() - - # Look for Baptism, etc events. - # These are fairly good indications that someone's birth. - if not birth_date: - for ev_ref in person.get_primary_event_ref_list(): - ev = self.db.get_event_from_handle(ev_ref.ref) - if ev and ev.type.is_birth_fallback(): - birth_date = ev.get_date_object() - explain = _("birth-related evidence") - - if not birth_date and death_date: - # person died more than MAX after current year - birth_date = death_date.copy_offset_ymd(year=-self.MAX_AGE_PROB_ALIVE) - explain = _("death date") - - if not death_date and birth_date: - # person died more than MAX after current year - death_date = birth_date.copy_offset_ymd(year=self.MAX_AGE_PROB_ALIVE) - explain = _("birth date") - - if death_date and birth_date: - return (birth_date, death_date, explain, person) # direct self evidence - - # Neither birth nor death events are available. Try looking - # at siblings. If a sibling was born more than X years past, - # or more than Z future, then probably this person is - # not alive. If the sibling died more than X years - # past, or more than X years future, then probably not alive. - - family_list = person.get_parent_family_handle_list() - for family_handle in family_list: - family = self.db.get_family_from_handle(family_handle) - if family is None: - continue - for child_ref in family.get_child_ref_list(): - child_handle = child_ref.ref - child = self.db.get_person_from_handle(child_handle) - if child is None: - continue - # Go through once looking for direct evidence: - for ev_ref in child.get_primary_event_ref_list(): - ev = self.db.get_event_from_handle(ev_ref.ref) - if ev and ev.type.is_birth(): - dobj = ev.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - # if sibling birth date too far away, then not alive: - year = dobj.get_year() - if year != 0: - # sibling birth date - return (gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF), - gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF + self.MAX_AGE_PROB_ALIVE), - _("sibling birth date"), - child) - elif ev and ev.type.is_death(): - dobj = ev.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - # if sibling death date too far away, then not alive: - year = dobj.get_year() - if year != 0: - # sibling death date - return (gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF - self.MAX_AGE_PROB_ALIVE), - gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF - self.MAX_AGE_PROB_ALIVE - + self.MAX_AGE_PROB_ALIVE), - _("sibling death date"), - child) - # Go through again looking for fallback: - for ev_ref in child.get_primary_event_ref_list(): - ev = self.db.get_event_from_handle(ev_ref.ref) - if ev and ev.type.is_birth_fallback(): - dobj = ev.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - # if sibling birth date too far away, then not alive: - year = dobj.get_year() - if year != 0: - # sibling birth date - return (gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF), - gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF + self.MAX_AGE_PROB_ALIVE), - _("sibling birth-related date"), - child) - elif ev and ev.type.is_death_fallback(): - dobj = ev.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - # if sibling death date too far away, then not alive: - year = dobj.get_year() - if year != 0: - # sibling death date - return (gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF - self.MAX_AGE_PROB_ALIVE), - gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE), - _("sibling death-related date"), - child) - - if not is_spouse: # if you are not in recursion, let's recurse: - for family_handle in person.get_family_handle_list(): - family = self.db.get_family_from_handle(family_handle) - if family: - mother_handle = family.get_mother_handle() - father_handle = family.get_father_handle() - if mother_handle == person.handle and father_handle: - father = self.db.get_person_from_handle(father_handle) - date1, date2, explain, other = self.probably_alive_range(father, is_spouse=True) - if date1 and date2: - return date1, date2, _("a spouse, ") + explain, other - elif father_handle == person.handle and mother_handle: - mother = self.db.get_person_from_handle(mother_handle) - date1, date2, explain, other = self.probably_alive_range(mother, is_spouse=True) - if date1 and date2: - return date1, date2, _("a spouse, ") + explain, other - # Let's check the family events and see if we find something - for ref in family.get_event_ref_list(): - if ref: - event = self.db.get_event_from_handle(ref.ref) - if event: - date = event.get_date_object() - year = date.get_year() - if year != 0: - other = None - if person.handle == mother_handle and father_handle: - other = self.db.get_person_from_handle(father_handle) - elif person.handle == father_handle and mother_handle: - other = self.db.get_person_from_handle(mother_handle) - return (gen.lib.Date().copy_ymd(year - self.AVG_GENERATION_GAP), - gen.lib.Date().copy_ymd(year - self.AVG_GENERATION_GAP + - self.MAX_AGE_PROB_ALIVE), - - _("event with spouse"), other) - - # Try looking for descendants that were born more than a lifespan - # ago. - - def descendants_too_old (person, years): - for family_handle in person.get_family_handle_list(): - family = self.db.get_family_from_handle(family_handle) - if not family: - # can happen with LivingProxyDb(PrivateProxyDb(db)) - continue - for child_ref in family.get_child_ref_list(): - child_handle = child_ref.ref - child = self.db.get_person_from_handle(child_handle) - child_birth_ref = child.get_birth_ref() - if child_birth_ref: - child_birth = self.db.get_event_from_handle(child_birth_ref.ref) - dobj = child_birth.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - d = gen.lib.Date(dobj) - val = d.get_start_date() - val = d.get_year() - years - d.set_year(val) - return (d, d.copy_offset_ymd(self.MAX_AGE_PROB_ALIVE), - _("descendant birth date"), - child) - child_death_ref = child.get_death_ref() - if child_death_ref: - child_death = self.db.get_event_from_handle(child_death_ref.ref) - dobj = child_death.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - return (dobj.copy_offset_ymd(- self.AVG_GENERATION_GAP), - dobj.copy_offset_ymd(- self.AVG_GENERATION_GAP + self.MAX_AGE_PROB_ALIVE), - _("descendant death date"), - child) - date1, date2, explain, other = descendants_too_old (child, years + self.AVG_GENERATION_GAP) - if date1 and date2: - return date1, date2, explain, other - # Check fallback data: - for ev_ref in child.get_primary_event_ref_list(): - ev = self.db.get_event_from_handle(ev_ref.ref) - if ev and ev.type.is_birth_fallback(): - dobj = ev.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - d = gen.lib.Date(dobj) - val = d.get_start_date() - val = d.get_year() - years - d.set_year(val) - return (d, d.copy_offset_ymd(self.MAX_AGE_PROB_ALIVE), - _("descendant birth-related date"), - child) - - elif ev and ev.type.is_death_fallback(): - dobj = ev.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - return (dobj.copy_offset_ymd(- self.AVG_GENERATION_GAP), - dobj.copy_offset_ymd(- self.AVG_GENERATION_GAP + self.MAX_AGE_PROB_ALIVE), - _("descendant death-related date"), - child) - - return (None, None, "", None) - - # If there are descendants that are too old for the person to have - # been alive in the current year then they must be dead. - - date1, date2, explain, other = None, None, "", None - try: - date1, date2, explain, other = descendants_too_old(person, self.AVG_GENERATION_GAP) - except RuntimeError: - raise DatabaseError( - _("Database error: %s is defined as his or her own ancestor") % - name_displayer.display(person)) - - if date1 and date2: - return (date1, date2, explain, other) - - def ancestors_too_old(person, year): - family_handle = person.get_main_parents_family_handle() - if family_handle: - family = self.db.get_family_from_handle(family_handle) - if not family: - # can happen with LivingProxyDb(PrivateProxyDb(db)) - return (None, None, "", None) - father_handle = family.get_father_handle() - if father_handle: - father = self.db.get_person_from_handle(father_handle) - father_birth_ref = father.get_birth_ref() - if father_birth_ref and father_birth_ref.get_role().is_primary(): - father_birth = self.db.get_event_from_handle( - father_birth_ref.ref) - dobj = father_birth.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - return (dobj.copy_offset_ymd(- year), - dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE), - _("ancestor birth date"), - father) - father_death_ref = father.get_death_ref() - if father_death_ref and father_death_ref.get_role().is_primary(): - father_death = self.db.get_event_from_handle( - father_death_ref.ref) - dobj = father_death.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - return (dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE), - dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE), - _("ancestor death date"), - father) - - # Check fallback data: - for ev_ref in father.get_primary_event_ref_list(): - ev = self.db.get_event_from_handle(ev_ref.ref) - if ev and ev.type.is_birth_fallback(): - dobj = ev.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - return (dobj.copy_offset_ymd(- year), - dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE), - _("ancestor birth-related date"), - father) - - elif ev and ev.type.is_death_fallback(): - dobj = ev.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - return (dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE), - dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE), - _("ancestor death-related date"), - father) - - date1, date2, explain, other = ancestors_too_old (father, year - self.AVG_GENERATION_GAP) - if date1 and date2: - return date1, date2, explain, other - - mother_handle = family.get_mother_handle() - if mother_handle: - mother = self.db.get_person_from_handle(mother_handle) - mother_birth_ref = mother.get_birth_ref() - if mother_birth_ref and mother_birth_ref.get_role().is_primary(): - mother_birth = self.db.get_event_from_handle(mother_birth_ref.ref) - dobj = mother_birth.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - return (dobj.copy_offset_ymd(- year), - dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE), - _("ancestor birth date"), - mother) - mother_death_ref = mother.get_death_ref() - if mother_death_ref and mother_death_ref.get_role().is_primary(): - mother_death = self.db.get_event_from_handle( - mother_death_ref.ref) - dobj = mother_death.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - return (dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE), - dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE), - _("ancestor death date"), - mother) - - # Check fallback data: - for ev_ref in mother.get_primary_event_ref_list(): - ev = self.db.get_event_from_handle(ev_ref.ref) - if ev and ev.type.is_birth_fallback(): - dobj = ev.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - return (dobj.copy_offset_ymd(- year), - dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE), - _("ancestor birth-related date"), - mother) - - elif ev and ev.type.is_death_fallback(): - dobj = ev.get_date_object() - if dobj.get_start_date() != gen.lib.Date.EMPTY: - return (dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE), - dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE), - _("ancestor death-related date"), - mother) - - date1, date2, explain, other = ancestors_too_old (mother, year - self.AVG_GENERATION_GAP) - if date1 and date2: - return (date1, date2, explain, other) - - return (None, None, "", None) - - # If there are ancestors that would be too old in the current year - # then assume our person must be dead too. - date1, date2, explain, other = ancestors_too_old (person, - self.AVG_GENERATION_GAP) - if date1 and date2: - return (date1, date2, explain, other) - - # If we can't find any reason to believe that they are dead we - # must assume they are alive. - - return (None, None, "", None) - -#------------------------------------------------------------------------- -# -# probably_alive -# -#------------------------------------------------------------------------- -def probably_alive(person, db, - current_date=None, - limit=0, - max_sib_age_diff=None, - max_age_prob_alive=None, - avg_generation_gap=None, - return_range=False): - """ - Return true if the person may be alive on current_date. - - This works by a process of elimination. If we can't find a good - reason to believe that someone is dead then we assume they must - be alive. - - :param current_date: a date object that is not estimated or modified - (defaults to today) - :param limit: number of years to check beyond death_date - :param max_sib_age_diff: maximum sibling age difference, in years - :param max_age_prob_alive: maximum age of a person, in years - :param avg_generation_gap: average generation gap, in years - """ - # First, get the real database to use all people - # for determining alive status: - basedb = db.basedb - # Now, we create a wrapper for doing work: - pb = ProbablyAlive(basedb, max_sib_age_diff, - max_age_prob_alive, - avg_generation_gap) - birth, death, explain, relative = pb.probably_alive_range(person) - if current_date is None: - current_date = gen.lib.date.Today() - if not birth or not death: - # no evidence, must consider alive - return (True, None, None, _("no evidence"), None) - # must have dates from here: - if limit: - death += limit # add these years to death - # Finally, check to see if current_date is between dates - result = (current_date.match(birth, ">=") and - current_date.match(death, "<=")) - if return_range: - return (result, birth, death, explain, relative) - else: - return result - -def probably_alive_range(person, db, - max_sib_age_diff=None, - max_age_prob_alive=None, - avg_generation_gap=None): - """ - Computes estimated birth and death dates. - Returns: (birth_date, death_date, explain_text, related_person) - """ - # First, find the real database to use all people - # for determining alive status: - from gen.proxy.proxybase import ProxyDbBase - basedb = db - while isinstance(basedb, ProxyDbBase): - basedb = basedb.db - # Now, we create a wrapper for doing work: - pb = ProbablyAlive(basedb, max_sib_age_diff, - max_age_prob_alive, avg_generation_gap) - return pb.probably_alive_range(person) - #------------------------------------------------------------------------- # # Other util functions @@ -1353,16 +895,6 @@ def get_researcher(): return owner -def update_constants(): - """ - Used to update the constants that are cached in this module. - """ - from gen.config import config - global _MAX_AGE_PROB_ALIVE, _MAX_SIB_AGE_DIFF, _AVG_GENERATION_GAP - _MAX_AGE_PROB_ALIVE = config.get('behavior.max-age-prob-alive') - _MAX_SIB_AGE_DIFF = config.get('behavior.max-sib-age-diff') - _AVG_GENERATION_GAP = config.get('behavior.avg-generation-gap') - #------------------------------------------------------------------------- # # Function to return the name of the main participant of an event diff --git a/src/gen/filters/rules/person/_probablyalive.py b/src/gen/filters/rules/person/_probablyalive.py index 1e7e14158..52b0b8521 100644 --- a/src/gen/filters/rules/person/_probablyalive.py +++ b/src/gen/filters/rules/person/_probablyalive.py @@ -32,7 +32,7 @@ from gen.ggettext import gettext as _ # GRAMPS modules # #------------------------------------------------------------------------- -from Utils import probably_alive +from gen.utils.alive import probably_alive from gen.filters.rules import Rule import gen.datehandler diff --git a/src/gen/proxy/living.py b/src/gen/proxy/living.py index 25eedb85f..a1a7143d8 100644 --- a/src/gen/proxy/living.py +++ b/src/gen/proxy/living.py @@ -38,7 +38,7 @@ from itertools import ifilter #------------------------------------------------------------------------- from proxybase import ProxyDbBase from gen.lib import Date, Person, Name, Surname -from Utils import probably_alive +from gen.utils.alive import probably_alive from gen.config import config #------------------------------------------------------------------------- diff --git a/src/gen/utils/Makefile.am b/src/gen/utils/Makefile.am index 127b6a82f..61fe573c7 100644 --- a/src/gen/utils/Makefile.am +++ b/src/gen/utils/Makefile.am @@ -8,6 +8,7 @@ pkgpythondir = $(datadir)/@PACKAGE@/gen/utils pkgpython_PYTHON = \ __init__.py \ + alive.py \ callback.py \ callman.py \ configmanager.py \ diff --git a/src/gen/utils/alive.py b/src/gen/utils/alive.py new file mode 100644 index 000000000..983a30b2f --- /dev/null +++ b/src/gen/utils/alive.py @@ -0,0 +1,519 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2000-2007 Donald N. Allingham +# Copyright (C) 2009 Gary Burton +# Copyright (C) 2011 Tim G L Lyons +# +# 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$ + +""" +A utility to make a best guess if a person is alive. This is used to provide +privacy in reports and exports. +""" + +#------------------------------------------------------------------------- +# +# Standard python modules +# +#------------------------------------------------------------------------- +import logging +LOG = logging.getLogger(".gen.utils.alive") + +#------------------------------------------------------------------------- +# +# Gramps modules +# +#------------------------------------------------------------------------- +from gen.display.name import displayer as name_displayer +import gen.lib +from gen.errors import DatabaseError +from gen.ggettext import sgettext as _ + +#------------------------------------------------------------------------- +# +# Constants from config .ini keys +# +#------------------------------------------------------------------------- +# cache values; use refresh_constants() if they change +try: + from gen.config import config + _MAX_AGE_PROB_ALIVE = config.get('behavior.max-age-prob-alive') + _MAX_SIB_AGE_DIFF = config.get('behavior.max-sib-age-diff') + _AVG_GENERATION_GAP = config.get('behavior.avg-generation-gap') +except ImportError: + # Utils used as module not part of GRAMPS + _MAX_AGE_PROB_ALIVE = 110 + _MAX_SIB_AGE_DIFF = 20 + _AVG_GENERATION_GAP = 20 + +#------------------------------------------------------------------------- +# +# ProbablyAlive class +# +#------------------------------------------------------------------------- +class ProbablyAlive(object): + """ + An object to hold the parameters for considering someone alive. + """ + + def __init__(self, + db, + max_sib_age_diff=None, + max_age_prob_alive=None, + avg_generation_gap=None): + self.db = db + if max_sib_age_diff is None: + max_sib_age_diff = _MAX_SIB_AGE_DIFF + if max_age_prob_alive is None: + max_age_prob_alive = _MAX_AGE_PROB_ALIVE + if avg_generation_gap is None: + avg_generation_gap = _AVG_GENERATION_GAP + self.MAX_SIB_AGE_DIFF = max_sib_age_diff + self.MAX_AGE_PROB_ALIVE = max_age_prob_alive + self.AVG_GENERATION_GAP = avg_generation_gap + + def probably_alive_range(self, person, is_spouse=False): + # FIXME: some of these computed dates need to be a span. For + # example, if a person could be born +/- 20 yrs around + # a date then it should be a span, and yr_offset should + # deal with it as well ("between 1920 and 1930" + 10 = + # "between 1930 and 1940") + if person is None: + return (None, None, "", None) + birth_ref = person.get_birth_ref() + death_ref = person.get_death_ref() + death_date = None + birth_date = None + explain = "" + # If the recorded death year is before current year then + # things are simple. + if death_ref and death_ref.get_role().is_primary(): + if death_ref: + death = self.db.get_event_from_handle(death_ref.ref) + if death and death.get_date_object().get_start_date() != gen.lib.Date.EMPTY: + death_date = death.get_date_object() + + # Look for Cause Of Death, Burial or Cremation events. + # These are fairly good indications that someone's not alive. + if not death_date: + for ev_ref in person.get_primary_event_ref_list(): + if ev_ref: + ev = self.db.get_event_from_handle(ev_ref.ref) + if ev and ev.type.is_death_fallback(): + death_date = ev.get_date_object() + explain = _("death-related evidence") + + # If they were born within X years before current year then + # assume they are alive (we already know they are not dead). + if not birth_date: + if birth_ref and birth_ref.get_role().is_primary(): + birth = self.db.get_event_from_handle(birth_ref.ref) + if birth and birth.get_date_object().get_start_date() != gen.lib.Date.EMPTY: + birth_date = birth.get_date_object() + + # Look for Baptism, etc events. + # These are fairly good indications that someone's birth. + if not birth_date: + for ev_ref in person.get_primary_event_ref_list(): + ev = self.db.get_event_from_handle(ev_ref.ref) + if ev and ev.type.is_birth_fallback(): + birth_date = ev.get_date_object() + explain = _("birth-related evidence") + + if not birth_date and death_date: + # person died more than MAX after current year + birth_date = death_date.copy_offset_ymd(year=-self.MAX_AGE_PROB_ALIVE) + explain = _("death date") + + if not death_date and birth_date: + # person died more than MAX after current year + death_date = birth_date.copy_offset_ymd(year=self.MAX_AGE_PROB_ALIVE) + explain = _("birth date") + + if death_date and birth_date: + return (birth_date, death_date, explain, person) # direct self evidence + + # Neither birth nor death events are available. Try looking + # at siblings. If a sibling was born more than X years past, + # or more than Z future, then probably this person is + # not alive. If the sibling died more than X years + # past, or more than X years future, then probably not alive. + + family_list = person.get_parent_family_handle_list() + for family_handle in family_list: + family = self.db.get_family_from_handle(family_handle) + if family is None: + continue + for child_ref in family.get_child_ref_list(): + child_handle = child_ref.ref + child = self.db.get_person_from_handle(child_handle) + if child is None: + continue + # Go through once looking for direct evidence: + for ev_ref in child.get_primary_event_ref_list(): + ev = self.db.get_event_from_handle(ev_ref.ref) + if ev and ev.type.is_birth(): + dobj = ev.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + # if sibling birth date too far away, then not alive: + year = dobj.get_year() + if year != 0: + # sibling birth date + return (gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF), + gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF + self.MAX_AGE_PROB_ALIVE), + _("sibling birth date"), + child) + elif ev and ev.type.is_death(): + dobj = ev.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + # if sibling death date too far away, then not alive: + year = dobj.get_year() + if year != 0: + # sibling death date + return (gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF - self.MAX_AGE_PROB_ALIVE), + gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF - self.MAX_AGE_PROB_ALIVE + + self.MAX_AGE_PROB_ALIVE), + _("sibling death date"), + child) + # Go through again looking for fallback: + for ev_ref in child.get_primary_event_ref_list(): + ev = self.db.get_event_from_handle(ev_ref.ref) + if ev and ev.type.is_birth_fallback(): + dobj = ev.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + # if sibling birth date too far away, then not alive: + year = dobj.get_year() + if year != 0: + # sibling birth date + return (gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF), + gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF + self.MAX_AGE_PROB_ALIVE), + _("sibling birth-related date"), + child) + elif ev and ev.type.is_death_fallback(): + dobj = ev.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + # if sibling death date too far away, then not alive: + year = dobj.get_year() + if year != 0: + # sibling death date + return (gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF - self.MAX_AGE_PROB_ALIVE), + gen.lib.Date().copy_ymd(year - self.MAX_SIB_AGE_DIFF - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE), + _("sibling death-related date"), + child) + + if not is_spouse: # if you are not in recursion, let's recurse: + for family_handle in person.get_family_handle_list(): + family = self.db.get_family_from_handle(family_handle) + if family: + mother_handle = family.get_mother_handle() + father_handle = family.get_father_handle() + if mother_handle == person.handle and father_handle: + father = self.db.get_person_from_handle(father_handle) + date1, date2, explain, other = self.probably_alive_range(father, is_spouse=True) + if date1 and date2: + return date1, date2, _("a spouse, ") + explain, other + elif father_handle == person.handle and mother_handle: + mother = self.db.get_person_from_handle(mother_handle) + date1, date2, explain, other = self.probably_alive_range(mother, is_spouse=True) + if date1 and date2: + return date1, date2, _("a spouse, ") + explain, other + # Let's check the family events and see if we find something + for ref in family.get_event_ref_list(): + if ref: + event = self.db.get_event_from_handle(ref.ref) + if event: + date = event.get_date_object() + year = date.get_year() + if year != 0: + other = None + if person.handle == mother_handle and father_handle: + other = self.db.get_person_from_handle(father_handle) + elif person.handle == father_handle and mother_handle: + other = self.db.get_person_from_handle(mother_handle) + return (gen.lib.Date().copy_ymd(year - self.AVG_GENERATION_GAP), + gen.lib.Date().copy_ymd(year - self.AVG_GENERATION_GAP + + self.MAX_AGE_PROB_ALIVE), + + _("event with spouse"), other) + + # Try looking for descendants that were born more than a lifespan + # ago. + + def descendants_too_old (person, years): + for family_handle in person.get_family_handle_list(): + family = self.db.get_family_from_handle(family_handle) + if not family: + # can happen with LivingProxyDb(PrivateProxyDb(db)) + continue + for child_ref in family.get_child_ref_list(): + child_handle = child_ref.ref + child = self.db.get_person_from_handle(child_handle) + child_birth_ref = child.get_birth_ref() + if child_birth_ref: + child_birth = self.db.get_event_from_handle(child_birth_ref.ref) + dobj = child_birth.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + d = gen.lib.Date(dobj) + val = d.get_start_date() + val = d.get_year() - years + d.set_year(val) + return (d, d.copy_offset_ymd(self.MAX_AGE_PROB_ALIVE), + _("descendant birth date"), + child) + child_death_ref = child.get_death_ref() + if child_death_ref: + child_death = self.db.get_event_from_handle(child_death_ref.ref) + dobj = child_death.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + return (dobj.copy_offset_ymd(- self.AVG_GENERATION_GAP), + dobj.copy_offset_ymd(- self.AVG_GENERATION_GAP + self.MAX_AGE_PROB_ALIVE), + _("descendant death date"), + child) + date1, date2, explain, other = descendants_too_old (child, years + self.AVG_GENERATION_GAP) + if date1 and date2: + return date1, date2, explain, other + # Check fallback data: + for ev_ref in child.get_primary_event_ref_list(): + ev = self.db.get_event_from_handle(ev_ref.ref) + if ev and ev.type.is_birth_fallback(): + dobj = ev.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + d = gen.lib.Date(dobj) + val = d.get_start_date() + val = d.get_year() - years + d.set_year(val) + return (d, d.copy_offset_ymd(self.MAX_AGE_PROB_ALIVE), + _("descendant birth-related date"), + child) + + elif ev and ev.type.is_death_fallback(): + dobj = ev.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + return (dobj.copy_offset_ymd(- self.AVG_GENERATION_GAP), + dobj.copy_offset_ymd(- self.AVG_GENERATION_GAP + self.MAX_AGE_PROB_ALIVE), + _("descendant death-related date"), + child) + + return (None, None, "", None) + + # If there are descendants that are too old for the person to have + # been alive in the current year then they must be dead. + + date1, date2, explain, other = None, None, "", None + try: + date1, date2, explain, other = descendants_too_old(person, self.AVG_GENERATION_GAP) + except RuntimeError: + raise DatabaseError( + _("Database error: %s is defined as his or her own ancestor") % + name_displayer.display(person)) + + if date1 and date2: + return (date1, date2, explain, other) + + def ancestors_too_old(person, year): + family_handle = person.get_main_parents_family_handle() + if family_handle: + family = self.db.get_family_from_handle(family_handle) + if not family: + # can happen with LivingProxyDb(PrivateProxyDb(db)) + return (None, None, "", None) + father_handle = family.get_father_handle() + if father_handle: + father = self.db.get_person_from_handle(father_handle) + father_birth_ref = father.get_birth_ref() + if father_birth_ref and father_birth_ref.get_role().is_primary(): + father_birth = self.db.get_event_from_handle( + father_birth_ref.ref) + dobj = father_birth.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + return (dobj.copy_offset_ymd(- year), + dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE), + _("ancestor birth date"), + father) + father_death_ref = father.get_death_ref() + if father_death_ref and father_death_ref.get_role().is_primary(): + father_death = self.db.get_event_from_handle( + father_death_ref.ref) + dobj = father_death.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + return (dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE), + dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE), + _("ancestor death date"), + father) + + # Check fallback data: + for ev_ref in father.get_primary_event_ref_list(): + ev = self.db.get_event_from_handle(ev_ref.ref) + if ev and ev.type.is_birth_fallback(): + dobj = ev.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + return (dobj.copy_offset_ymd(- year), + dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE), + _("ancestor birth-related date"), + father) + + elif ev and ev.type.is_death_fallback(): + dobj = ev.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + return (dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE), + dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE), + _("ancestor death-related date"), + father) + + date1, date2, explain, other = ancestors_too_old (father, year - self.AVG_GENERATION_GAP) + if date1 and date2: + return date1, date2, explain, other + + mother_handle = family.get_mother_handle() + if mother_handle: + mother = self.db.get_person_from_handle(mother_handle) + mother_birth_ref = mother.get_birth_ref() + if mother_birth_ref and mother_birth_ref.get_role().is_primary(): + mother_birth = self.db.get_event_from_handle(mother_birth_ref.ref) + dobj = mother_birth.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + return (dobj.copy_offset_ymd(- year), + dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE), + _("ancestor birth date"), + mother) + mother_death_ref = mother.get_death_ref() + if mother_death_ref and mother_death_ref.get_role().is_primary(): + mother_death = self.db.get_event_from_handle( + mother_death_ref.ref) + dobj = mother_death.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + return (dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE), + dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE), + _("ancestor death date"), + mother) + + # Check fallback data: + for ev_ref in mother.get_primary_event_ref_list(): + ev = self.db.get_event_from_handle(ev_ref.ref) + if ev and ev.type.is_birth_fallback(): + dobj = ev.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + return (dobj.copy_offset_ymd(- year), + dobj.copy_offset_ymd(- year + self.MAX_AGE_PROB_ALIVE), + _("ancestor birth-related date"), + mother) + + elif ev and ev.type.is_death_fallback(): + dobj = ev.get_date_object() + if dobj.get_start_date() != gen.lib.Date.EMPTY: + return (dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE), + dobj.copy_offset_ymd(- year - self.MAX_AGE_PROB_ALIVE + self.MAX_AGE_PROB_ALIVE), + _("ancestor death-related date"), + mother) + + date1, date2, explain, other = ancestors_too_old (mother, year - self.AVG_GENERATION_GAP) + if date1 and date2: + return (date1, date2, explain, other) + + return (None, None, "", None) + + # If there are ancestors that would be too old in the current year + # then assume our person must be dead too. + date1, date2, explain, other = ancestors_too_old (person, - self.AVG_GENERATION_GAP) + if date1 and date2: + return (date1, date2, explain, other) + + # If we can't find any reason to believe that they are dead we + # must assume they are alive. + + return (None, None, "", None) + +#------------------------------------------------------------------------- +# +# probably_alive +# +#------------------------------------------------------------------------- +def probably_alive(person, db, + current_date=None, + limit=0, + max_sib_age_diff=None, + max_age_prob_alive=None, + avg_generation_gap=None, + return_range=False): + """ + Return true if the person may be alive on current_date. + + This works by a process of elimination. If we can't find a good + reason to believe that someone is dead then we assume they must + be alive. + + :param current_date: a date object that is not estimated or modified + (defaults to today) + :param limit: number of years to check beyond death_date + :param max_sib_age_diff: maximum sibling age difference, in years + :param max_age_prob_alive: maximum age of a person, in years + :param avg_generation_gap: average generation gap, in years + """ + # First, get the real database to use all people + # for determining alive status: + basedb = db.basedb + # Now, we create a wrapper for doing work: + pb = ProbablyAlive(basedb, max_sib_age_diff, + max_age_prob_alive, + avg_generation_gap) + birth, death, explain, relative = pb.probably_alive_range(person) + if current_date is None: + current_date = gen.lib.date.Today() + if not birth or not death: + # no evidence, must consider alive + return (True, None, None, _("no evidence"), None) + # must have dates from here: + if limit: + death += limit # add these years to death + # Finally, check to see if current_date is between dates + result = (current_date.match(birth, ">=") and + current_date.match(death, "<=")) + if return_range: + return (result, birth, death, explain, relative) + else: + return result + +def probably_alive_range(person, db, + max_sib_age_diff=None, + max_age_prob_alive=None, + avg_generation_gap=None): + """ + Computes estimated birth and death dates. + Returns: (birth_date, death_date, explain_text, related_person) + """ + # First, find the real database to use all people + # for determining alive status: + from gen.proxy.proxybase import ProxyDbBase + basedb = db + while isinstance(basedb, ProxyDbBase): + basedb = basedb.db + # Now, we create a wrapper for doing work: + pb = ProbablyAlive(basedb, max_sib_age_diff, + max_age_prob_alive, avg_generation_gap) + return pb.probably_alive_range(person) + +def update_constants(): + """ + Used to update the constants that are cached in this module. + """ + from gen.config import config + global _MAX_AGE_PROB_ALIVE, _MAX_SIB_AGE_DIFF, _AVG_GENERATION_GAP + _MAX_AGE_PROB_ALIVE = config.get('behavior.max-age-prob-alive') + _MAX_SIB_AGE_DIFF = config.get('behavior.max-sib-age-diff') + _AVG_GENERATION_GAP = config.get('behavior.avg-generation-gap') diff --git a/src/plugins/Records.py b/src/plugins/Records.py index 3ce424cdb..2df56a21c 100644 --- a/src/plugins/Records.py +++ b/src/plugins/Records.py @@ -46,7 +46,7 @@ from gen.plug.menu import (BooleanOption, EnumeratedListOption, from gen.plug.report import Report from gen.plug.report import utils as ReportUtils from gen.plug.report import MenuReportOptions -from Utils import probably_alive +from gen.utils.alive import probably_alive #------------------------------------------------------------------------ # diff --git a/src/plugins/drawreport/Calendar.py b/src/plugins/drawreport/Calendar.py index 8958fd96e..3eab332d4 100644 --- a/src/plugins/drawreport/Calendar.py +++ b/src/plugins/drawreport/Calendar.py @@ -48,7 +48,7 @@ from gen.plug.menu import (BooleanOption, StringOption, NumberOption, from gen.plug.report import Report from gen.plug.report import utils as ReportUtils from gen.plug.report import MenuReportOptions -from Utils import probably_alive +from gen.utils.alive import probably_alive from gen.datehandler import displayer as _dd import gen.locale import gen.lib diff --git a/src/plugins/export/ExportFtree.py b/src/plugins/export/ExportFtree.py index d55860934..bc6819e1f 100644 --- a/src/plugins/export/ExportFtree.py +++ b/src/plugins/export/ExportFtree.py @@ -45,7 +45,7 @@ log = logging.getLogger(".WriteFtree") # GRAMPS modules # #------------------------------------------------------------------------- -import Utils +from gen.utils.alive import probably_alive from gui.plug.export import WriterOptionBox from gui.glade import Glade @@ -156,7 +156,7 @@ class FtreeWriter(object): death = None #if self.restrict: - # alive = Utils.probably_alive(p, self.db) + # alive = probably_alive(p, self.db) #else: # alive = 0 diff --git a/src/plugins/export/ExportGeneWeb.py b/src/plugins/export/ExportGeneWeb.py index 39663fc04..fe9d61516 100644 --- a/src/plugins/export/ExportGeneWeb.py +++ b/src/plugins/export/ExportGeneWeb.py @@ -49,7 +49,7 @@ log = logging.getLogger(".WriteGeneWeb") import gen.lib from gui.plug.export import WriterOptionBox #import const -import Utils +from gen.utils.alive import probably_alive from gui.glade import Glade from gen.config import config @@ -276,7 +276,7 @@ class GeneWebWriter(object): place = self.db.get_place_from_handle(place_handle) b_place = place.get_title() - if Utils.probably_alive(person,self.db): + if probably_alive(person,self.db): d_date = "" else: d_date = "0" @@ -334,7 +334,7 @@ class GeneWebWriter(object): #missing_surname = config.get("preferences.no-surname-text") surname = self.rem_spaces( person.get_primary_name().get_surname()) #firstname = config.get('preferences.private-given-text') - #if not (Utils.probably_alive(person,self.db) and \ + #if not (probably_alive(person,self.db) and \ # self.restrict and self.living): firstname = self.rem_spaces( person.get_primary_name().get_first_name()) if person.get_handle() not in self.person_ids: @@ -346,7 +346,7 @@ class GeneWebWriter(object): #missing_first_name = config.get("preferences.no-given-text") surname = self.rem_spaces( person.get_primary_name().get_surname()) #firstname = config.get('preferences.private-given-text') - #if not (Utils.probably_alive(person,self.db) and \ + #if not (probably_alive(person,self.db) and \ # self.restrict and self.living): firstname = self.rem_spaces( person.get_primary_name().get_first_name()) if person.get_handle() not in self.person_ids: diff --git a/src/plugins/lib/libnarrate.py b/src/plugins/lib/libnarrate.py index 65bc1e29e..6f0e2db08 100644 --- a/src/plugins/lib/libnarrate.py +++ b/src/plugins/lib/libnarrate.py @@ -40,7 +40,7 @@ from gen.lib.eventroletype import EventRoleType from gen.lib.eventtype import EventType from gen.lib.familyreltype import FamilyRelType from gen.display.name import displayer as _nd -import Utils +from gen.utils.alive import probably_alive from gen.plug.report import utils as ReportUtils from libtranslate import Translator @@ -2186,7 +2186,7 @@ class Narrator(object): 'unknown_gender_name' : self.__first_name, } - dead = not Utils.probably_alive(self.__person, self.__db) + dead = not probably_alive(self.__person, self.__db) if not self.__first_name_used: index = _NAME_INDEX_INCLUDE_NAME diff --git a/src/plugins/quickview/AgeOnDate.py b/src/plugins/quickview/AgeOnDate.py index 26c712d5e..62e759859 100644 --- a/src/plugins/quickview/AgeOnDate.py +++ b/src/plugins/quickview/AgeOnDate.py @@ -29,7 +29,7 @@ Display references for any object from gen.simple import SimpleAccess, SimpleDoc from gui.plug.quick import QuickTable -from Utils import probably_alive +from gen.utils.alive import probably_alive from gen.ggettext import gettext as _ import gen.datehandler import gen.lib diff --git a/src/plugins/textreport/BirthdayReport.py b/src/plugins/textreport/BirthdayReport.py index 8919b4322..d053219f3 100644 --- a/src/plugins/textreport/BirthdayReport.py +++ b/src/plugins/textreport/BirthdayReport.py @@ -49,7 +49,7 @@ from gen.plug.menu import (BooleanOption, StringOption, NumberOption, from gen.plug.report import Report from gen.plug.report import utils as ReportUtils from gen.plug.report import MenuReportOptions -from Utils import probably_alive +from gen.utils.alive import probably_alive import gen.locale from gen.datehandler import displayer as _dd diff --git a/src/plugins/view/pedigreeview.py b/src/plugins/view/pedigreeview.py index 3234eeeb2..dda5a553c 100644 --- a/src/plugins/view/pedigreeview.py +++ b/src/plugins/view/pedigreeview.py @@ -51,8 +51,9 @@ import gen.lib from gui.views.navigationview import NavigationView from gui.editors import FilterEditor from gen.display.name import displayer as name_displayer -from Utils import (media_path_full, probably_alive, find_children, - find_parents, find_witnessed_people) +from gen.utils.alive import probably_alive +from Utils import (media_path_full, find_children, find_parents, + find_witnessed_people) from libformatting import FormattingHelper from gui.thumbnails import get_thumbnail_path from gen.errors import WindowActiveError diff --git a/src/plugins/view/relview.py b/src/plugins/view/relview.py index e807bcb75..07e3e1143 100644 --- a/src/plugins/view/relview.py +++ b/src/plugins/view/relview.py @@ -52,7 +52,8 @@ from gui.views.navigationview import NavigationView from gui.editors import EditPerson, EditFamily from gui.editors import FilterEditor from gen.display.name import displayer as name_displayer -from Utils import media_path_full, probably_alive +from Utils import media_path_full +from gen.utils.alive import probably_alive from gui.utils import open_file_with_default_application import gen.datehandler from gui.thumbnails import get_thumbnail_image diff --git a/src/plugins/webreport/NarrativeWeb.py b/src/plugins/webreport/NarrativeWeb.py index 2c29691bd..8d09861e0 100644 --- a/src/plugins/webreport/NarrativeWeb.py +++ b/src/plugins/webreport/NarrativeWeb.py @@ -105,6 +105,7 @@ from libhtml import Html from libhtmlbackend import HtmlBackend, process_spaces from libgedcom import make_gedcom_date +from gen.utils.alive import probably_alive from gen.utils.place import conv_lat_lon from gui.pluginmanager import GuiPluginManager @@ -6119,7 +6120,7 @@ class IndividualPage(BasePage): birth_date = birth.get_date_object() if birth_date and birth_date is not gen.lib.Date.EMPTY: - alive = Utils.probably_alive(self.person, self.dbase_, date.Today() ) + alive = probably_alive(self.person, self.dbase_, date.Today() ) death_date = _find_death_date(self.dbase_, self.person) if not alive and death_date is not None: diff --git a/src/plugins/webreport/WebCal.py b/src/plugins/webreport/WebCal.py index 795b6fc5a..9fdbaf8cf 100644 --- a/src/plugins/webreport/WebCal.py +++ b/src/plugins/webreport/WebCal.py @@ -59,7 +59,8 @@ from gen.plug.menu import BooleanOption, NumberOption, StringOption, \ EnumeratedListOption, FilterOption, PersonOption, \ DestinationOption, NoteOption import gen.locale -from Utils import probably_alive, xml_lang, get_researcher +from Utils import xml_lang, get_researcher +from gen.utils.alive import probably_alive from gen.datehandler import displayer as _dd from gen.display.name import displayer as _nd diff --git a/src/webapp/utils.py b/src/webapp/utils.py index 35161784f..ab0858dcd 100644 --- a/src/webapp/utils.py +++ b/src/webapp/utils.py @@ -57,7 +57,7 @@ from webapp.dbdjango import DbDjango # #------------------------------------------------------------------------ from gen.simple import SimpleTable, SimpleAccess, make_basic_stylesheet -import Utils +from gen.utils.alive import probably_alive as alive from gen.dbstate import DbState from gen.datehandler import displayer, parser from gen.lib.date import Date as GDate, Today @@ -140,7 +140,7 @@ def get_person_from_handle(db, handle): def probably_alive(handle): return False person = db.get_person_from_handle(handle) - return Utils.probably_alive(person, db) + return alive(person, db) def format_number(number, with_grouping=True): # FIXME: should be user's setting