From 5aefd4463fdf1ca14f49c1eee15cba49ce4c9ffa Mon Sep 17 00:00:00 2001 From: Don Allingham Date: Mon, 15 Nov 2004 02:07:21 +0000 Subject: [PATCH] * src/DateParser.py: handle leap year in gregorial validity check * src/MergeData.py: Preserve more data when merging the 1.0.X patch from Julio Sanchez) * src/plugins/ReadGedcom.py: Attach top leve source to the person instead of the primary name (ported from the 1.0.X patch from Julio Sanchez) * src/const.py: Add support for "Number of Children" attribute (GEDCOM NCHI) (ported from the 1.0.X patch from Julio Sanchez) svn: r3728 --- ChangeLog | 10 +++++++++ src/DateParser.py | 54 ++++++++++++++++++++++++++--------------------- src/MergeData.py | 24 +++++++++++++++------ src/ReadGedcom.py | 2 +- src/const.py.in | 2 ++ 5 files changed, 61 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index a0fd76f26..0e0af67e1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2004-11-14 Don Allingham + * src/DateParser.py: handle leap year in gregorial validity check + * src/MergeData.py: Preserve more data when merging + the 1.0.X patch from Julio Sanchez) + * src/plugins/ReadGedcom.py: Attach top leve source to the + person instead of the primary name (ported from the 1.0.X patch + from Julio Sanchez) + * src/const.py: Add support for "Number of Children" attribute + (GEDCOM NCHI) (ported from the 1.0.X patch from Julio Sanchez) + 2004-11-12 Tim Waugh * src/plugins/Ancestors.py (person_name): Handle surname prefix (patch from Julio Sanchez). diff --git a/src/DateParser.py b/src/DateParser.py index f5f2eae9e..1aef6eadd 100644 --- a/src/DateParser.py +++ b/src/DateParser.py @@ -36,6 +36,7 @@ __version__ = "$Revision$" import re import time import locale +import calendar #------------------------------------------------------------------------- # @@ -49,7 +50,8 @@ import Date # Top-level module functions # #------------------------------------------------------------------------- -_max_days = [ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ] +_max_days = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ] +_leap_days = [ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ] def gregorian_valid(date_tuple): day = date_tuple[0] @@ -58,6 +60,9 @@ def gregorian_valid(date_tuple): try: if month > 12: valid = False + elif calendar.isleap(date_tuple[2]): + if day > _leap_days[month-1]: + valid = False elif day > _max_days[month-1]: valid = False except: @@ -82,18 +87,9 @@ class DateParser: # RFC-2822 only uses capitalized English abbreviated names, no locales. _rfc_days = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat') _rfc_mons_to_int = { - 'Jan' : 1, - 'Feb' : 2, - 'Mar' : 3, - 'Apr' : 4, - 'May' : 5, - 'Jun' : 6, - 'Jul' : 7, - 'Aug' : 8, - 'Sep' : 9, - 'Oct' : 10, - 'Nov' : 11, - 'Dec' : 12, + 'Jan' : 1, 'Feb' : 2, 'Mar' : 3, 'Apr' : 4, + 'May' : 5, 'Jun' : 6, 'Jul' : 7, 'Aug' : 8, + 'Sep' : 9, 'Oct' : 10, 'Nov' : 11, 'Dec' : 12, } month_to_int = { @@ -317,9 +313,9 @@ class DateParser: def _parse_greg_julian(self,text): return self._parse_calendar(text,self._text,self._text2, - self.month_to_int) + self.month_to_int,gregorian_valid) - def _parse_calendar(self,text,regex1,regex2,mmap): + def _parse_calendar(self,text,regex1,regex2,mmap,check=None): match = regex1.match(text) if match: groups = match.groups() @@ -336,7 +332,10 @@ class DateParser: d = self._get_int(groups[1]) y = int(groups[3]) s = groups[4] != None - return (d,m,y,s) + value = (d,m,y,s) + if check and not check((d,m,y)): + value = Date.EMPTY + return value match = regex2.match(text) if match: @@ -354,7 +353,11 @@ class DateParser: else: y = int(groups[3]) s = groups[4] != None - return (d,m,y,s) + value = (d,m,y,s) + if check and not check((d,m,y)): + value = DATE.EMPTY + return value + return Date.EMPTY def _parse_subdate(self,text,subparser=None): @@ -363,6 +366,9 @@ class DateParser: """ if subparser == None: subparser = self._parse_greg_julian + check = gregorian_valid + else: + check = None value = subparser(text) if value != Date.EMPTY: @@ -374,7 +380,7 @@ class DateParser: y = self._get_int(groups[0]) m = self._get_int(groups[1]) d = self._get_int(groups[2]) - if gregorian_valid((d,m)): + if gregorian_valid((d,m,y)): return (d,m,y,False) else: return Date.EMPTY @@ -385,7 +391,7 @@ class DateParser: d = self._get_int(groups[2]) m = self._rfc_mons_to_int[groups[3]] y = self._get_int(groups[4]) - if gregorian_valid((d,m)): + if gregorian_valid((d,m,y)): return (d,m,y,False) else: return Date.EMPTY @@ -400,11 +406,11 @@ class DateParser: m = self._get_int(groups[1]) d = self._get_int(groups[3]) y = self._get_int(groups[4]) - if gregorian_valid((d,m)): - return (d,m,y,False) - else: - return Date.EMPTY - + value = (d,m,y,False) + if check and not check((d,m,y)): + value = Date.EMPTY + return value + return Date.EMPTY def set_date(self,date,text): diff --git a/src/MergeData.py b/src/MergeData.py index ea3b7e0ec..f1613684a 100644 --- a/src/MergeData.py +++ b/src/MergeData.py @@ -235,8 +235,8 @@ class MergePeople: for xdata in self.p2.get_alternate_names(): for data in lst: if data.are_equal(xdata): - self.copy_note(xdata,data) - self.copy_sources(xdata,data) + self.copy_note(data,xdata) + self.copy_sources(data,xdata) break else: self.p1.add_alternate_name(xdata) @@ -246,8 +246,8 @@ class MergePeople: for data in lst: if data.get_type() == xdata.get_type() and \ data.getValue() == xdata.get_value(): - self.copy_note(xdata,data) - self.copy_sources(xdata,data) + self.copy_note(data,xdata) + self.copy_sources(data,xdata) break else: self.p1.add_attribute(xdata) @@ -256,12 +256,22 @@ class MergePeople: for xdata in self.p2.get_event_list(): for data in lst: if data.are_equal(xdata): - self.copy_note(xdata,data) - self.copy_sources(xdata,data) + self.copy_note(data,xdata) + self.copy_sources(data,xdata) break else: self.p1.add_event(xdata) + lst = self.p1.get_address_list() + for xdata in self.p2.getAddressList(): + for data in lst: + if data.are_equal(xdata): + self.copy_note(data,xdata) + self.copy_sources(data,xdata) + break + else: + self.p1.addAddress(xdata) + lst = self.p1.get_url_list()[:] for xdata in self.p2.get_url_list(): for data in lst: @@ -345,6 +355,8 @@ class MergePeople: old_note = old_note + "\n\n" self.p1.set_note(old_note + self.p2.get_note()) + self.copy_sources(self.p1,self.p2) + try: self.db.remove_person(self.p2.get_handle()) self.db.personMap[self.p1.get_handle()] = self.p1 diff --git a/src/ReadGedcom.py b/src/ReadGedcom.py index a9140d949..c12162dab 100644 --- a/src/ReadGedcom.py +++ b/src/ReadGedcom.py @@ -985,7 +985,7 @@ class GedcomParser: self.person.add_event_handle(event.get_handle()) elif matches[1] == "SOUR": source_ref = self.handle_source(matches,2) - self.person.get_primary_name().add_source_reference(source_ref) + self.person.add_source_reference(source_ref) elif matches[1] == "REFN": if intRE.match(matches[2]): try: diff --git a/src/const.py.in b/src/const.py.in index 751fec3f5..5caaca744 100644 --- a/src/const.py.in +++ b/src/const.py.in @@ -382,6 +382,7 @@ personalConstantAttributes = { "Description" : "DSCR", "Identification Number" : "IDNO", "National Origin" : "NATI", + "Number of Children" : "NCHI", "Social Security Number": "SSN" } @@ -396,6 +397,7 @@ personal_attributes = TransTable({ "Description" : _("Description"), "Identification Number" : _("Identification Number"), "National Origin" : _("National Origin"), + "Number of Children" : _("Number of Children"), "Social Security Number": _("Social Security Number") })