From 70520be80c0ff20178cf8c16715a494338d1132d Mon Sep 17 00:00:00 2001 From: Jan Skarvall Date: Sun, 13 Sep 2020 17:18:06 +0200 Subject: [PATCH] Add support for open spans --- gramps/gen/datehandler/_date_ar.py | 263 +- gramps/gen/datehandler/_date_bg.py | 336 +- gramps/gen/datehandler/_date_ca.py | 209 +- gramps/gen/datehandler/_date_cs.py | 74 +- gramps/gen/datehandler/_date_da.py | 142 +- gramps/gen/datehandler/_date_de.py | 191 +- gramps/gen/datehandler/_date_el.py | 208 +- gramps/gen/datehandler/_date_es.py | 150 +- gramps/gen/datehandler/_date_fi.py | 124 +- gramps/gen/datehandler/_date_fr.py | 352 +- gramps/gen/datehandler/_date_hr.py | 132 +- gramps/gen/datehandler/_date_hu.py | 392 ++- gramps/gen/datehandler/_date_is.py | 183 +- gramps/gen/datehandler/_date_it.py | 218 +- gramps/gen/datehandler/_date_ja.py | 291 +- gramps/gen/datehandler/_date_lt.py | 205 +- gramps/gen/datehandler/_date_nb.py | 147 +- gramps/gen/datehandler/_date_nl.py | 202 +- gramps/gen/datehandler/_date_pl.py | 203 +- gramps/gen/datehandler/_date_pt.py | 219 +- gramps/gen/datehandler/_date_ru.py | 167 +- gramps/gen/datehandler/_date_sk.py | 177 +- gramps/gen/datehandler/_date_sl.py | 108 +- gramps/gen/datehandler/_date_sr.py | 385 ++- gramps/gen/datehandler/_date_sv.py | 118 +- gramps/gen/datehandler/_date_uk.py | 128 +- gramps/gen/datehandler/_date_zh_CN.py | 110 +- gramps/gen/datehandler/_date_zh_TW.py | 108 +- gramps/gen/datehandler/_datedisplay.py | 635 ++-- gramps/gen/datehandler/_dateparser.py | 536 +-- gramps/gen/datehandler/_datestrings.py | 225 +- .../gen/datehandler/test/datehandler_test.py | 225 +- gramps/gen/lib/date.py | 699 ++-- gramps/gen/lib/test/date_test.py | 1106 ++++-- gramps/gui/editors/editdate.py | 199 +- gramps/plugins/export/exportgeneweb.py | 227 +- gramps/plugins/export/exportvcalendar.py | 70 +- gramps/plugins/export/exportvcard.py | 149 +- gramps/plugins/export/exportxml.py | 983 +++--- gramps/plugins/importer/importgeneweb.py | 627 ++-- gramps/plugins/importer/importxml.py | 1839 +++++----- gramps/plugins/lib/libgedcom.py | 3007 ++++++++++------- 42 files changed, 9448 insertions(+), 6621 deletions(-) diff --git a/gramps/gen/datehandler/_date_ar.py b/gramps/gen/datehandler/_date_ar.py index d471b4ecc..df9af008e 100644 --- a/gramps/gen/datehandler/_date_ar.py +++ b/gramps/gen/datehandler/_date_ar.py @@ -23,29 +23,29 @@ Arabic-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler from ..const import ARABIC_COMMA -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Arabic parser class # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserAR(DateParser): """ Convert a text string into a Date object. If the date cannot be @@ -54,117 +54,183 @@ class DateParserAR(DateParser): # modifiers before the date modifier_to_int = { - 'قبل' : Date.MOD_BEFORE, - 'قبل' : Date.MOD_BEFORE, - 'قبل.' : Date.MOD_BEFORE, - 'بعد' : Date.MOD_AFTER, - 'بعد' : Date.MOD_AFTER, - 'بعد.' : Date.MOD_AFTER, - 'حوالي' : Date.MOD_ABOUT, - 'حوالي.' : Date.MOD_ABOUT, - 'حوالي' : Date.MOD_ABOUT, - 'حوالي' : Date.MOD_ABOUT, - 'حوالي.' : Date.MOD_ABOUT, - 'حوالي' : Date.MOD_ABOUT, - } + "قبل": Date.MOD_BEFORE, + "قبل": Date.MOD_BEFORE, + "قبل.": Date.MOD_BEFORE, + "بعد": Date.MOD_AFTER, + "بعد": Date.MOD_AFTER, + "بعد.": Date.MOD_AFTER, + "حوالي": Date.MOD_ABOUT, + "حوالي.": Date.MOD_ABOUT, + "حوالي": Date.MOD_ABOUT, + "حوالي": Date.MOD_ABOUT, + "حوالي.": Date.MOD_ABOUT, + "حوالي": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } islamic_to_int = { - "محرّم" : 1, "محرّم الحرام" : 1, - "صفر" : 2, "ربيع الأول" : 3, - "ربيع 1" : 3, "ربيع الأخير" : 4, - "ربيع الثاني" : 4, "ربيع الثاني" : 4, - "ربيع الثاني" : 4, "ربيع الثاني" : 4, - "ربيع 2" : 4, "جمادى الأولى" : 5, - "جمادى الأول" : 5, "جمادى 1" : 5, - "جمادى الثانية" : 6, "جمادى الأخير" : 6, - "جمادى الثاني" : 6, "جمادى 2" : 5, - "رجب" : 7, "شعبان" : 8, - "شعبان" : 8, "رمضان" : 9, - "رمضان" : 9, "شوال" : 10, - "ذو القعدة" : 11, "ذو القعدة" : 11, - "ذو القعدة" : 11, "ذو الحجة" : 12, - "ذو الحجة" : 12, "ذو الحجة" : 12, - } + "محرّم": 1, + "محرّم الحرام": 1, + "صفر": 2, + "ربيع الأول": 3, + "ربيع 1": 3, + "ربيع الأخير": 4, + "ربيع الثاني": 4, + "ربيع الثاني": 4, + "ربيع الثاني": 4, + "ربيع الثاني": 4, + "ربيع 2": 4, + "جمادى الأولى": 5, + "جمادى الأول": 5, + "جمادى 1": 5, + "جمادى الثانية": 6, + "جمادى الأخير": 6, + "جمادى الثاني": 6, + "جمادى 2": 5, + "رجب": 7, + "شعبان": 8, + "شعبان": 8, + "رمضان": 9, + "رمضان": 9, + "شوال": 10, + "ذو القعدة": 11, + "ذو القعدة": 11, + "ذو القعدة": 11, + "ذو الحجة": 12, + "ذو الحجة": 12, + "ذو الحجة": 12, + } - bce = ["قبل الميلاد", "قبل الميلاد", "قبل الميلاد", "قبل الميلاد", "قبل الميلاد", "قبل الميلاد" ] + bce = [ + "قبل الميلاد", + "قبل الميلاد", + "قبل الميلاد", + "قبل الميلاد", + "قبل الميلاد", + "قبل الميلاد", + ] calendar_to_int = { - 'غريغوري' : Date.CAL_GREGORIAN, - 'غريغوري' : Date.CAL_GREGORIAN, - 'يوليوسي' : Date.CAL_JULIAN, - 'يوليوسي' : Date.CAL_JULIAN, - 'عبري' : Date.CAL_HEBREW, - 'عبري' : Date.CAL_HEBREW, - 'إسلامي' : Date.CAL_ISLAMIC, - 'إسلامي' : Date.CAL_ISLAMIC, - 'فرنسي' : Date.CAL_FRENCH, - 'فرنسي جمهوري': Date.CAL_FRENCH, - 'فرنسي' : Date.CAL_FRENCH, - 'فارسي' : Date.CAL_PERSIAN, - 'فارسي' : Date.CAL_PERSIAN, - 'سويدي' : Date.CAL_SWEDISH, - 'سويدي' : Date.CAL_SWEDISH, - } + "غريغوري": Date.CAL_GREGORIAN, + "غريغوري": Date.CAL_GREGORIAN, + "يوليوسي": Date.CAL_JULIAN, + "يوليوسي": Date.CAL_JULIAN, + "عبري": Date.CAL_HEBREW, + "عبري": Date.CAL_HEBREW, + "إسلامي": Date.CAL_ISLAMIC, + "إسلامي": Date.CAL_ISLAMIC, + "فرنسي": Date.CAL_FRENCH, + "فرنسي جمهوري": Date.CAL_FRENCH, + "فرنسي": Date.CAL_FRENCH, + "فارسي": Date.CAL_PERSIAN, + "فارسي": Date.CAL_PERSIAN, + "سويدي": Date.CAL_SWEDISH, + "سويدي": Date.CAL_SWEDISH, + } quality_to_int = { - 'متوقع' : Date.QUAL_ESTIMATED, - 'متوقع.' : Date.QUAL_ESTIMATED, - 'متوقع' : Date.QUAL_ESTIMATED, - 'محسوب.' : Date.QUAL_CALCULATED, - 'محسوب' : Date.QUAL_CALCULATED, - 'محسوب' : Date.QUAL_CALCULATED, - } + "متوقع": Date.QUAL_ESTIMATED, + "متوقع.": Date.QUAL_ESTIMATED, + "متوقع": Date.QUAL_ESTIMATED, + "محسوب.": Date.QUAL_CALCULATED, + "محسوب": Date.QUAL_CALCULATED, + "محسوب": Date.QUAL_CALCULATED, + } def init_strings(self): """ This method compiles regular expression strings for matching dates. """ DateParser.init_strings(self) - _span_1 = ['من'] - _span_2 = ['إلى'] - _range_1 = ['بين'] - _range_2 = ['و'] + _span_1 = ["من"] + _span_2 = ["إلى"] + _range_1 = ["بين"] + _range_2 = ["و"] self._span = re.compile( - r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_span_1), '|'.join(_span_2)), re.IGNORECASE) + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) self._range = re.compile( - r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_range_1), '|'.join(_range_2)), re.IGNORECASE) + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Arabic display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayAR(DateDisplay): """ Arabic language date display class. """ - # this is used to display the 12 gregorian months - long_months = ( "", "كانون الثاني", "شباط", "آذار", "نيسان", "أيار", - "حزيران", "تموز", "آب", "أيلول", "تشرين الأول", - "تشرين الثاني", "كانون الأول" ) - short_months = ( "", "كانون2", "شباط", "آذار", "نيسان", "أيار", "حزيران", - "تموز", "آب", "أيلول", "تشرين1", "تشرين2", "كانون1" ) + # this is used to display the 12 gregorian months + long_months = ( + "", + "كانون الثاني", + "شباط", + "آذار", + "نيسان", + "أيار", + "حزيران", + "تموز", + "آب", + "أيلول", + "تشرين الأول", + "تشرين الثاني", + "كانون الأول", + ) + + short_months = ( + "", + "كانون2", + "شباط", + "آذار", + "نيسان", + "أيار", + "حزيران", + "تموز", + "آب", + "أيلول", + "تشرين1", + "تشرين2", + "كانون1", + ) islamic = ( - "", "محرّم", "صفر", "ربيع الأول", "ربيع الثاني", - "جمادى الأولى", "جمادى الثانية", "رجب", "شعبان", - "رمضان", "شوال", "ذو القعدة", "ذو الحجة" - ) + "", + "محرّم", + "صفر", + "ربيع الأول", + "ربيع الثاني", + "جمادى الأولى", + "جمادى الثانية", + "رجب", + "شعبان", + "رمضان", + "شوال", + "ذو القعدة", + "ذو الحجة", + ) formats = ( - "YYYY-MM-DD (قياسي)", "عددي", "شهر يوم, سنة", - "شهر يوم, سنة", "يوم شهر سنة", "يوم شهر سنة" - ) - # this must agree with DateDisplayEn's "formats" definition - # (since no locale-specific _display_gregorian exists, here) + "YYYY-MM-DD (قياسي)", + "عددي", + "شهر يوم, سنة", + "شهر يوم, سنة", + "يوم شهر سنة", + "يوم شهر سنة", + ) + # this must agree with DateDisplayEn's "formats" definition + # (since no locale-specific _display_gregorian exists, here) - calendar = ( - "", "يوليوسي", "عبري", "فرنسي", - "فارسي", "إسلامي", "سويدي" - ) + calendar = ("", "يوليوسي", "عبري", "فرنسي", "فارسي", "إسلامي", "سويدي") _mod_str = ("", "قبل ", "بعد ", "حوالي ", "", "", "") @@ -192,12 +258,12 @@ class DateDisplayAR(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'من', d1, 'إلى', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "من", d1, "إلى", d2, scal) elif mod == Date.MOD_RANGE: d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'بين', d1, 'و', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "بين", d1, "و", d2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) @@ -208,27 +274,30 @@ class DateDisplayAR(DateDisplay): numerical -- for Arabic dates """ value = DateDisplay.dd_dformat01(self, date_val) - return value.replace(',', ARABIC_COMMA) + return value.replace(",", ARABIC_COMMA) def dd_dformat02(self, date_val, inflect, long_months): """ month_name day, year -- for Arabic dates """ value = DateDisplay.dd_dformat02(self, date_val, inflect, long_months) - return value.replace(',', ARABIC_COMMA) + return value.replace(",", ARABIC_COMMA) def dd_dformat03(self, date_val, inflect, short_months): """ month_abbreviation day, year -- for Arabic dates """ value = DateDisplay.dd_dformat03(self, date_val, inflect, short_months) - return value.replace(',', ARABIC_COMMA) + return value.replace(",", ARABIC_COMMA) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('ar_EG', 'ar_AR', 'ar', 'Arabic', 'arabic', ('%d %b, %Y',)), - DateParserAR, DateDisplayAR) + ("ar_EG", "ar_AR", "ar", "Arabic", "arabic", ("%d %b, %Y",)), + DateParserAR, + DateDisplayAR, +) diff --git a/gramps/gen/datehandler/_date_bg.py b/gramps/gen/datehandler/_date_bg.py index e9f9ae85e..bd836323c 100644 --- a/gramps/gen/datehandler/_date_bg.py +++ b/gramps/gen/datehandler/_date_bg.py @@ -23,172 +23,202 @@ Bulgarian-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Bulgarian parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserBG(DateParser): modifier_to_int = { - 'преди' : Date.MOD_BEFORE, - 'пр.' : Date.MOD_BEFORE, - 'пр' : Date.MOD_BEFORE, - 'след' : Date.MOD_AFTER, - 'сл.' : Date.MOD_AFTER, - 'сл' : Date.MOD_AFTER, - 'ок' : Date.MOD_ABOUT, - 'ок.' : Date.MOD_ABOUT, - 'около' : Date.MOD_ABOUT, - 'примерно' : Date.MOD_ABOUT, - 'прим' : Date.MOD_ABOUT, - 'прим.' : Date.MOD_ABOUT, - 'приблизително' : Date.MOD_ABOUT, - 'приб.' : Date.MOD_ABOUT, - 'прибл.' : Date.MOD_ABOUT, - 'приб' : Date.MOD_ABOUT, - 'прибл' : Date.MOD_ABOUT, - } + "преди": Date.MOD_BEFORE, + "пр.": Date.MOD_BEFORE, + "пр": Date.MOD_BEFORE, + "след": Date.MOD_AFTER, + "сл.": Date.MOD_AFTER, + "сл": Date.MOD_AFTER, + "ок": Date.MOD_ABOUT, + "ок.": Date.MOD_ABOUT, + "около": Date.MOD_ABOUT, + "примерно": Date.MOD_ABOUT, + "прим": Date.MOD_ABOUT, + "прим.": Date.MOD_ABOUT, + "приблизително": Date.MOD_ABOUT, + "приб.": Date.MOD_ABOUT, + "прибл.": Date.MOD_ABOUT, + "приб": Date.MOD_ABOUT, + "прибл": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } calendar_to_int = { - 'григориански' : Date.CAL_GREGORIAN, - 'г' : Date.CAL_GREGORIAN, - 'юлиански' : Date.CAL_JULIAN, - 'ю' : Date.CAL_JULIAN, - 'еврейски' : Date.CAL_HEBREW, - 'е' : Date.CAL_HEBREW, - 'ислямски' : Date.CAL_ISLAMIC, - 'и' : Date.CAL_ISLAMIC, - 'френски републикански' : Date.CAL_FRENCH, - 'републикански' : Date.CAL_FRENCH, - 'фр.реп.' : Date.CAL_FRENCH, - 'р' : Date.CAL_FRENCH, - 'френски' : Date.CAL_FRENCH, - 'фр.' : Date.CAL_FRENCH, - 'персийски' : Date.CAL_PERSIAN, - 'п' : Date.CAL_PERSIAN, - } + "григориански": Date.CAL_GREGORIAN, + "г": Date.CAL_GREGORIAN, + "юлиански": Date.CAL_JULIAN, + "ю": Date.CAL_JULIAN, + "еврейски": Date.CAL_HEBREW, + "е": Date.CAL_HEBREW, + "ислямски": Date.CAL_ISLAMIC, + "и": Date.CAL_ISLAMIC, + "френски републикански": Date.CAL_FRENCH, + "републикански": Date.CAL_FRENCH, + "фр.реп.": Date.CAL_FRENCH, + "р": Date.CAL_FRENCH, + "френски": Date.CAL_FRENCH, + "фр.": Date.CAL_FRENCH, + "персийски": Date.CAL_PERSIAN, + "п": Date.CAL_PERSIAN, + } quality_to_int = { - 'приблизително' : Date.QUAL_ESTIMATED, - 'прибл.' : Date.QUAL_ESTIMATED, - 'изчислено' : Date.QUAL_CALCULATED, - 'изчисл.' : Date.QUAL_CALCULATED, - 'изч.' : Date.QUAL_CALCULATED, - } + "приблизително": Date.QUAL_ESTIMATED, + "прибл.": Date.QUAL_ESTIMATED, + "изчислено": Date.QUAL_CALCULATED, + "изчисл.": Date.QUAL_CALCULATED, + "изч.": Date.QUAL_CALCULATED, + } hebrew_to_int = { - "тишрей":1, - "мархешван":2, - "кислев":3, - "тевет":4, - "шват":5, - "адар":6, - "адар бет":7, - "нисан":8, - "ияр":9, - "сиван":10, - "тамуз":11, - "ав":12, - "eлул":13, + "тишрей": 1, + "мархешван": 2, + "кислев": 3, + "тевет": 4, + "шват": 5, + "адар": 6, + "адар бет": 7, + "нисан": 8, + "ияр": 9, + "сиван": 10, + "тамуз": 11, + "ав": 12, + "eлул": 13, } islamic_to_int = { - "мухаррам":1, - "саффар":2, - "рабиу-л-ауал":3, - "рабиу-с-сани":4, - "джумадал-уля":5, - "джумада-с-сания":6, - "раджаб":7, - "шаабан":8, - "рамадан":9, - "шауал":10, - "зу-л-кида":11, - "зул-л-хиджа":12, - } + "мухаррам": 1, + "саффар": 2, + "рабиу-л-ауал": 3, + "рабиу-с-сани": 4, + "джумадал-уля": 5, + "джумада-с-сания": 6, + "раджаб": 7, + "шаабан": 8, + "рамадан": 9, + "шауал": 10, + "зу-л-кида": 11, + "зул-л-хиджа": 12, + } persian_to_int = { - "фарвардин":1, - "урдбихищ":2, - "хурдад":3, - "тир":4, - "мурдад":5, - "шахривар":6, - "михр":7, - "абан":8, - "азар":9, - "дай":10, - "бахман":11, - "исфаидармуз":12, - } + "фарвардин": 1, + "урдбихищ": 2, + "хурдад": 3, + "тир": 4, + "мурдад": 5, + "шахривар": 6, + "михр": 7, + "абан": 8, + "азар": 9, + "дай": 10, + "бахман": 11, + "исфаидармуз": 12, + } french_to_int = { - "вандемер":1, - "брюмер":2, - "фример":3, - "нивоз":4, - "плювиоз":5, - "вантоз":6, - "жерминал":7, - "флореал":8, - "прериал":9, - "месидор":10, - "термидор":11, - "фрюктидор":12, - "допълнителен":13, - } + "вандемер": 1, + "брюмер": 2, + "фример": 3, + "нивоз": 4, + "плювиоз": 5, + "вантоз": 6, + "жерминал": 7, + "флореал": 8, + "прериал": 9, + "месидор": 10, + "термидор": 11, + "фрюктидор": 12, + "допълнителен": 13, + } - bce = [ - 'преди Христа', 'пр. Хр.', 'пр.Хр.' - ] + DateParser.bce + bce = ["преди Христа", "пр. Хр.", "пр.Хр."] + DateParser.bce def init_strings(self): DateParser.init_strings(self) - _span_1 = ['от'] - _span_2 = ['до'] - _range_1 = ['между'] - _range_2 = ['и'] + _span_1 = ["от"] + _span_2 = ["до"] + _range_1 = ["между"] + _range_2 = ["и"] self._span = re.compile( - r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_span_1), '|'.join(_span_2)), re.IGNORECASE) + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) self._range = re.compile( - r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_range_1), '|'.join(_range_2)), re.IGNORECASE) + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Bulgarian displayer # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayBG(DateDisplay): """ Bulgarian language date display class. """ - long_months = ( "", "януари", "февруари", "март", "април", "май", - "юни", "юли", "август", "септември", "октомври", - "ноември", "декември" ) - short_months = ( "", "яну", "февр", "март", "апр", "май", "юни", - "юли", "авг", "септ", "окт", "ное", "дек" ) + long_months = ( + "", + "януари", + "февруари", + "март", + "април", + "май", + "юни", + "юли", + "август", + "септември", + "октомври", + "ноември", + "декември", + ) + short_months = ( + "", + "яну", + "февр", + "март", + "апр", + "май", + "юни", + "юли", + "авг", + "септ", + "окт", + "ное", + "дек", + ) calendar = ( "", @@ -197,8 +227,8 @@ class DateDisplayBG(DateDisplay): "републикански", "персийски", "ислямски", - "шведски" - ) + "шведски", + ) _mod_str = ("", "преди ", "след ", "около ", "", "", "") @@ -207,12 +237,18 @@ class DateDisplayBG(DateDisplay): _bce_str = "%s пр. Хр." formats = ( - "ГГГГ-ММ-ДД (ISO)", "Числов", "Месец Ден, Година", "Мес. Ден, Година", "Ден Месец Година", "Ден Мес. Година" - ) - # this must agree with DateDisplayEn's "formats" definition - # (since no locale-specific _display_gregorian exists, here) + "ГГГГ-ММ-ДД (ISO)", + "Числов", + "Месец Ден, Година", + "Мес. Ден, Година", + "Ден Месец Година", + "Ден Мес. Година", + ) + # this must agree with DateDisplayEn's "formats" definition + # (since no locale-specific _display_gregorian exists, here) - hebrew = ( "", + hebrew = ( + "", "Тишрей", "Мархешван", "Кислев", @@ -226,9 +262,10 @@ class DateDisplayBG(DateDisplay): "Тамуз", "Ав", "Елул", - ) + ) - islamic = ( "", + islamic = ( + "", "Мухаррам", "Саффар", "Рабиу-л-ауал", @@ -241,9 +278,10 @@ class DateDisplayBG(DateDisplay): "Шауал", "Зу-л-кида", "Зул-л-хиджа", - ) + ) - persian = ( "", + persian = ( + "", "Фарвардин", "Урдбихищ", "Хурдад", @@ -256,9 +294,10 @@ class DateDisplayBG(DateDisplay): "Дай", "Бахман", "Исфаидармуз", - ) + ) - french = ( "", + french = ( + "", "Вандемер", "Брюмер", "Фример", @@ -271,8 +310,8 @@ class DateDisplayBG(DateDisplay): "Мессидор", "Термидор", "Фрюктидор", - "Допълнителен" - ) + "Допълнителен", + ) def display(self, date): """ @@ -294,12 +333,12 @@ class DateDisplayBG(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'от', d1, 'до', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "от", d1, "до", d2, scal) elif mod == Date.MOD_RANGE: d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'между', d1, 'и', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "между", d1, "и", d2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) @@ -315,21 +354,24 @@ class DateDisplayBG(DateDisplay): if date_val[0] == date_val[1] == 0: return str(date_val[2]) else: - value = self.dhformat.replace('%m', str(date_val[1])) + value = self.dhformat.replace("%m", str(date_val[1])) # some locales have %b for the month, e.g. ar_EG, is_IS, nb_NO - value = value.replace('%b', str(date_val[1])) - if date_val[0] == 0: # ignore the zero day and its delimiter - i_day = value.find('%e') # Bulgarian uses %e and not %d - value = value.replace(value[i_day:i_day+3], '') - value = value.replace('%e', str(date_val[0])) - value = value.replace('%Y', str(abs(date_val[2]))) - return value.replace('-', '/') + value = value.replace("%b", str(date_val[1])) + if date_val[0] == 0: # ignore the zero day and its delimiter + i_day = value.find("%e") # Bulgarian uses %e and not %d + value = value.replace(value[i_day : i_day + 3], "") + value = value.replace("%e", str(date_val[0])) + value = value.replace("%Y", str(abs(date_val[2]))) + return value.replace("-", "/") -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('bg_BG', 'bg', 'bulgarian', 'Bulgarian', ('%e.%m.%Y',)), - DateParserBG, DateDisplayBG) + ("bg_BG", "bg", "bulgarian", "Bulgarian", ("%e.%m.%Y",)), + DateParserBG, + DateDisplayBG, +) diff --git a/gramps/gen/datehandler/_date_ca.py b/gramps/gen/datehandler/_date_ca.py index 7f1ffdddb..1f0fc133e 100644 --- a/gramps/gen/datehandler/_date_ca.py +++ b/gramps/gen/datehandler/_date_ca.py @@ -25,137 +25,170 @@ Catalan-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Catalan parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserCA(DateParser): modifier_to_int = { - 'abans de' : Date.MOD_BEFORE, - 'abans' : Date.MOD_BEFORE, - 'ab.' : Date.MOD_BEFORE, - 'després de' : Date.MOD_AFTER, - 'després' : Date.MOD_AFTER, - 'desp.' : Date.MOD_AFTER, - 'desp' : Date.MOD_AFTER, - 'aprox.' : Date.MOD_ABOUT, - 'aprox' : Date.MOD_ABOUT, - 'circa' : Date.MOD_ABOUT, - 'ca.' : Date.MOD_ABOUT, - 'ca' : Date.MOD_ABOUT, - 'c.' : Date.MOD_ABOUT, - 'cap a' : Date.MOD_ABOUT, - 'al voltant' : Date.MOD_ABOUT, - 'al voltant de': Date.MOD_ABOUT, - } + "abans de": Date.MOD_BEFORE, + "abans": Date.MOD_BEFORE, + "ab.": Date.MOD_BEFORE, + "després de": Date.MOD_AFTER, + "després": Date.MOD_AFTER, + "desp.": Date.MOD_AFTER, + "desp": Date.MOD_AFTER, + "aprox.": Date.MOD_ABOUT, + "aprox": Date.MOD_ABOUT, + "circa": Date.MOD_ABOUT, + "ca.": Date.MOD_ABOUT, + "ca": Date.MOD_ABOUT, + "c.": Date.MOD_ABOUT, + "cap a": Date.MOD_ABOUT, + "al voltant": Date.MOD_ABOUT, + "al voltant de": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } calendar_to_int = { - 'gregorià' : Date.CAL_GREGORIAN, - 'g' : Date.CAL_GREGORIAN, - 'julià' : Date.CAL_JULIAN, - 'j' : Date.CAL_JULIAN, - 'hebreu' : Date.CAL_HEBREW, - 'h' : Date.CAL_HEBREW, - 'islàmic' : Date.CAL_ISLAMIC, - 'i' : Date.CAL_ISLAMIC, - 'revolucionari': Date.CAL_FRENCH, - 'r' : Date.CAL_FRENCH, - 'persa' : Date.CAL_PERSIAN, - 'p' : Date.CAL_PERSIAN, - 'swedish' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - } + "gregorià": Date.CAL_GREGORIAN, + "g": Date.CAL_GREGORIAN, + "julià": Date.CAL_JULIAN, + "j": Date.CAL_JULIAN, + "hebreu": Date.CAL_HEBREW, + "h": Date.CAL_HEBREW, + "islàmic": Date.CAL_ISLAMIC, + "i": Date.CAL_ISLAMIC, + "revolucionari": Date.CAL_FRENCH, + "r": Date.CAL_FRENCH, + "persa": Date.CAL_PERSIAN, + "p": Date.CAL_PERSIAN, + "swedish": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } quality_to_int = { - 'estimat' : Date.QUAL_ESTIMATED, - 'est.' : Date.QUAL_ESTIMATED, - 'est' : Date.QUAL_ESTIMATED, - 'calc.' : Date.QUAL_CALCULATED, - 'calc' : Date.QUAL_CALCULATED, - 'calculat' : Date.QUAL_CALCULATED, - } + "estimat": Date.QUAL_ESTIMATED, + "est.": Date.QUAL_ESTIMATED, + "est": Date.QUAL_ESTIMATED, + "calc.": Date.QUAL_CALCULATED, + "calc": Date.QUAL_CALCULATED, + "calculat": Date.QUAL_CALCULATED, + } def init_strings(self): DateParser.init_strings(self) - _span_1 = ['des de'] - _span_2 = ['fins a'] - _range_1 = ['entre', r'ent\.', 'ent'] - _range_2 = ['i'] + _span_1 = ["des de"] + _span_2 = ["fins a"] + _range_1 = ["entre", r"ent\.", "ent"] + _range_2 = ["i"] self._span = re.compile( - r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_span_1), '|'.join(_span_2)), re.IGNORECASE) + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) self._range = re.compile( - r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_range_1), '|'.join(_range_2)), re.IGNORECASE) + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Catalan display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayCA(DateDisplay): """ Catalan language date display class. """ - long_months = ( "", "Gener", "Febrer", "Març", "Abril", "Maig", - "Juny", "Juliol", "Agost", "Setembre", "Octubre", - "Novembre", "Desembre" ) - short_months = ( "", "Gen", "Feb", "Mar", "Abr", "Mai", "Jun", - "Jul", "Ago", "Set", "Oct", "Nov", "Des" ) + long_months = ( + "", + "Gener", + "Febrer", + "Març", + "Abril", + "Maig", + "Juny", + "Juliol", + "Agost", + "Setembre", + "Octubre", + "Novembre", + "Desembre", + ) - calendar = ( - "", "Julià", "Hebreu", - "Revolucionari", "Persa", "Islàmic", - "Suec" - ) + short_months = ( + "", + "Gen", + "Feb", + "Mar", + "Abr", + "Mai", + "Jun", + "Jul", + "Ago", + "Set", + "Oct", + "Nov", + "Des", + ) + + calendar = ("", "Julià", "Hebreu", "Revolucionari", "Persa", "Islàmic", "Suec") _mod_str = ("", "abans de ", "després de ", "cap a ", "", "", "") _qual_str = ("", "estimat ", "calculat ") french = ( - '', + "", "Vendemiari", - 'Brumari', - 'Frimari', + "Brumari", + "Frimari", "Nivós", "Pluviós", "Ventós", - 'Germinal', + "Germinal", "Floreal", - 'Pradial', - 'Messidor', - 'Termidor', - 'Fructidor', - 'Extra', - ) + "Pradial", + "Messidor", + "Termidor", + "Fructidor", + "Extra", + ) formats = ( - "AAAA-MM-DD (ISO)", "Numèrica", "Mes Dia, Any", - "MES Dia, Any", "Dia Mes, Any", "Dia MES, Any" - ) - # this must agree with DateDisplayEn's "formats" definition - # (since no locale-specific _display_gregorian exists, here) + "AAAA-MM-DD (ISO)", + "Numèrica", + "Mes Dia, Any", + "MES Dia, Any", + "Dia Mes, Any", + "Dia MES, Any", + ) + # this must agree with DateDisplayEn's "formats" definition + # (since no locale-specific _display_gregorian exists, here) def display(self, date): """ @@ -177,23 +210,25 @@ class DateDisplayCA(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'des de', d1, 'fins a', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "des de", d1, "fins a", d2, scal) elif mod == Date.MOD_RANGE: d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'entre', d1, 'i', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "entre", d1, "i", d2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('ca_ES', 'ca', 'català', 'Catalan', - 'ca_FR', 'ca_AD', 'ca_IT', ('%d/%m/%Y',)), - DateParserCA, DateDisplayCA) + ("ca_ES", "ca", "català", "Catalan", "ca_FR", "ca_AD", "ca_IT", ("%d/%m/%Y",)), + DateParserCA, + DateDisplayCA, +) diff --git a/gramps/gen/datehandler/_date_cs.py b/gramps/gen/datehandler/_date_cs.py index 610470f40..fe03eb0c9 100644 --- a/gramps/gen/datehandler/_date_cs.py +++ b/gramps/gen/datehandler/_date_cs.py @@ -23,72 +23,80 @@ Czech-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Czech parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserCZ(DateParser): """ Converts a text string into a Date object """ modifier_to_int = { - 'před': Date.MOD_BEFORE, - 'kolem': Date.MOD_ABOUT, - 'po': Date.MOD_AFTER, + "před": Date.MOD_BEFORE, + "kolem": Date.MOD_ABOUT, + "po": Date.MOD_AFTER, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, } quality_to_int = { - 'přibližně' : Date.QUAL_ESTIMATED, - 'odhadem' : Date.QUAL_ESTIMATED, - 'odh.' : Date.QUAL_ESTIMATED, - 'vypočteno' : Date.QUAL_CALCULATED, - 'vypočtené' : Date.QUAL_CALCULATED, - 'vyp.' : Date.QUAL_CALCULATED, + "přibližně": Date.QUAL_ESTIMATED, + "odhadem": Date.QUAL_ESTIMATED, + "odh.": Date.QUAL_ESTIMATED, + "vypočteno": Date.QUAL_CALCULATED, + "vypočtené": Date.QUAL_CALCULATED, + "vyp.": Date.QUAL_CALCULATED, } - bce = ["před naším letopočtem", "před Kristem", - "př. n. l.", "př. Kr."] + DateParser.bce + bce = [ + "před naším letopočtem", + "před Kristem", + "př. n. l.", + "př. Kr.", + ] + DateParser.bce def dhformat_changed(self): - """ Allow overriding so a subclass can modify it """ + """Allow overriding so a subclass can modify it""" # bug 9739 grampslocale.py gets '%-d.%-m.%Y' -- makes it be '%/d.%/m.%Y' - self.dhformat = self.dhformat.replace('/', '') # so counteract that + self.dhformat = self.dhformat.replace("/", "") # so counteract that def init_strings(self): DateParser.init_strings(self) - self._text2 = re.compile(r'(\d+)?\.?\s+?%s\.?\s*((\d+)(/\d+)?)?\s*$' - % self._mon_str, re.IGNORECASE) + self._text2 = re.compile( + r"(\d+)?\.?\s+?%s\.?\s*((\d+)(/\d+)?)?\s*$" % self._mon_str, re.IGNORECASE + ) self._span = re.compile( - r"(od)\s+(?P.+)\s+(do)\s+(?P.+)", - re.IGNORECASE) + r"(od)\s+(?P.+)\s+(do)\s+(?P.+)", re.IGNORECASE + ) self._range = re.compile( - r"(mezi)\s+(?P.+)\s+(a)\s+(?P.+)", - re.IGNORECASE) + r"(mezi)\s+(?P.+)\s+(a)\s+(?P.+)", re.IGNORECASE + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Czech display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayCZ(DateDisplay): """ Czech language date display class. @@ -97,17 +105,17 @@ class DateDisplayCZ(DateDisplay): display = DateDisplay.display_formatted def formats_changed(self): - """ Allow overriding so a subclass can modify """ + """Allow overriding so a subclass can modify""" # bug 9537 grampslocale.py gets '%-d.%-m.%Y' -- makes it be '%/d.%/m.%Y' - self.dhformat = self.dhformat.replace('/', '') # so counteract that + self.dhformat = self.dhformat.replace("/", "") # so counteract that -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ("cs_CZ", "cs", "CS", "Czech", ('%-d.%-m.%Y',)), - DateParserCZ, DateDisplayCZ) + ("cs_CZ", "cs", "CS", "Czech", ("%-d.%-m.%Y",)), DateParserCZ, DateDisplayCZ +) diff --git a/gramps/gen/datehandler/_date_da.py b/gramps/gen/datehandler/_date_da.py index 0446aade8..d1470d38a 100644 --- a/gramps/gen/datehandler/_date_da.py +++ b/gramps/gen/datehandler/_date_da.py @@ -23,28 +23,28 @@ Danish-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Danish parser class # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserDa(DateParser): """ Convert a text string into a Date object, expecting a date @@ -54,65 +54,94 @@ class DateParserDa(DateParser): # modifiers before the date modifier_to_int = { - 'før' : Date.MOD_BEFORE, - 'inden' : Date.MOD_BEFORE, - 'efter' : Date.MOD_AFTER, - 'omkring' : Date.MOD_ABOUT, - 'ca.' : Date.MOD_ABOUT - } + "før": Date.MOD_BEFORE, + "inden": Date.MOD_BEFORE, + "efter": Date.MOD_AFTER, + "omkring": Date.MOD_ABOUT, + "ca.": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } bce = ["f Kr"] calendar_to_int = { - 'gregoriansk ' : Date.CAL_GREGORIAN, - 'g' : Date.CAL_GREGORIAN, - 'juliansk tidsregning': Date.CAL_JULIAN, - 'juliansk' : Date.CAL_JULIAN, - 'j' : Date.CAL_JULIAN, - 'hebraisk' : Date.CAL_HEBREW, - 'h' : Date.CAL_HEBREW, - 'islamisk' : Date.CAL_ISLAMIC, - 'muslimsk' : Date.CAL_ISLAMIC, - 'i' : Date.CAL_ISLAMIC, - 'fransk' : Date.CAL_FRENCH, - 'fransk republikansk' : Date.CAL_FRENCH, - 'f' : Date.CAL_FRENCH, - 'persisk' : Date.CAL_PERSIAN, - 'p' : Date.CAL_PERSIAN, - 'svensk' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - } + "gregoriansk ": Date.CAL_GREGORIAN, + "g": Date.CAL_GREGORIAN, + "juliansk tidsregning": Date.CAL_JULIAN, + "juliansk": Date.CAL_JULIAN, + "j": Date.CAL_JULIAN, + "hebraisk": Date.CAL_HEBREW, + "h": Date.CAL_HEBREW, + "islamisk": Date.CAL_ISLAMIC, + "muslimsk": Date.CAL_ISLAMIC, + "i": Date.CAL_ISLAMIC, + "fransk": Date.CAL_FRENCH, + "fransk republikansk": Date.CAL_FRENCH, + "f": Date.CAL_FRENCH, + "persisk": Date.CAL_PERSIAN, + "p": Date.CAL_PERSIAN, + "svensk": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } quality_to_int = { - 'estimeret' : Date.QUAL_ESTIMATED, - 'anslået' : Date.QUAL_ESTIMATED, - 'beregnet' : Date.QUAL_CALCULATED, - } + "estimeret": Date.QUAL_ESTIMATED, + "anslået": Date.QUAL_ESTIMATED, + "beregnet": Date.QUAL_CALCULATED, + } def init_strings(self): DateParser.init_strings(self) self._span = re.compile( - r"(fra)?\s*(?P.+)\s*(til|--|–)\s*(?P.+)", - re.IGNORECASE) + r"(fra)?\s*(?P.+)\s*(til|--|–)\s*(?P.+)", re.IGNORECASE + ) self._range = re.compile( - r"(mellem)\s+(?P.+)\s+og\s+(?P.+)", re.IGNORECASE) + r"(mellem)\s+(?P.+)\s+og\s+(?P.+)", re.IGNORECASE + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Danish display class # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayDa(DateDisplay): """ Danish language date display class. """ - long_months = ( "", "januar", "februar", "marts", "april", "maj", - "juni", "juli", "august", "september", "oktober", - "november", "december" ) + long_months = ( + "", + "januar", + "februar", + "marts", + "april", + "maj", + "juni", + "juli", + "august", + "september", + "oktober", + "november", + "december", + ) - short_months = ( "", "jan", "feb", "mar", "apr", "maj", "jun", - "jul", "aug", "sep", "okt", "nov", "dec" ) + short_months = ( + "", + "jan", + "feb", + "mar", + "apr", + "maj", + "jun", + "jul", + "aug", + "sep", + "okt", + "nov", + "dec", + ) formats = ( "ÅÅÅÅ-MM-DD (ISO)", @@ -121,9 +150,9 @@ class DateDisplayDa(DateDisplay): "Md Dag År", "Dag måned år", "Dag md År", - ) - # this must agree with DateDisplayEn's "formats" definition - # (since no locale-specific _display_gregorian exists, here) + ) + # this must agree with DateDisplayEn's "formats" definition + # (since no locale-specific _display_gregorian exists, here) calendar = ( "", @@ -132,8 +161,8 @@ class DateDisplayDa(DateDisplay): "fransk republikansk", "persisk", "islamisk", - "svensk" - ) + "svensk", + ) _mod_str = ("", "før ", "efter ", "ca. ", "", "", "") @@ -166,19 +195,18 @@ class DateDisplayDa(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%smellem %s og %s%s" % (qual_str, d1, d2, - scal) + return "%smellem %s og %s%s" % (qual_str, d1, d2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) - return "%s%s%s%s" % (qual_str, self._mod_str[mod], - text, scal) + return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('da_DK', 'da', 'dansk', 'Danish', ('%d-%m-%Y',)), - DateParserDa, DateDisplayDa) + ("da_DK", "da", "dansk", "Danish", ("%d-%m-%Y",)), DateParserDa, DateDisplayDa +) diff --git a/gramps/gen/datehandler/_date_de.py b/gramps/gen/datehandler/_date_de.py index 8ff970d1a..bb8d3050c 100644 --- a/gramps/gen/datehandler/_date_de.py +++ b/gramps/gen/datehandler/_date_de.py @@ -23,28 +23,28 @@ German-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # German parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserDE(DateParser): month_to_int = DateParser.month_to_int @@ -208,72 +208,90 @@ class DateParserDE(DateParser): month_to_int["wendeling"] = 11 modifier_to_int = { - 'vor' : Date.MOD_BEFORE, - 'nach' : Date.MOD_AFTER, - 'gegen' : Date.MOD_ABOUT, - 'um' : Date.MOD_ABOUT, - 'etwa' : Date.MOD_ABOUT, - 'circa' : Date.MOD_ABOUT, - 'ca.' : Date.MOD_ABOUT, - } + "vor": Date.MOD_BEFORE, + "nach": Date.MOD_AFTER, + "gegen": Date.MOD_ABOUT, + "um": Date.MOD_ABOUT, + "etwa": Date.MOD_ABOUT, + "circa": Date.MOD_ABOUT, + "ca.": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } calendar_to_int = { - 'gregorianisch' : Date.CAL_GREGORIAN, - 'greg.' : Date.CAL_GREGORIAN, - 'julianisch' : Date.CAL_JULIAN, - 'jul.' : Date.CAL_JULIAN, - 'hebräisch' : Date.CAL_HEBREW, - 'hebr.' : Date.CAL_HEBREW, - 'islamisch' : Date.CAL_ISLAMIC, - 'isl.' : Date.CAL_ISLAMIC, - 'französisch republikanisch': Date.CAL_FRENCH, - 'franz.' : Date.CAL_FRENCH, - 'persisch' : Date.CAL_PERSIAN, - 'schwedisch' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - } + "gregorianisch": Date.CAL_GREGORIAN, + "greg.": Date.CAL_GREGORIAN, + "julianisch": Date.CAL_JULIAN, + "jul.": Date.CAL_JULIAN, + "hebräisch": Date.CAL_HEBREW, + "hebr.": Date.CAL_HEBREW, + "islamisch": Date.CAL_ISLAMIC, + "isl.": Date.CAL_ISLAMIC, + "französisch republikanisch": Date.CAL_FRENCH, + "franz.": Date.CAL_FRENCH, + "persisch": Date.CAL_PERSIAN, + "schwedisch": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } quality_to_int = { - 'geschätzt' : Date.QUAL_ESTIMATED, - 'gesch.' : Date.QUAL_ESTIMATED, - 'errechnet' : Date.QUAL_CALCULATED, - 'berechnet' : Date.QUAL_CALCULATED, - 'ber.' : Date.QUAL_CALCULATED, - } + "geschätzt": Date.QUAL_ESTIMATED, + "gesch.": Date.QUAL_ESTIMATED, + "errechnet": Date.QUAL_CALCULATED, + "berechnet": Date.QUAL_CALCULATED, + "ber.": Date.QUAL_CALCULATED, + } - bce = ["vor unserer Zeitrechnung", "vor unserer Zeit", - "vor der Zeitrechnung", "vor der Zeit", - "v. u. Z.", "v. d. Z.", "v.u.Z.", "v.d.Z.", - "vor Christi Geburt", "vor Christus", "v. Chr."] + DateParser.bce + bce = [ + "vor unserer Zeitrechnung", + "vor unserer Zeit", + "vor der Zeitrechnung", + "vor der Zeit", + "v. u. Z.", + "v. d. Z.", + "v.u.Z.", + "v.d.Z.", + "vor Christi Geburt", + "vor Christus", + "v. Chr.", + ] + DateParser.bce def init_strings(self): DateParser.init_strings(self) self._span = re.compile( - r"(von|vom)\s+(?P.+)\s+(bis)\s+(?P.+)", re.IGNORECASE) + r"(von|vom)\s+(?P.+)\s+(bis)\s+(?P.+)", re.IGNORECASE + ) self._range = re.compile( - r"zwischen\s+(?P.+)\s+und\s+(?P.+)", re.IGNORECASE) + r"zwischen\s+(?P.+)\s+und\s+(?P.+)", re.IGNORECASE + ) self._text2 = re.compile( - r'(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' % self._mon_str, - re.IGNORECASE) + r"(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?" % self._mon_str, re.IGNORECASE + ) self._jtext2 = re.compile( - r'(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' % self._jmon_str, - re.IGNORECASE) + r"(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?" % self._jmon_str, re.IGNORECASE + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # German display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayDE(DateDisplay): """ German language date display class. """ calendar = ( - "", "julianisch", "hebräisch", - "französisch republikanisch", "persisch", "islamisch", - "schwedisch" - ) + "", + "julianisch", + "hebräisch", + "französisch republikanisch", + "persisch", + "islamisch", + "schwedisch", + ) _mod_str = ("", "vor ", "nach ", "etwa ", "", "", "") @@ -282,11 +300,15 @@ class DateDisplayDE(DateDisplay): _bce_str = "%s v. u. Z." formats = ( - "JJJJ-MM-DD (ISO)", "Numerisch", "Monat Tag Jahr", - "MONAT Tag Jahr", "Tag. Monat Jahr", "Tag. MONAT Jahr", - "Numerisch mit führenden Nullen" - ) - # this definition must agree with its "_display_gregorian" method + "JJJJ-MM-DD (ISO)", + "Numerisch", + "Monat Tag Jahr", + "MONAT Tag Jahr", + "Tag. Monat Jahr", + "Tag. MONAT Jahr", + "Numerisch mit führenden Nullen", + ) + # this definition must agree with its "_display_gregorian" method def _display_gregorian(self, date_val, **kwargs): """ @@ -304,9 +326,9 @@ class DateDisplayDE(DateDisplay): if date_val[0] == date_val[1] == 0: value = str(date_val[2]) else: - value = self.dhformat.replace('%m', str(date_val[1])) - value = value.replace('%d', str(date_val[0])) - value = value.replace('%Y', str(date_val[2])) + value = self.dhformat.replace("%m", str(date_val[1])) + value = value.replace("%d", str(date_val[0])) + value = value.replace("%Y", str(date_val[2])) elif self.format == 2: # month_name day, year if date_val[0] == 0: @@ -315,8 +337,7 @@ class DateDisplayDE(DateDisplay): else: value = "%s %s" % (self.long_months[date_val[1]], year) else: - value = "%s %d, %s" % (self.long_months[date_val[1]], - date_val[0], year) + value = "%s %d, %s" % (self.long_months[date_val[1]], date_val[0], year) elif self.format == 3: # month_abbreviation day, year if date_val[0] == 0: @@ -325,8 +346,11 @@ class DateDisplayDE(DateDisplay): else: value = "%s %s" % (self.short_months[date_val[1]], year) else: - value = "%s %d, %s" % (self.short_months[date_val[1]], - date_val[0], year) + value = "%s %d, %s" % ( + self.short_months[date_val[1]], + date_val[0], + year, + ) elif self.format == 4: # day. month_name year if date_val[0] == 0: @@ -335,8 +359,7 @@ class DateDisplayDE(DateDisplay): else: value = "%s %s" % (self.long_months[date_val[1]], year) else: - value = "%d. %s %s" % (date_val[0], - self.long_months[date_val[1]], year) + value = "%d. %s %s" % (date_val[0], self.long_months[date_val[1]], year) elif self.format == 6: # day.month_number.year with leading zeros if date_val[3]: @@ -345,10 +368,9 @@ class DateDisplayDE(DateDisplay): if date_val[0] == date_val[1] == 0: value = str(date_val[2]) else: - value = self.dhformat.replace('%m', str(date_val[1]) - .zfill(2)) - value = value.replace('%d', str(date_val[0]).zfill(2)) - value = value.replace('%Y', str(date_val[2])) + value = self.dhformat.replace("%m", str(date_val[1]).zfill(2)) + value = value.replace("%d", str(date_val[0]).zfill(2)) + value = value.replace("%Y", str(date_val[2])) else: # day. month_abbreviation year if date_val[0] == 0: @@ -357,8 +379,11 @@ class DateDisplayDE(DateDisplay): else: value = "%s %s" % (self.short_months[date_val[1]], year) else: - value = "%d. %s %s" % (date_val[0], - self.short_months[date_val[1]], year) + value = "%d. %s %s" % ( + date_val[0], + self.short_months[date_val[1]], + year, + ) if date_val[2] < 0: return self._bce_str % value else: @@ -384,7 +409,7 @@ class DateDisplayDE(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'von', d1, 'bis', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "von", d1, "bis", d2, scal) elif mod == Date.MOD_RANGE: d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) @@ -395,13 +420,25 @@ class DateDisplayDE(DateDisplay): scal = self.format_extras(cal, newyear) return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('de_DE', 'german', 'German', 'de_CH', - 'de_LI', 'de_LU', 'de_BE', 'de', ('%d.%m.%Y',)), - DateParserDE, DateDisplayDE) -register_datehandler( ('de_AT', ('%d.%m.%Y',)), DateParserDE, DateDisplayDE) \ No newline at end of file + ( + "de_DE", + "german", + "German", + "de_CH", + "de_LI", + "de_LU", + "de_BE", + "de", + ("%d.%m.%Y",), + ), + DateParserDE, + DateDisplayDE, +) +register_datehandler(("de_AT", ("%d.%m.%Y",)), DateParserDE, DateDisplayDE) diff --git a/gramps/gen/datehandler/_date_el.py b/gramps/gen/datehandler/_date_el.py index b5209f5f6..928c56152 100644 --- a/gramps/gen/datehandler/_date_el.py +++ b/gramps/gen/datehandler/_date_el.py @@ -24,28 +24,28 @@ Greek-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Greek parser class # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserEL(DateParser): """ Convert a text string into a Date object. If the date cannot be @@ -54,94 +54,126 @@ class DateParserEL(DateParser): # modifiers before the date modifier_to_int = { - 'προ του' : Date.MOD_BEFORE, - 'πριν το' : Date.MOD_BEFORE, - 'πριν από τις' : Date.MOD_BEFORE, - 'πριν από την' : Date.MOD_BEFORE, - 'πριν από το' : Date.MOD_BEFORE, - 'πριν από τον' : Date.MOD_BEFORE, - 'προ' : Date.MOD_BEFORE, - 'πρ.' : Date.MOD_BEFORE, - 'μετά το' : Date.MOD_AFTER, - 'μετά από τις' : Date.MOD_AFTER, - 'μετά από την' : Date.MOD_AFTER, - 'μετά από το' : Date.MOD_AFTER, - 'μετά από τον' : Date.MOD_AFTER, - 'μετά' : Date.MOD_AFTER, - 'μετ.' : Date.MOD_AFTER, - 'γύρω στο' : Date.MOD_ABOUT, - 'γύρω στον' : Date.MOD_ABOUT, - 'γύρω στις' : Date.MOD_ABOUT, - 'περίπου το' : Date.MOD_ABOUT, - 'περ.' : Date.MOD_ABOUT, - 'γυρ.' : Date.MOD_ABOUT, - '~' : Date.MOD_ABOUT, - } + "προ του": Date.MOD_BEFORE, + "πριν το": Date.MOD_BEFORE, + "πριν από τις": Date.MOD_BEFORE, + "πριν από την": Date.MOD_BEFORE, + "πριν από το": Date.MOD_BEFORE, + "πριν από τον": Date.MOD_BEFORE, + "προ": Date.MOD_BEFORE, + "πρ.": Date.MOD_BEFORE, + "μετά το": Date.MOD_AFTER, + "μετά από τις": Date.MOD_AFTER, + "μετά από την": Date.MOD_AFTER, + "μετά από το": Date.MOD_AFTER, + "μετά από τον": Date.MOD_AFTER, + "μετά": Date.MOD_AFTER, + "μετ.": Date.MOD_AFTER, + "γύρω στο": Date.MOD_ABOUT, + "γύρω στον": Date.MOD_ABOUT, + "γύρω στις": Date.MOD_ABOUT, + "περίπου το": Date.MOD_ABOUT, + "περ.": Date.MOD_ABOUT, + "γυρ.": Date.MOD_ABOUT, + "~": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } - bce = ["π.Χ.", "π.Κ.Χ.", "π.Κ.Ε.", "π.Χ" ] + bce = ["π.Χ.", "π.Κ.Χ.", "π.Κ.Ε.", "π.Χ"] calendar_to_int = { - 'γρηγοριανό' : Date.CAL_GREGORIAN, - 'γ' : Date.CAL_GREGORIAN, - 'ιουλιανό' : Date.CAL_JULIAN, - 'ι' : Date.CAL_JULIAN, - 'εβραϊκό' : Date.CAL_HEBREW, - 'ε' : Date.CAL_HEBREW, - 'ισλαμικό' : Date.CAL_ISLAMIC, - 'ισλ' : Date.CAL_ISLAMIC, - 'γαλλικό' : Date.CAL_FRENCH, - 'γαλλικής δημοκρατίας': Date.CAL_FRENCH, - 'γ' : Date.CAL_FRENCH, - 'περσικό' : Date.CAL_PERSIAN, - 'π' : Date.CAL_PERSIAN, - 'σουηδικό' : Date.CAL_SWEDISH, - 'σ' : Date.CAL_SWEDISH, - } + "γρηγοριανό": Date.CAL_GREGORIAN, + "γ": Date.CAL_GREGORIAN, + "ιουλιανό": Date.CAL_JULIAN, + "ι": Date.CAL_JULIAN, + "εβραϊκό": Date.CAL_HEBREW, + "ε": Date.CAL_HEBREW, + "ισλαμικό": Date.CAL_ISLAMIC, + "ισλ": Date.CAL_ISLAMIC, + "γαλλικό": Date.CAL_FRENCH, + "γαλλικής δημοκρατίας": Date.CAL_FRENCH, + "γ": Date.CAL_FRENCH, + "περσικό": Date.CAL_PERSIAN, + "π": Date.CAL_PERSIAN, + "σουηδικό": Date.CAL_SWEDISH, + "σ": Date.CAL_SWEDISH, + } quality_to_int = { - 'κατʼ εκτίμηση' : Date.QUAL_ESTIMATED, - 'εκτιμώμενη' : Date.QUAL_ESTIMATED, - 'εκτ.' : Date.QUAL_ESTIMATED, - 'εκτ' : Date.QUAL_ESTIMATED, - 'υπολογ' : Date.QUAL_CALCULATED, - 'υπολογ.' : Date.QUAL_CALCULATED, - 'υπολογισμένη' : Date.QUAL_CALCULATED, - 'με υπολογισμό' : Date.QUAL_CALCULATED, - } + "κατʼ εκτίμηση": Date.QUAL_ESTIMATED, + "εκτιμώμενη": Date.QUAL_ESTIMATED, + "εκτ.": Date.QUAL_ESTIMATED, + "εκτ": Date.QUAL_ESTIMATED, + "υπολογ": Date.QUAL_CALCULATED, + "υπολογ.": Date.QUAL_CALCULATED, + "υπολογισμένη": Date.QUAL_CALCULATED, + "με υπολογισμό": Date.QUAL_CALCULATED, + } def init_strings(self): """ This method compiles regular expression strings for matching dates. """ DateParser.init_strings(self) - _span_1 = ['από'] - _span_2 = ['έως'] - _range_1 = ['μετ', r'μετ\.', 'μεταξύ'] - _range_2 = ['και'] + _span_1 = ["από"] + _span_2 = ["έως"] + _range_1 = ["μετ", r"μετ\.", "μεταξύ"] + _range_2 = ["και"] self._span = re.compile( - r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_span_1), '|'.join(_span_2)), re.IGNORECASE) + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) self._range = re.compile( - r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_range_1), '|'.join(_range_2)), re.IGNORECASE) + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Greek display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayEL(DateDisplay): """ Greek language date display class. """ - # this is used to display the 12 gregorian months - long_months = ( "", "Ιανουάριος", "Φεβρουάριος", "Μάρτιος", - "Απρίλιος", "Μάιος", "Ιούνιος", - "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", - "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος" ) - short_months = ( "", "Ιαν", "Φεβ", "Μαρ", "Απρ", "Μάι", "Ιουν", - "Ιουλ", "Αύγ", "Σεπ", "Οκτ", "Νοε", "Δεκ" ) + # this is used to display the 12 gregorian months + long_months = ( + "", + "Ιανουάριος", + "Φεβρουάριος", + "Μάρτιος", + "Απρίλιος", + "Μάιος", + "Ιούνιος", + "Ιούλιος", + "Αύγουστος", + "Σεπτέμβριος", + "Οκτώβριος", + "Νοέμβριος", + "Δεκέμβριος", + ) + + short_months = ( + "", + "Ιαν", + "Φεβ", + "Μαρ", + "Απρ", + "Μάι", + "Ιουν", + "Ιουλ", + "Αύγ", + "Σεπ", + "Οκτ", + "Νοε", + "Δεκ", + ) _mod_str = ("", "προ του ", "μετά το ", "γύρω στο ", "", "", "") @@ -150,10 +182,13 @@ class DateDisplayEL(DateDisplay): _bce_str = "%s π.Χ." formats = ( - "ΕΕΕΕ-ΜΜ-ΗΗ (ISO)", "ΗΗ-ΜΜ-ΕΕΕΕ", "ΗΗ/ΜΜ/ΕΕΕΕ", - "ΗΗ Μήνας ΕΕΕΕ", "ΗΗ Μήν ΕΕΕΕ" - ) - # this definition must agree with its "_display_gregorian" method + "ΕΕΕΕ-ΜΜ-ΗΗ (ISO)", + "ΗΗ-ΜΜ-ΕΕΕΕ", + "ΗΗ/ΜΜ/ΕΕΕΕ", + "ΗΗ Μήνας ΕΕΕΕ", + "ΗΗ Μήν ΕΕΕΕ", + ) + # this definition must agree with its "_display_gregorian" method def _display_gregorian(self, date_val, **kwargs): """ @@ -189,8 +224,7 @@ class DateDisplayEL(DateDisplay): else: value = "%s %s" % (self.long_months[date_val[1]], year) else: - value = "%d %s %s" % (date_val[0], - self.long_months[date_val[1]], year) + value = "%d %s %s" % (date_val[0], self.long_months[date_val[1]], year) else: # day month_abbreviation year if date_val[0] == 0: @@ -199,8 +233,7 @@ class DateDisplayEL(DateDisplay): else: value = "%s %s" % (self.short_months[date_val[1]], year) else: - value = "%d %s %s" % (date_val[0], - self.short_months[date_val[1]], year) + value = "%d %s %s" % (date_val[0], self.short_months[date_val[1]], year) if date_val[2] < 0: return self._bce_str % value else: @@ -226,22 +259,25 @@ class DateDisplayEL(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'από', d1, 'έως', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "από", d1, "έως", d2, scal) elif mod == Date.MOD_RANGE: d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'μεταξύ', d1, 'και', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "μεταξύ", d1, "και", d2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('el_GR', 'el_CY', 'el', 'Greek', 'greek', ('%d/%m/%Y',)), - DateParserEL, DateDisplayEL) + ("el_GR", "el_CY", "el", "Greek", "greek", ("%d/%m/%Y",)), + DateParserEL, + DateDisplayEL, +) diff --git a/gramps/gen/datehandler/_date_es.py b/gramps/gen/datehandler/_date_es.py index e7ecb1aa6..a3f731d4c 100644 --- a/gramps/gen/datehandler/_date_es.py +++ b/gramps/gen/datehandler/_date_es.py @@ -23,102 +23,105 @@ Spanish-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Spanish parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserES(DateParser): modifier_to_int = { - 'antes de' : Date.MOD_BEFORE, - 'antes' : Date.MOD_BEFORE, - 'ant.' : Date.MOD_BEFORE, - 'ant' : Date.MOD_BEFORE, - 'después de' : Date.MOD_AFTER, - 'después' : Date.MOD_AFTER, - 'desp.' : Date.MOD_AFTER, - 'desp' : Date.MOD_AFTER, - 'aprox.' : Date.MOD_ABOUT, - 'aprox' : Date.MOD_ABOUT, - 'apr.' : Date.MOD_ABOUT, - 'apr' : Date.MOD_ABOUT, - 'circa' : Date.MOD_ABOUT, - 'ca.' : Date.MOD_ABOUT, - 'ca' : Date.MOD_ABOUT, - 'c.' : Date.MOD_ABOUT, - 'hacia' : Date.MOD_ABOUT, - } + "antes de": Date.MOD_BEFORE, + "antes": Date.MOD_BEFORE, + "ant.": Date.MOD_BEFORE, + "ant": Date.MOD_BEFORE, + "después de": Date.MOD_AFTER, + "después": Date.MOD_AFTER, + "desp.": Date.MOD_AFTER, + "desp": Date.MOD_AFTER, + "aprox.": Date.MOD_ABOUT, + "aprox": Date.MOD_ABOUT, + "apr.": Date.MOD_ABOUT, + "apr": Date.MOD_ABOUT, + "circa": Date.MOD_ABOUT, + "ca.": Date.MOD_ABOUT, + "ca": Date.MOD_ABOUT, + "c.": Date.MOD_ABOUT, + "hacia": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } calendar_to_int = { - 'gregoriano' : Date.CAL_GREGORIAN, - 'g' : Date.CAL_GREGORIAN, - 'juliano' : Date.CAL_JULIAN, - 'j' : Date.CAL_JULIAN, - 'hebreo' : Date.CAL_HEBREW, - 'h' : Date.CAL_HEBREW, - 'islámico' : Date.CAL_ISLAMIC, - 'i' : Date.CAL_ISLAMIC, - 'revolucionario' : Date.CAL_FRENCH, - 'r' : Date.CAL_FRENCH, - 'persa' : Date.CAL_PERSIAN, - 'p' : Date.CAL_PERSIAN, - 'swedish' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - } + "gregoriano": Date.CAL_GREGORIAN, + "g": Date.CAL_GREGORIAN, + "juliano": Date.CAL_JULIAN, + "j": Date.CAL_JULIAN, + "hebreo": Date.CAL_HEBREW, + "h": Date.CAL_HEBREW, + "islámico": Date.CAL_ISLAMIC, + "i": Date.CAL_ISLAMIC, + "revolucionario": Date.CAL_FRENCH, + "r": Date.CAL_FRENCH, + "persa": Date.CAL_PERSIAN, + "p": Date.CAL_PERSIAN, + "swedish": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } quality_to_int = { - 'estimado' : Date.QUAL_ESTIMATED, - 'est.' : Date.QUAL_ESTIMATED, - 'est' : Date.QUAL_ESTIMATED, - 'calc.' : Date.QUAL_CALCULATED, - 'calc' : Date.QUAL_CALCULATED, - 'calculado' : Date.QUAL_CALCULATED, - } + "estimado": Date.QUAL_ESTIMATED, + "est.": Date.QUAL_ESTIMATED, + "est": Date.QUAL_ESTIMATED, + "calc.": Date.QUAL_CALCULATED, + "calc": Date.QUAL_CALCULATED, + "calculado": Date.QUAL_CALCULATED, + } def init_strings(self): DateParser.init_strings(self) - _span_1 = ['de'] - _span_2 = ['a'] - _range_1 = ['entre', r'ent\.', 'ent'] - _range_2 = ['y'] + _span_1 = ["de"] + _span_2 = ["a"] + _range_1 = ["entre", r"ent\.", "ent"] + _range_2 = ["y"] self._span = re.compile( - r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_span_1), '|'.join(_span_2)), re.IGNORECASE) + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) self._range = re.compile( - r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_range_1), '|'.join(_range_2)), re.IGNORECASE) + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Spanish display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayES(DateDisplay): """ Spanish language date display class. """ - # TODO: Translate these month strings: - long_months = ( "", "enero", "febrero", "marzo", "abril", "mayo", - "junio", "julio", "agosto", "septiembre", "octubre", - "noviembre", "diciembre" ) short_months = ( "", "ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", @@ -135,11 +138,15 @@ class DateDisplayES(DateDisplay): _qual_str = ("", "estimado ", "calculado ") formats = ( - "AAAA-MM-DD (ISO)", "Numérica", "Mes Día, Año", - "MES Día, Año", "Día Mes, Año", "Día MES, Año" - ) - # this must agree with DateDisplayEn's "formats" definition - # (since no locale-specific _display_gregorian exists, here) + "AAAA-MM-DD (ISO)", + "Numérica", + "Mes Día, Año", + "MES Día, Año", + "Día Mes, Año", + "Día MES, Año", + ) + # this must agree with DateDisplayEn's "formats" definition + # (since no locale-specific _display_gregorian exists, here) def display(self, date): """ @@ -161,22 +168,23 @@ class DateDisplayES(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'de', d1, 'a', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "de", d1, "a", d2, scal) elif mod == Date.MOD_RANGE: d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'entre', d1, 'y', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "entre", d1, "y", d2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('es_ES', 'es', 'spanish', 'Spanish', ('%d/%m/%Y',)), - DateParserES, DateDisplayES) + ("es_ES", "es", "spanish", "Spanish", ("%d/%m/%Y",)), DateParserES, DateDisplayES +) diff --git a/gramps/gen/datehandler/_date_fi.py b/gramps/gen/datehandler/_date_fi.py index 0954baf0f..ceeaa27a4 100644 --- a/gramps/gen/datehandler/_date_fi.py +++ b/gramps/gen/datehandler/_date_fi.py @@ -23,31 +23,31 @@ Finnish-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Finnish parser # # This handles only dates where days and months are given as numeric, as: # - That's how they are normally used in Finland # - Parsing Finnish is much more complicated than English -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserFI(DateParser): # NOTE: these need to be in lower case because the "key" comparison @@ -58,76 +58,79 @@ class DateParserFI(DateParser): # examples: # - ennen 1.1.2005 # - noin 1.1.2005 - 'ennen' : Date.MOD_BEFORE, - 'e.' : Date.MOD_BEFORE, - 'noin' : Date.MOD_ABOUT, - 'n.' : Date.MOD_ABOUT, - } + "ennen": Date.MOD_BEFORE, + "e.": Date.MOD_BEFORE, + "noin": Date.MOD_ABOUT, + "n.": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } modifier_after_to_int = { # examples: # - 1.1.2005 jälkeen - 'jälkeen' : Date.MOD_AFTER, - 'j.' : Date.MOD_AFTER, - } + "jälkeen": Date.MOD_AFTER, + "j.": Date.MOD_AFTER, + } bce = ["ekr.", "ekr"] calendar_to_int = { - 'gregoriaaninen' : Date.CAL_GREGORIAN, - 'greg.' : Date.CAL_GREGORIAN, - 'juliaaninen' : Date.CAL_JULIAN, - 'jul.' : Date.CAL_JULIAN, - 'heprealainen' : Date.CAL_HEBREW, - 'hepr.' : Date.CAL_HEBREW, - 'islamilainen' : Date.CAL_ISLAMIC, - 'isl.' : Date.CAL_ISLAMIC, - 'ranskan vallankumouksen aikainen': Date.CAL_FRENCH, - 'ranskan v.' : Date.CAL_FRENCH, - 'persialainen' : Date.CAL_PERSIAN, - 'pers.' : Date.CAL_PERSIAN, - 'svensk' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - } + "gregoriaaninen": Date.CAL_GREGORIAN, + "greg.": Date.CAL_GREGORIAN, + "juliaaninen": Date.CAL_JULIAN, + "jul.": Date.CAL_JULIAN, + "heprealainen": Date.CAL_HEBREW, + "hepr.": Date.CAL_HEBREW, + "islamilainen": Date.CAL_ISLAMIC, + "isl.": Date.CAL_ISLAMIC, + "ranskan vallankumouksen aikainen": Date.CAL_FRENCH, + "ranskan v.": Date.CAL_FRENCH, + "persialainen": Date.CAL_PERSIAN, + "pers.": Date.CAL_PERSIAN, + "svensk": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } quality_to_int = { - 'arviolta' : Date.QUAL_ESTIMATED, - 'arv.' : Date.QUAL_ESTIMATED, - 'laskettuna' : Date.QUAL_CALCULATED, - 'lask.' : Date.QUAL_CALCULATED, - } + "arviolta": Date.QUAL_ESTIMATED, + "arv.": Date.QUAL_ESTIMATED, + "laskettuna": Date.QUAL_CALCULATED, + "lask.": Date.QUAL_CALCULATED, + } def init_strings(self): DateParser.init_strings(self) - self._text2 = re.compile(r'(\d+)?\.?\s+?%s\.?\s*((\d+)(/\d+)?)?\s*$' - % self._mon_str, re.IGNORECASE) - self._span = re.compile(r"(?P.+)\s+(-)\s+(?P.+)", - re.IGNORECASE) + self._text2 = re.compile( + r"(\d+)?\.?\s+?%s\.?\s*((\d+)(/\d+)?)?\s*$" % self._mon_str, re.IGNORECASE + ) + self._span = re.compile(r"(?P.+)\s+(-)\s+(?P.+)", re.IGNORECASE) self._range = re.compile( - r"(vuosien\s*)?(?P.+)\s+ja\s+(?P.+)\s+välillä", - re.IGNORECASE) + r"(vuosien\s*)?(?P.+)\s+ja\s+(?P.+)\s+välillä", re.IGNORECASE + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Finnish display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayFI(DateDisplay): """ Finnish language date display class. """ + _bce_str = "%s ekr." formats = ( "VVVV-KK-PP (ISO)", "PP.KK.VVVV", - "Päivä Kuukausi Vuosi" # Day, full month name, year - ) - # this definition must agree with its "_display_calendar" method + "Päivä Kuukausi Vuosi", # Day, full month name, year + ) + # this definition must agree with its "_display_calendar" method display = DateDisplay.display_formatted - def _display_calendar(self, date_val, long_months, short_months = None, - inflect=""): + def _display_calendar(self, date_val, long_months, short_months=None, inflect=""): # this must agree with its locale-specific "formats" definition if short_months is None: @@ -159,25 +162,26 @@ class DateDisplayFI(DateDisplay): return year else: if inflect: - return self.format_long_month_year(date_val[1], year, - inflect, long_months) + return self.format_long_month_year( + date_val[1], year, inflect, long_months + ) else: return "{long_month.f[IN]} {year}".format( - long_month = long_months[date_val[1]], - year = year) + long_month=long_months[date_val[1]], year=year + ) else: - if not hasattr(long_months[date_val[1]], 'f'): # not a Lexeme - return self.dd_dformat01(date_val) # maybe the month is zero + if not hasattr(long_months[date_val[1]], "f"): # not a Lexeme + return self.dd_dformat01(date_val) # maybe the month is zero return "{day:d}. {long_month.f[P]} {year}".format( - day = date_val[0], - long_month = long_months[date_val[1]], - year = year) + day=date_val[0], long_month=long_months[date_val[1]], year=year + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('fi_FI', 'fi', 'finnish', 'Finnish', ('%d.%m.%Y',)), - DateParserFI, DateDisplayFI) + ("fi_FI", "fi", "finnish", "Finnish", ("%d.%m.%Y",)), DateParserFI, DateDisplayFI +) diff --git a/gramps/gen/datehandler/_date_fr.py b/gramps/gen/datehandler/_date_fr.py index b7f21e012..d948e1167 100644 --- a/gramps/gen/datehandler/_date_fr.py +++ b/gramps/gen/datehandler/_date_fr.py @@ -25,29 +25,29 @@ French-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # French parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserFR(DateParser): """ Convert a text string into a Date object. If the date cannot be @@ -57,39 +57,45 @@ class DateParserFR(DateParser): month_to_int = DateParser.month_to_int modifier_to_int = { - 'avant' : Date.MOD_BEFORE, - 'av.' : Date.MOD_BEFORE, - #u'av' : Date.MOD_BEFORE, # Broke Hebrew "Av" month name - #u'<' : Date.MOD_BEFORE, # Worrying about XML/HTML parsing - 'après' : Date.MOD_AFTER, - 'ap.' : Date.MOD_AFTER, - 'ap' : Date.MOD_AFTER, - #u'>' : Date.MOD_AFTER, # Worrying about XML/HTML parsing - 'environ' : Date.MOD_ABOUT, - 'env.' : Date.MOD_ABOUT, - 'env' : Date.MOD_ABOUT, - 'circa' : Date.MOD_ABOUT, - 'ca.' : Date.MOD_ABOUT, - 'ca' : Date.MOD_ABOUT, - 'c.' : Date.MOD_ABOUT, - 'vers' : Date.MOD_ABOUT, - '~' : Date.MOD_ABOUT, - } + "avant": Date.MOD_BEFORE, + "av.": Date.MOD_BEFORE, + # u'av' : Date.MOD_BEFORE, # Broke Hebrew "Av" month name + # u'<' : Date.MOD_BEFORE, # Worrying about XML/HTML parsing + "après": Date.MOD_AFTER, + "ap.": Date.MOD_AFTER, + "ap": Date.MOD_AFTER, + # u'>' : Date.MOD_AFTER, # Worrying about XML/HTML parsing + "environ": Date.MOD_ABOUT, + "env.": Date.MOD_ABOUT, + "env": Date.MOD_ABOUT, + "circa": Date.MOD_ABOUT, + "ca.": Date.MOD_ABOUT, + "ca": Date.MOD_ABOUT, + "c.": Date.MOD_ABOUT, + "vers": Date.MOD_ABOUT, + "~": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } quality_to_int = { - 'estimée': Date.QUAL_ESTIMATED, - 'est.' : Date.QUAL_ESTIMATED, - 'est' : Date.QUAL_ESTIMATED, - 'calculée': Date.QUAL_CALCULATED, - 'calc.' : Date.QUAL_CALCULATED, - 'calc' : Date.QUAL_CALCULATED, - 'comptée' : Date.QUAL_CALCULATED, - 'compt.' : Date.QUAL_CALCULATED, - 'compt' : Date.QUAL_CALCULATED, - } + "estimée": Date.QUAL_ESTIMATED, + "est.": Date.QUAL_ESTIMATED, + "est": Date.QUAL_ESTIMATED, + "calculée": Date.QUAL_CALCULATED, + "calc.": Date.QUAL_CALCULATED, + "calc": Date.QUAL_CALCULATED, + "comptée": Date.QUAL_CALCULATED, + "compt.": Date.QUAL_CALCULATED, + "compt": Date.QUAL_CALCULATED, + } - bce = ["avant le calendrier", "avant notre ère", "avant JC", - "avant J.C"] + DateParser.bce + bce = [ + "avant le calendrier", + "avant notre ère", + "avant JC", + "avant J.C", + ] + DateParser.bce def init_strings(self): """ @@ -104,126 +110,139 @@ class DateParserFR(DateParser): """ DateParser.init_strings(self) - DateParser.calendar_to_int.update({ - 'révolutionnaire' : Date.CAL_FRENCH, - 'r' : Date.CAL_FRENCH, - 'perse' : Date.CAL_PERSIAN, - }) + DateParser.calendar_to_int.update( + { + "révolutionnaire": Date.CAL_FRENCH, + "r": Date.CAL_FRENCH, + "perse": Date.CAL_PERSIAN, + } + ) - DateParser.month_to_int.update({ - "januaris" : 1, - "januarii" : 1, - "januarius" : 1, - "janer" : 1, - "jänner" : 1, - "jenner" : 1, - "hartmonat" : 1, - "hartung" : 1, - "horn" : 1, - "eismond" : 1, - "februaris" : 2, - "februarii" : 2, - "februarius" : 2, - "hornig" : 2, - "hornung" : 2, - "wintermonat" : 2, - "taumond" : 2, - "narrenmond" : 2, - "martii" : 3, - "martius" : 3, - "lenzing" : 3, - "aprilis" : 4, - "ostermond" : 4, - "maius" : 5, - "maii" : 5, - "maien" : 5, - "bluviose" : 5, - "wonnemond" : 5, - "wiesenmonat" : 5, - "junius" : 6, - "junii" : 6, - "vendose" : 6, - "brachet" : 6, - "julius" : 7, - "julii" : 7, - "heuet" : 7, - "heuert" : 7, - "augustus" : 8, - "augusti" : 8, - "ernting" : 8, - "septembris" : 9, - "7bre" : 9, - "7bris" : 9, - "september" : 9, - "scheidling" : 9, - "october" : 10, - "octobris" : 10, - "8bre" : 10, - "8bris" : 10, - "gilbhard" : 10, - "november" : 11, - "novembris" : 11, - "9bre" : 11, - "9bris" : 11, - "nebelmonat" : 11, - "nebelung" : 11, - "december" : 12, - "decembris" : 12, - "10bre" : 12, - "10bris" : 12, - "xbre" : 12, - "xbris" : 12, - "julmond" : 12, - "christmond" : 12, - }) + DateParser.month_to_int.update( + { + "januaris": 1, + "januarii": 1, + "januarius": 1, + "janer": 1, + "jänner": 1, + "jenner": 1, + "hartmonat": 1, + "hartung": 1, + "horn": 1, + "eismond": 1, + "februaris": 2, + "februarii": 2, + "februarius": 2, + "hornig": 2, + "hornung": 2, + "wintermonat": 2, + "taumond": 2, + "narrenmond": 2, + "martii": 3, + "martius": 3, + "lenzing": 3, + "aprilis": 4, + "ostermond": 4, + "maius": 5, + "maii": 5, + "maien": 5, + "bluviose": 5, + "wonnemond": 5, + "wiesenmonat": 5, + "junius": 6, + "junii": 6, + "vendose": 6, + "brachet": 6, + "julius": 7, + "julii": 7, + "heuet": 7, + "heuert": 7, + "augustus": 8, + "augusti": 8, + "ernting": 8, + "septembris": 9, + "7bre": 9, + "7bris": 9, + "september": 9, + "scheidling": 9, + "october": 10, + "octobris": 10, + "8bre": 10, + "8bris": 10, + "gilbhard": 10, + "november": 11, + "novembris": 11, + "9bre": 11, + "9bris": 11, + "nebelmonat": 11, + "nebelung": 11, + "december": 12, + "decembris": 12, + "10bre": 12, + "10bris": 12, + "xbre": 12, + "xbris": 12, + "julmond": 12, + "christmond": 12, + } + ) # This self._numeric is different from the base # avoid bug gregorian / french calendar conversion (+/-10 days) self._numeric = re.compile(r"((\d+)[/\. ])?\s*((\d+)[/\.])?\s*(\d+)\s*$") - self._span = re.compile(r"(de)\s+(?P.+)\s+(à)\s+(?P.+)", - re.IGNORECASE) - self._range = re.compile(r"(entre|ent\.|ent)\s+(?P.+)\s+(et)\s+(?P.+)", - re.IGNORECASE) + self._span = re.compile( + r"(de)\s+(?P.+)\s+(à)\s+(?P.+)", re.IGNORECASE + ) + self._range = re.compile( + r"(entre|ent\.|ent)\s+(?P.+)\s+(et)\s+(?P.+)", re.IGNORECASE + ) # This self._text are different from the base # by adding ".?" after the first date and removing "\s*$" at the end - #gregorian and julian + # gregorian and julian - self._text2 = re.compile(r'(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' % - self._mon_str, re.IGNORECASE) + self._text2 = re.compile( + r"(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?" % self._mon_str, re.IGNORECASE + ) - #hebrew + # hebrew - self._jtext2 = re.compile(r'(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' % - self._jmon_str, re.IGNORECASE) + self._jtext2 = re.compile( + r"(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?" % self._jmon_str, re.IGNORECASE + ) - #french + # french - self._ftext2 = re.compile(r'(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' % - self._fmon_str, re.IGNORECASE) + self._ftext2 = re.compile( + r"(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?" % self._fmon_str, re.IGNORECASE + ) - #persian + # persian - self._ptext2 = re.compile(r'(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' % - self._pmon_str, re.IGNORECASE) + self._ptext2 = re.compile( + r"(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?" % self._pmon_str, re.IGNORECASE + ) - #islamic + # islamic - self._itext2 = re.compile(r'(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' % - self._imon_str, re.IGNORECASE) + self._itext2 = re.compile( + r"(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?" % self._imon_str, re.IGNORECASE + ) - #swedish + # swedish - self._stext2 = re.compile(r'(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' % - self._smon_str, re.IGNORECASE) + self._stext2 = re.compile( + r"(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?" % self._smon_str, re.IGNORECASE + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # French display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayFR(DateDisplay): """ French language date display class. @@ -232,23 +251,25 @@ class DateDisplayFR(DateDisplay): _bce_str = "%s avant le calendrier" def formats_changed(self): - """ Allow overriding so a subclass can modify """ + """Allow overriding so a subclass can modify""" # Replace the previous "Numérique" by a string which # do have an explicit meaning: "System default (format)" example = self.dhformat - example = example.replace('%d', "J") - example = example.replace('%m', "M") - example = example.replace('%Y', "A") + example = example.replace("%d", "J") + example = example.replace("%m", "M") + example = example.replace("%Y", "A") - self.formats = ("AAAA-MM-JJ (ISO)", # 0 - "Défaut système (" + example + ")", # 1 - "Jour Mois Année", # 2 - "Jour MOI Année", # 3 - "Jour. Mois Année", # 4 - "Jour. MOI Année", # 5 - "Mois Jour, Année", # 6 - "MOI Jour, Année",) # 7 + self.formats = ( + "AAAA-MM-JJ (ISO)", # 0 + "Défaut système (" + example + ")", # 1 + "Jour Mois Année", # 2 + "Jour MOI Année", # 3 + "Jour. Mois Année", # 4 + "Jour. MOI Année", # 5 + "Mois Jour, Année", # 6 + "MOI Jour, Année", + ) # 7 # this definition must agree with its "_display_gregorian" method def _display_gregorian(self, date_val, **kwargs): @@ -272,14 +293,14 @@ class DateDisplayFR(DateDisplay): if date_val[0] == date_val[1] == 0: value = str(date_val[2]) else: - value = self.dhformat.replace('%m', str(date_val[1])) - value = value.replace('%d', str(date_val[0])) + value = self.dhformat.replace("%m", str(date_val[1])) + value = value.replace("%d", str(date_val[0])) # base_display : # value = value.replace('%Y', str(abs(date_val[2]))) # value = value.replace('-', '/') - value = value.replace('%Y', str(date_val[2])) + value = value.replace("%Y", str(date_val[2])) elif self.format == 2: # day month_name year @@ -291,8 +312,7 @@ class DateDisplayFR(DateDisplay): value = "%s %s" % (self.long_months[date_val[1]], year) else: - value = "%d %s %s" % (date_val[0], - self.long_months[date_val[1]], year) + value = "%d %s %s" % (date_val[0], self.long_months[date_val[1]], year) elif self.format == 3: # day month_abbreviation year @@ -304,8 +324,7 @@ class DateDisplayFR(DateDisplay): value = "%s %s" % (self.short_months[date_val[1]], year) else: - value = "%d %s %s" % (date_val[0], - self.short_months[date_val[1]], year) + value = "%d %s %s" % (date_val[0], self.short_months[date_val[1]], year) elif self.format == 4: # day. month_name year @@ -321,9 +340,7 @@ class DateDisplayFR(DateDisplay): # value = "%d %s %s" % (date_val[0], # self.long_months[date_val[1]], year) - value = "%d. %s %s" % (date_val[0], - self.long_months[date_val[1]], - year) + value = "%d. %s %s" % (date_val[0], self.long_months[date_val[1]], year) elif self.format == 5: # day. month_abbreviation year @@ -339,8 +356,11 @@ class DateDisplayFR(DateDisplay): # value = "%d %s %s" % (date_val[0], # self.short_months[date_val[1]], year) - value = "%d. %s %s" % (date_val[0], - self.short_months[date_val[1]], year) + value = "%d. %s %s" % ( + date_val[0], + self.short_months[date_val[1]], + year, + ) elif self.format == 6: # month_name day, year @@ -351,8 +371,7 @@ class DateDisplayFR(DateDisplay): else: value = "%s %s" % (self.long_months[date_val[1]], year) else: - value = "%s %d, %s" % (self.long_months[date_val[1]], - date_val[0], year) + value = "%s %d, %s" % (self.long_months[date_val[1]], date_val[0], year) elif self.format == 7: # month_abbreviation day, year @@ -363,8 +382,11 @@ class DateDisplayFR(DateDisplay): else: value = "%s %s" % (self.short_months[date_val[1]], year) else: - value = "%s %d, %s" % (self.short_months[date_val[1]], - date_val[0], year) + value = "%s %d, %s" % ( + self.short_months[date_val[1]], + date_val[0], + year, + ) else: return self.display_iso(date_val) @@ -375,13 +397,15 @@ class DateDisplayFR(DateDisplay): display = DateDisplay.display_formatted -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('fr_FR', 'fr', 'french', 'French', 'fr_CA', - 'fr_BE', 'fr_CH', ('%d/%m/%Y',)), - DateParserFR, DateDisplayFR) + ("fr_FR", "fr", "french", "French", "fr_CA", "fr_BE", "fr_CH", ("%d/%m/%Y",)), + DateParserFR, + DateDisplayFR, +) diff --git a/gramps/gen/datehandler/_date_hr.py b/gramps/gen/datehandler/_date_hr.py index 5ba085678..38ef8fd1b 100644 --- a/gramps/gen/datehandler/_date_hr.py +++ b/gramps/gen/datehandler/_date_hr.py @@ -28,50 +28,51 @@ Croatian-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Croatian parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserHR(DateParser): modifier_to_int = { - 'prije' : Date.MOD_BEFORE, - 'pr. ' : Date.MOD_BEFORE, - 'poslije' : Date.MOD_AFTER, - 'po. ' : Date.MOD_AFTER, - 'nakon' : Date.MOD_AFTER, - 'na. ' : Date.MOD_AFTER, - 'oko' : Date.MOD_ABOUT, - 'okolo' : Date.MOD_ABOUT, - 'ok. ' : Date.MOD_ABOUT, - } + "prije": Date.MOD_BEFORE, + "pr. ": Date.MOD_BEFORE, + "poslije": Date.MOD_AFTER, + "po. ": Date.MOD_AFTER, + "nakon": Date.MOD_AFTER, + "na. ": Date.MOD_AFTER, + "oko": Date.MOD_ABOUT, + "okolo": Date.MOD_ABOUT, + "ok. ": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } quality_to_int = { - 'približno' : Date.QUAL_ESTIMATED, - 'prb.' : Date.QUAL_ESTIMATED, - 'izračunato' : Date.QUAL_CALCULATED, - 'izr.' : Date.QUAL_CALCULATED, - } + "približno": Date.QUAL_ESTIMATED, + "prb.": Date.QUAL_ESTIMATED, + "izračunato": Date.QUAL_CALCULATED, + "izr.": Date.QUAL_CALCULATED, + } - bce = ["prije nove ere", "prije Krista", - "p.n.e."] + DateParser.bce + bce = ["prije nove ere", "prije Krista", "p.n.e."] + DateParser.bce def init_strings(self): """ @@ -80,71 +81,86 @@ class DateParserHR(DateParser): DateParser.init_strings(self) # match 'Day. MONTH year.' format with or without dots - self._text2 = re.compile(r'(\d+)?\.?\s*?%s\.?\s*((\d+)(/\d+)?)?\s*\.?$' - % self._mon_str, re.IGNORECASE) + self._text2 = re.compile( + r"(\d+)?\.?\s*?%s\.?\s*((\d+)(/\d+)?)?\s*\.?$" % self._mon_str, + re.IGNORECASE, + ) # match Day.Month.Year. - self._numeric = re.compile( - r"((\d+)[/\. ])?\s*((\d+)[/\.])?\s*(\d+)\.?$") + self._numeric = re.compile(r"((\d+)[/\. ])?\s*((\d+)[/\.])?\s*(\d+)\.?$") - self._jtext2 = re.compile(r'(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' - % self._jmon_str, re.IGNORECASE) + self._jtext2 = re.compile( + r"(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?" % self._jmon_str, re.IGNORECASE + ) - _span_1 = ['od'] - _span_2 = ['do'] - _range_1 = ['između'] - _range_2 = ['i'] - self._span = re.compile(r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" - % ('|'.join(_span_1), '|'.join(_span_2)), - re.IGNORECASE) - self._range = re.compile(r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" - % ('|'.join(_range_1), '|'.join(_range_2)), - re.IGNORECASE) + _span_1 = ["od"] + _span_2 = ["do"] + _range_1 = ["između"] + _range_2 = ["i"] + self._span = re.compile( + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) + self._range = re.compile( + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Croatian display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayHR(DateDisplay): """ Croatian language date display class. """ - # TODO fix BUG 7064: non-Gregorian calendars wrongly use BCE notation for negative dates + + # TODO fix BUG 7064: non-Gregorian calendars wrongly use BCE notation for negative dates # not refactoring _bce_str into base class because it'll be gone under #7064 _bce_str = "%s p.n.e." display = DateDisplay.display_formatted def format_short_month_year(self, month, year, inflect, short_months): - """ Allow a subclass to modify the year, e.g. add a period """ - if not hasattr(short_months[1], 'f'): # not a Lexeme: no inflection + """Allow a subclass to modify the year, e.g. add a period""" + if not hasattr(short_months[1], "f"): # not a Lexeme: no inflection return "{short_month} {year}.".format( - short_month = short_months[month], year = year) + short_month=short_months[month], year=year + ) return self.FORMATS_short_month_year[inflect].format( - short_month = short_months[month], year = year) + short_month=short_months[month], year=year + ) def _get_localized_year(self, year): - """ Allow a subclass to modify the year, e.g. add a period """ - return year + '.' + """Allow a subclass to modify the year, e.g. add a period""" + return year + "." # FIXME probably there should be a Croatian-specific "formats" (and this # ("American comma") format (and dd_dformat03 too) should be eliminated) def dd_dformat02(self, date_val, inflect, long_months): - """ month_name day, year """ - return DateDisplay.dd_dformat02( - self, date_val, inflect, long_months).replace(' .', '') + """month_name day, year""" + return DateDisplay.dd_dformat02(self, date_val, inflect, long_months).replace( + " .", "" + ) def dd_dformat04(self, date_val, inflect, long_months): - """ day month_name year """ - return DateDisplay.dd_dformat04( - self, date_val, inflect, long_months).replace(' .', '') + """day month_name year""" + return DateDisplay.dd_dformat04(self, date_val, inflect, long_months).replace( + " .", "" + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('hr_HR', 'hr', 'HR', 'croatian', 'Croatian', 'hrvatski', ('%d. %m. %Y.',)), - DateParserHR, DateDisplayHR) + ("hr_HR", "hr", "HR", "croatian", "Croatian", "hrvatski", ("%d. %m. %Y.",)), + DateParserHR, + DateDisplayHR, +) diff --git a/gramps/gen/datehandler/_date_hu.py b/gramps/gen/datehandler/_date_hu.py index 119b1cfae..22d86dc36 100644 --- a/gramps/gen/datehandler/_date_hu.py +++ b/gramps/gen/datehandler/_date_hu.py @@ -24,226 +24,233 @@ Hungarian-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Hungarian parser # # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserHU(DateParser): - month_to_int = DateParser.month_to_int - month_to_int["-"]=0 #to make the Zero month to work + month_to_int["-"] = 0 # to make the Zero month to work month_to_int["január"] = 1 month_to_int["jan"] = 1 month_to_int["jan."] = 1 month_to_int["I"] = 1 -# month_to_int["i"] = 1 + # month_to_int["i"] = 1 month_to_int["február"] = 2 month_to_int["feb"] = 2 month_to_int["feb."] = 2 month_to_int["II"] = 2 -# month_to_int["ii"] = 2 + # month_to_int["ii"] = 2 month_to_int["március"] = 3 month_to_int["márc"] = 3 month_to_int["márc."] = 3 month_to_int["III"] = 3 -# month_to_int["iii"] = 3 + # month_to_int["iii"] = 3 month_to_int["április"] = 4 month_to_int["ápr"] = 4 month_to_int["ápr."] = 4 month_to_int["IV"] = 4 -# month_to_int["iv"] = 4 + # month_to_int["iv"] = 4 month_to_int["május"] = 5 month_to_int["máj"] = 5 month_to_int["máj."] = 5 month_to_int["V"] = 5 -# month_to_int["v"] = 5 + # month_to_int["v"] = 5 month_to_int["június"] = 6 month_to_int["jún"] = 6 month_to_int["jún."] = 6 month_to_int["VI"] = 6 -# month_to_int["vi"] = 6 + # month_to_int["vi"] = 6 month_to_int["július"] = 7 month_to_int["júl"] = 7 month_to_int["júl."] = 7 month_to_int["VII"] = 7 -# month_to_int["vii"] = 7 + # month_to_int["vii"] = 7 month_to_int["augusztus"] = 8 month_to_int["aug"] = 8 month_to_int["aug."] = 8 month_to_int["VIII"] = 8 -# month_to_int["viii"] = 8 + # month_to_int["viii"] = 8 month_to_int["szeptember"] = 9 month_to_int["szept"] = 9 month_to_int["szept."] = 9 month_to_int["IX"] = 9 -# month_to_int["ix"] = 9 + # month_to_int["ix"] = 9 month_to_int["október"] = 10 month_to_int["okt"] = 10 month_to_int["okt."] = 10 month_to_int["X"] = 10 -# month_to_int["x"] = 10 + # month_to_int["x"] = 10 month_to_int["november"] = 11 month_to_int["nov"] = 11 month_to_int["nov."] = 11 month_to_int["XI"] = 11 -# month_to_int["xi"] = 11 + # month_to_int["xi"] = 11 month_to_int["december"] = 12 month_to_int["dec"] = 12 month_to_int["dec."] = 12 month_to_int["XII"] = 12 -# month_to_int["xii"] = 12 + # month_to_int["xii"] = 12 - -#----------------------------------------------------------------------- -# -# Alternative and latin names - not verified -# -#----------------------------------------------------------------------- + # ----------------------------------------------------------------------- + # + # Alternative and latin names - not verified + # + # ----------------------------------------------------------------------- # Other common latin names -# month_to_int["januaris"] = 01 -# month_to_int["januarii"] = 01 -# month_to_int["januarius"] = 01 -# month_to_int["februaris"] = 02 -# month_to_int["februarii"] = 02 -# month_to_int["februarius"] = 02 -# month_to_int["martii"] = 03 -# month_to_int["martius"] = 03 -# month_to_int["aprilis"] = 04 -# month_to_int["maius"] = 05 -# month_to_int["maii"] = 05 -# month_to_int["junius"] = 06 -# month_to_int["junii"] = 06 -# month_to_int["julius"] = 07 -# month_to_int["julii"] = 07 -# month_to_int["augustus"] = 08 -# month_to_int["augusti"] = 08 -# month_to_int["septembris"] = 09 -# month_to_int["7bris"] = 09 -# month_to_int["september"] = 09 -# month_to_int["october"] = 10 -# month_to_int["octobris"] = 10 -# month_to_int["8bris"] = 10 -# month_to_int["novembris"] = 11 -# month_to_int["9bris"] = 11 -# month_to_int["november"] = 11 -# month_to_int["decembris"] = 12 -# month_to_int["10bris"] = 12 -# month_to_int["xbris"] = 12 -# month_to_int["december"] = 12 + # month_to_int["januaris"] = 01 + # month_to_int["januarii"] = 01 + # month_to_int["januarius"] = 01 + # month_to_int["februaris"] = 02 + # month_to_int["februarii"] = 02 + # month_to_int["februarius"] = 02 + # month_to_int["martii"] = 03 + # month_to_int["martius"] = 03 + # month_to_int["aprilis"] = 04 + # month_to_int["maius"] = 05 + # month_to_int["maii"] = 05 + # month_to_int["junius"] = 06 + # month_to_int["junii"] = 06 + # month_to_int["julius"] = 07 + # month_to_int["julii"] = 07 + # month_to_int["augustus"] = 08 + # month_to_int["augusti"] = 08 + # month_to_int["septembris"] = 09 + # month_to_int["7bris"] = 09 + # month_to_int["september"] = 09 + # month_to_int["october"] = 10 + # month_to_int["octobris"] = 10 + # month_to_int["8bris"] = 10 + # month_to_int["novembris"] = 11 + # month_to_int["9bris"] = 11 + # month_to_int["november"] = 11 + # month_to_int["decembris"] = 12 + # month_to_int["10bris"] = 12 + # month_to_int["xbris"] = 12 + # month_to_int["december"] = 12 # old Hungarian names -# month_to_int["Boldogasszony hava"] = 01 -# month_to_int["Fergeteg hava"] = 01 -# month_to_int["Böjtelő hava"] = 02 -# month_to_int["Jégbontó hava"] = 02 -# month_to_int["Böjtmás hava"] = 03 -# month_to_int["Kikelet hava"] = 03 -# month_to_int["Szent György hava"] = 04 -# month_to_int["Szelek hava"] = 04 -# month_to_int["Pünkösd hava"] = 05 -# month_to_int["Ígéret hava"] = 05 -# month_to_int["Szent Iván hava"] = 06 -# month_to_int["Napisten hava"] = 06 -# month_to_int["Szent Jakab hava"] = 07 -# month_to_int["Áldás hava"] = 07 -# month_to_int["Kisasszony hava"] = 08 -# month_to_int["Újkenyér hava"] = 08 -# month_to_int["Szent Mihály hava"] = 09 -# month_to_int["Földanya hava"] = 09 -# month_to_int["Mindszent hava"] = 10 -# month_to_int["Magvető hava"] = 10 -# month_to_int["Szent András hava"] = 11 -# month_to_int["Enyészet hava"] = 11 -# month_to_int["Karácsony hava"] = 12 -# month_to_int["Álom hava"] = 12 + # month_to_int["Boldogasszony hava"] = 01 + # month_to_int["Fergeteg hava"] = 01 + # month_to_int["Böjtelő hava"] = 02 + # month_to_int["Jégbontó hava"] = 02 + # month_to_int["Böjtmás hava"] = 03 + # month_to_int["Kikelet hava"] = 03 + # month_to_int["Szent György hava"] = 04 + # month_to_int["Szelek hava"] = 04 + # month_to_int["Pünkösd hava"] = 05 + # month_to_int["Ígéret hava"] = 05 + # month_to_int["Szent Iván hava"] = 06 + # month_to_int["Napisten hava"] = 06 + # month_to_int["Szent Jakab hava"] = 07 + # month_to_int["Áldás hava"] = 07 + # month_to_int["Kisasszony hava"] = 08 + # month_to_int["Újkenyér hava"] = 08 + # month_to_int["Szent Mihály hava"] = 09 + # month_to_int["Földanya hava"] = 09 + # month_to_int["Mindszent hava"] = 10 + # month_to_int["Magvető hava"] = 10 + # month_to_int["Szent András hava"] = 11 + # month_to_int["Enyészet hava"] = 11 + # month_to_int["Karácsony hava"] = 12 + # month_to_int["Álom hava"] = 12 modifier_to_int = { - 'előtt' : Date.MOD_BEFORE, - 'körül' : Date.MOD_ABOUT, - 'után' : Date.MOD_AFTER, - } + "előtt": Date.MOD_BEFORE, + "körül": Date.MOD_ABOUT, + "után": Date.MOD_AFTER, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } quality_to_int = { - 'becsült' : Date.QUAL_ESTIMATED, - 'hozzávetőleg' : Date.QUAL_ESTIMATED, - 'becs.' : Date.QUAL_ESTIMATED, - 'számított' : Date.QUAL_CALCULATED, - 'körülbelül' : Date.QUAL_ESTIMATED, - 'számolt' : Date.QUAL_CALCULATED, - 'szám.' : Date.QUAL_CALCULATED, - } - - bce = ["időszámításunk előtt", "időszámítás előtt", "i. e.", - "Krisztus előtt", "Krisztus előtti", "Kr. e."] + DateParser.bce + "becsült": Date.QUAL_ESTIMATED, + "hozzávetőleg": Date.QUAL_ESTIMATED, + "becs.": Date.QUAL_ESTIMATED, + "számított": Date.QUAL_CALCULATED, + "körülbelül": Date.QUAL_ESTIMATED, + "számolt": Date.QUAL_CALCULATED, + "szám.": Date.QUAL_CALCULATED, + } + bce = [ + "időszámításunk előtt", + "időszámítás előtt", + "i. e.", + "Krisztus előtt", + "Krisztus előtti", + "Kr. e.", + ] + DateParser.bce calendar_to_int = { - 'Gergely' : Date.CAL_GREGORIAN, - 'Julián' : Date.CAL_JULIAN, - 'julián' : Date.CAL_JULIAN, - 'héber' : Date.CAL_HEBREW, - 'iszlám' : Date.CAL_ISLAMIC, - 'francia köztársasági' : Date.CAL_FRENCH, - 'perzsa' : Date.CAL_PERSIAN, - 'svéd' : Date.CAL_SWEDISH, - } - + "Gergely": Date.CAL_GREGORIAN, + "Julián": Date.CAL_JULIAN, + "julián": Date.CAL_JULIAN, + "héber": Date.CAL_HEBREW, + "iszlám": Date.CAL_ISLAMIC, + "francia köztársasági": Date.CAL_FRENCH, + "perzsa": Date.CAL_PERSIAN, + "svéd": Date.CAL_SWEDISH, + } def init_strings(self): # Compiles regular expression strings for matching dates DateParser.init_strings(self) - self._numeric = re.compile( - r"((\d+)[/\.])?\s*((\d+)[/\.])?\s*(\d+)[/\. ]?$") + self._numeric = re.compile(r"((\d+)[/\.])?\s*((\d+)[/\.])?\s*(\d+)[/\. ]?$") # this next RE has the (possibly-slashed) year at the string's start - self._text2 = re.compile(r'((\d+)(/\d+)?\.)?\s+?%s\.?\s*(\d+\.)?\s*$' - % self._mon_str, re.IGNORECASE) - _span_1 = [r'-tó\(ő\)l', '-tól', '-től'] - _span_2 = ['-ig'] - _range_1 = ['és'] - _range_2 = ['között'] - self._span = re.compile(r"(?P.+)(%s)\s+(?P.+)(%s)" % - ('|'.join(_span_1), '|'.join(_span_2)), - re.IGNORECASE) - self._range = re.compile(r"(?P.+)\s+(%s)\s+(?P.+)\s+(%s)" - % ('|'.join(_range_1), '|'.join(_range_2)), - re.IGNORECASE) - + self._text2 = re.compile( + r"((\d+)(/\d+)?\.)?\s+?%s\.?\s*(\d+\.)?\s*$" % self._mon_str, re.IGNORECASE + ) + _span_1 = [r"-tó\(ő\)l", "-tól", "-től"] + _span_2 = ["-ig"] + _range_1 = ["és"] + _range_2 = ["között"] + self._span = re.compile( + r"(?P.+)(%s)\s+(?P.+)(%s)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) + self._range = re.compile( + r"(?P.+)\s+(%s)\s+(?P.+)\s+(%s)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) def _get_int(self, val): """ @@ -253,13 +260,14 @@ class DateParserHU(DateParser): if val is None: return 0 else: - return int(val.replace('.', '')) + return int(val.replace(".", "")) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Hungarian display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayHU(DateDisplay): """ Hungarian language date display class. @@ -267,24 +275,34 @@ class DateDisplayHU(DateDisplay): _bce_str = "i. e. %s" - roman_months=( - "-.", "I.", "II.", "III.", "IV.", "V.", "VI.", - "VII.", "VIII.", "IX.", "X.", "XI.", "XII." - ) + roman_months = ( + "-.", + "I.", + "II.", + "III.", + "IV.", + "V.", + "VI.", + "VII.", + "VIII.", + "IX.", + "X.", + "XI.", + "XII.", + ) formats = ( - "ÉÉÉÉ-HH-NN (ISO)", # 0 - "Alapértelmezett éééé. hh. nn.", # 1 - "Év hónap nap", # year, full month name, day # 2 - "Év hó nap", #year, short month name, day # 3 - "Év római h.sz. nap" #year, Roman number, day # 4 - ) - # this definition must agree with its "_display_calendar" method + "ÉÉÉÉ-HH-NN (ISO)", # 0 + "Alapértelmezett éééé. hh. nn.", # 1 + "Év hónap nap", # year, full month name, day # 2 + "Év hó nap", # year, short month name, day # 3 + "Év római h.sz. nap", # year, Roman number, day # 4 + ) + # this definition must agree with its "_display_calendar" method display = DateDisplay.display_formatted - def _display_calendar(self, date_val, long_months, short_months = None, - inflect=""): + def _display_calendar(self, date_val, long_months, short_months=None, inflect=""): # this must agree with its locale-specific "formats" definition year = self._slash_year(date_val[2], date_val[3]) @@ -301,55 +319,84 @@ class DateDisplayHU(DateDisplay): if date_val[3]: return self.display_iso(date_val) else: - if date_val[0]==0: #No day - if date_val[1]==0: #No month -> year - value="%s" % year + if date_val[0] == 0: # No day + if date_val[1] == 0: # No month -> year + value = "%s" % year else: - value="%s. %02d." % (year, date_val[1]) #If no day -> year, month + value = "%s. %02d." % ( + year, + date_val[1], + ) # If no day -> year, month else: - value="%s. %02d. %02d." % (year, date_val[1], date_val[0]) + value = "%s. %02d. %02d." % (year, date_val[1], date_val[0]) elif self.format == 2: # year, full month name, day - if date_val[0]==0: - if date_val[1]==0: - value="%s" % year + if date_val[0] == 0: + if date_val[1] == 0: + value = "%s" % year else: - value="%s. %s" % (year, self.long_months[date_val[1]]) #If no day -> year, month + value = "%s. %s" % ( + year, + self.long_months[date_val[1]], + ) # If no day -> year, month else: - if date_val[1]==0: - value="%s. %s %02d." % (year, '-', date_val[0]) #To indicate somehow if the month is missing - else: - value="%s. %s %02d." % (year, self.long_months[date_val[1]], date_val[0]) - + if date_val[1] == 0: + value = "%s. %s %02d." % ( + year, + "-", + date_val[0], + ) # To indicate somehow if the month is missing + else: + value = "%s. %s %02d." % ( + year, + self.long_months[date_val[1]], + date_val[0], + ) elif self.format == 3: - #year, short month name, day + # year, short month name, day - if date_val[0]==0: - if date_val[1]==0: - value="%s" % year + if date_val[0] == 0: + if date_val[1] == 0: + value = "%s" % year else: - value="%s. %s" % (year, self.short_months[date_val[1]]) #If no day -> year, month + value = "%s. %s" % ( + year, + self.short_months[date_val[1]], + ) # If no day -> year, month else: - if date_val[1]==0: - value="%s. %s %02d." % (year, '-.', date_val[0]) #To indicate somehow if the month is missing - else: - value="%s. %s %02d." % (year, self.short_months[date_val[1]], date_val[0]) - + if date_val[1] == 0: + value = "%s. %s %02d." % ( + year, + "-.", + date_val[0], + ) # To indicate somehow if the month is missing + else: + value = "%s. %s %02d." % ( + year, + self.short_months[date_val[1]], + date_val[0], + ) elif self.format == 4: - #year, Roman number, day + # year, Roman number, day - if date_val[0]==0: - if date_val[1]==0: - value="%s" % year + if date_val[0] == 0: + if date_val[1] == 0: + value = "%s" % year else: - value="%s. %s" % (year, self.roman_months[date_val[1]]) #If no day -> year, month + value = "%s. %s" % ( + year, + self.roman_months[date_val[1]], + ) # If no day -> year, month else: - value="%s. %s %02d." % (year, self.roman_months[date_val[1]], date_val[0]) - + value = "%s. %s %02d." % ( + year, + self.roman_months[date_val[1]], + date_val[0], + ) else: # day month_name year @@ -361,11 +408,14 @@ class DateDisplayHU(DateDisplay): else: return value -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('hu_HU', 'hu', 'hungarian', 'Hungarian', 'magyar', ('%Y-%m-%d',)), - DateParserHU, DateDisplayHU) + ("hu_HU", "hu", "hungarian", "Hungarian", "magyar", ("%Y-%m-%d",)), + DateParserHU, + DateDisplayHU, +) diff --git a/gramps/gen/datehandler/_date_is.py b/gramps/gen/datehandler/_date_is.py index f8dec9392..cf6c81144 100644 --- a/gramps/gen/datehandler/_date_is.py +++ b/gramps/gen/datehandler/_date_is.py @@ -24,29 +24,29 @@ Icelandic-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re import datetime -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Icelandic parser class # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserIs(DateParser): """ Convert a text string into a Date object, expecting a date @@ -56,39 +56,41 @@ class DateParserIs(DateParser): # modifiers before the date modifier_to_int = { - 'fyrir' : Date.MOD_BEFORE, - 'á undan' : Date.MOD_BEFORE, - 'eftir' : Date.MOD_AFTER, - 'í kringum' : Date.MOD_ABOUT, - 'uþb' : Date.MOD_ABOUT, - 'um' : Date.MOD_ABOUT, - } + "fyrir": Date.MOD_BEFORE, + "á undan": Date.MOD_BEFORE, + "eftir": Date.MOD_AFTER, + "í kringum": Date.MOD_ABOUT, + "uþb": Date.MOD_ABOUT, + "um": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } bce = ["f Kr"] calendar_to_int = { - 'gregoríanskt ' : Date.CAL_GREGORIAN, - 'g' : Date.CAL_GREGORIAN, - 'júlíanskt' : Date.CAL_JULIAN, - 'j' : Date.CAL_JULIAN, - 'hebreskt' : Date.CAL_HEBREW, - 'h' : Date.CAL_HEBREW, - 'íslamskt' : Date.CAL_ISLAMIC, - 'múslimskt' : Date.CAL_ISLAMIC, - 'i' : Date.CAL_ISLAMIC, - 'franskt' : Date.CAL_FRENCH, - 'franska lýðveldisins' : Date.CAL_FRENCH, - 'f' : Date.CAL_FRENCH, - 'persneskt' : Date.CAL_PERSIAN, - 'p' : Date.CAL_PERSIAN, - 'sænskt' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - } + "gregoríanskt ": Date.CAL_GREGORIAN, + "g": Date.CAL_GREGORIAN, + "júlíanskt": Date.CAL_JULIAN, + "j": Date.CAL_JULIAN, + "hebreskt": Date.CAL_HEBREW, + "h": Date.CAL_HEBREW, + "íslamskt": Date.CAL_ISLAMIC, + "múslimskt": Date.CAL_ISLAMIC, + "i": Date.CAL_ISLAMIC, + "franskt": Date.CAL_FRENCH, + "franska lýðveldisins": Date.CAL_FRENCH, + "f": Date.CAL_FRENCH, + "persneskt": Date.CAL_PERSIAN, + "p": Date.CAL_PERSIAN, + "sænskt": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } quality_to_int = { - 'áætlað' : Date.QUAL_ESTIMATED, - 'reiknað' : Date.QUAL_CALCULATED, - } + "áætlað": Date.QUAL_ESTIMATED, + "reiknað": Date.QUAL_CALCULATED, + } def dhformat_changed(self): self._dhformat_parse = re.compile(r".*%(\S).*%(\S).*%(\S).*%(\S).*") @@ -97,34 +99,63 @@ class DateParserIs(DateParser): DateParser.init_strings(self) # match 'day. month year' format - self._text2 = re.compile(r'(\d+)?\.?\s*?%s\.?\s*((\d+)(/\d+)?)?\s*$' - % self._mon_str, re.IGNORECASE) + self._text2 = re.compile( + r"(\d+)?\.?\s*?%s\.?\s*((\d+)(/\d+)?)?\s*$" % self._mon_str, re.IGNORECASE + ) # match 'short-day day.month year' format - short_day_str = '(' + '|'.join(self._ds.short_days[1:]) + ')' - self._numeric = re.compile(r"%s\s*((\d+)[\.]\s*)?((\d+)\s*)?(\d+)\s*$" - % short_day_str, re.IGNORECASE) + short_day_str = "(" + "|".join(self._ds.short_days[1:]) + ")" + self._numeric = re.compile( + r"%s\s*((\d+)[\.]\s*)?((\d+)\s*)?(\d+)\s*$" % short_day_str, re.IGNORECASE + ) self._span = re.compile( - r"(frá)?\s*(?P.+)\s*(til|--|–)\s*(?P.+)", - re.IGNORECASE) + r"(frá)?\s*(?P.+)\s*(til|--|–)\s*(?P.+)", re.IGNORECASE + ) self._range = re.compile( - r"(milli)\s+(?P.+)\s+og\s+(?P.+)", re.IGNORECASE) + r"(milli)\s+(?P.+)\s+og\s+(?P.+)", re.IGNORECASE + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Icelandic display class # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayIs(DateDisplay): """ Icelandic language date display class. """ - long_months = ( "", "janúar", "febrúar", "mars", "apríl", "maí", - "júní", "júlí", "ágúst", "september", "október", - "nóvember", "desember" ) + long_months = ( + "", + "janúar", + "febrúar", + "mars", + "apríl", + "maí", + "júní", + "júlí", + "ágúst", + "september", + "október", + "nóvember", + "desember", + ) - short_months = ( "", "jan", "feb", "mar", "apr", "maí", "jún", - "júl", "ágú", "sep", "okt", "nóv", "des" ) + short_months = ( + "", + "jan", + "feb", + "mar", + "apr", + "maí", + "jún", + "júl", + "ágú", + "sep", + "okt", + "nóv", + "des", + ) formats = ( "ÁÁÁÁ-MM-DD (ISO)", @@ -133,9 +164,9 @@ class DateDisplayIs(DateDisplay): "Mán Dag Ár", "Dagur mánuður ár", "Dag Mán Ár", - ) - # this must agree with DateDisplayEn's "formats" definition - # (since no locale-specific _display_gregorian exists, here) + ) + # this must agree with DateDisplayEn's "formats" definition + # (since no locale-specific _display_gregorian exists, here) calendar = ( "", @@ -144,8 +175,8 @@ class DateDisplayIs(DateDisplay): "franska lýðveldisins", "persneskt", "íslamskt", - "sænskt" - ) + "sænskt", + ) _mod_str = ("", "fyrir ", "eftir ", "uþb ", "", "", "") @@ -178,19 +209,20 @@ class DateDisplayIs(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%smilli %s og %s%s" % (qual_str, d1, d2, - scal) + return "%smilli %s og %s%s" % (qual_str, d1, d2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) - return "%s%s%s%s" % (qual_str, self._mod_str[mod], - text, scal) + return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal) def _get_weekday(self, date_val): - if (date_val[0] == 0 or date_val[1] == 0 # no day or no month or both - or date_val[2] > datetime.MAXYEAR): # bug 10815 - return '' - w_day = datetime.date(date_val[2], date_val[1], date_val[0]) # y, m, d + if ( + date_val[0] == 0 + or date_val[1] == 0 # no day or no month or both + or date_val[2] > datetime.MAXYEAR + ): # bug 10815 + return "" + w_day = datetime.date(date_val[2], date_val[1], date_val[0]) # y, m, d return self.short_days[((w_day.weekday() + 1) % 7) + 1] def dd_dformat01(self, date_val): @@ -203,23 +235,26 @@ class DateDisplayIs(DateDisplay): if date_val[0] == date_val[1] == 0: return str(date_val[2]) else: - value = self.dhformat.replace('%m', str(date_val[1])) + value = self.dhformat.replace("%m", str(date_val[1])) # some locales have %b for the month, e.g. ar_EG, is_IS, nb_NO - value = value.replace('%b', str(date_val[1])) + value = value.replace("%b", str(date_val[1])) # some locales have %a for the abbreviated day, e.g. is_IS - value = value.replace('%a', self._get_weekday(date_val)) - if date_val[0] == 0: # ignore the zero day and its delimiter - i_day = value.find('%e') # Icelandic uses %e and not %d - value = value.replace(value[i_day:i_day+3], '') - value = value.replace('%e', str(date_val[0])) - value = value.replace('%Y', str(abs(date_val[2]))) - return value.replace('-', '/') + value = value.replace("%a", self._get_weekday(date_val)) + if date_val[0] == 0: # ignore the zero day and its delimiter + i_day = value.find("%e") # Icelandic uses %e and not %d + value = value.replace(value[i_day : i_day + 3], "") + value = value.replace("%e", str(date_val[0])) + value = value.replace("%Y", str(abs(date_val[2]))) + return value.replace("-", "/") -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('is_IS', 'is', 'íslenskt', 'Icelandic', ('%a %e.%b %Y',)), - DateParserIs, DateDisplayIs) + ("is_IS", "is", "íslenskt", "Icelandic", ("%a %e.%b %Y",)), + DateParserIs, + DateDisplayIs, +) diff --git a/gramps/gen/datehandler/_date_it.py b/gramps/gen/datehandler/_date_it.py index 06dc531e7..8a814d9fa 100644 --- a/gramps/gen/datehandler/_date_it.py +++ b/gramps/gen/datehandler/_date_it.py @@ -25,133 +25,174 @@ Italian-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Italian parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserIT(DateParser): modifier_to_int = { - 'prima del' : Date.MOD_BEFORE, - 'prima' : Date.MOD_BEFORE, - 'dopo del' : Date.MOD_AFTER, - 'dopo' : Date.MOD_AFTER, - 'approssimativamente' : Date.MOD_ABOUT, - 'apross.' : Date.MOD_ABOUT, - 'apross' : Date.MOD_ABOUT, - 'circa il' : Date.MOD_ABOUT, - 'circa' : Date.MOD_ABOUT, - 'ca.' : Date.MOD_ABOUT, - 'ca' : Date.MOD_ABOUT, - 'c.' : Date.MOD_ABOUT, - } + "prima del": Date.MOD_BEFORE, + "prima": Date.MOD_BEFORE, + "dopo del": Date.MOD_AFTER, + "dopo": Date.MOD_AFTER, + "approssimativamente": Date.MOD_ABOUT, + "apross.": Date.MOD_ABOUT, + "apross": Date.MOD_ABOUT, + "circa il": Date.MOD_ABOUT, + "circa": Date.MOD_ABOUT, + "ca.": Date.MOD_ABOUT, + "ca": Date.MOD_ABOUT, + "c.": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } calendar_to_int = { - 'gregoriano' : Date.CAL_GREGORIAN, - 'g' : Date.CAL_GREGORIAN, - 'giuliano' : Date.CAL_JULIAN, - 'j' : Date.CAL_JULIAN, - 'ebraico' : Date.CAL_HEBREW, - 'e' : Date.CAL_HEBREW, - 'islamico' : Date.CAL_ISLAMIC, - 'i' : Date.CAL_ISLAMIC, - 'rivoluzionario': Date.CAL_FRENCH, - 'r' : Date.CAL_FRENCH, - 'persiano' : Date.CAL_PERSIAN, - 'p' : Date.CAL_PERSIAN, - 'svedese' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - } + "gregoriano": Date.CAL_GREGORIAN, + "g": Date.CAL_GREGORIAN, + "giuliano": Date.CAL_JULIAN, + "j": Date.CAL_JULIAN, + "ebraico": Date.CAL_HEBREW, + "e": Date.CAL_HEBREW, + "islamico": Date.CAL_ISLAMIC, + "i": Date.CAL_ISLAMIC, + "rivoluzionario": Date.CAL_FRENCH, + "r": Date.CAL_FRENCH, + "persiano": Date.CAL_PERSIAN, + "p": Date.CAL_PERSIAN, + "svedese": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } quality_to_int = { - 'stimata' : Date.QUAL_ESTIMATED, - 'st.' : Date.QUAL_ESTIMATED, - 'st' : Date.QUAL_ESTIMATED, - 'calcolata' : Date.QUAL_CALCULATED, - 'calc.' : Date.QUAL_CALCULATED, - 'calc' : Date.QUAL_CALCULATED, - } + "stimata": Date.QUAL_ESTIMATED, + "st.": Date.QUAL_ESTIMATED, + "st": Date.QUAL_ESTIMATED, + "calcolata": Date.QUAL_CALCULATED, + "calc.": Date.QUAL_CALCULATED, + "calc": Date.QUAL_CALCULATED, + } def init_strings(self): DateParser.init_strings(self) - _span_1 = ['dal', 'da'] - _span_2 = ['al', 'a'] - _range_1 = ['tra', 'fra'] - _range_2 = ['e'] - self._span = re.compile(r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_span_1), '|'.join(_span_2)), - re.IGNORECASE) + _span_1 = ["dal", "da"] + _span_2 = ["al", "a"] + _range_1 = ["tra", "fra"] + _range_2 = ["e"] + self._span = re.compile( + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) self._range = re.compile( - r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_range_1), '|'.join(_range_2)), re.IGNORECASE) + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Italian display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayIT(DateDisplay): """ Italian language date display class. """ - long_months = ( "", "gennaio", "febbraio", "marzo", "aprile", - "maggio", "giugno", "luglio", "agosto", "settembre", - "ottobre", "novembre", "dicembre" ) - short_months = ( "", "gen", "feb", "mar", "apr", "mag", "giu", - "lug", "ago", "set", "ott", "nov", "dic" ) + long_months = ( + "", + "gennaio", + "febbraio", + "marzo", + "aprile", + "maggio", + "giugno", + "luglio", + "agosto", + "settembre", + "ottobre", + "novembre", + "dicembre", + ) + + short_months = ( + "", + "gen", + "feb", + "mar", + "apr", + "mag", + "giu", + "lug", + "ago", + "set", + "ott", + "nov", + "dic", + ) calendar = ( - "", "Giuliano", "Ebraico", - "Rivoluzionario", "Persiano", "Islamico", - "Svedese" - ) + "", + "Giuliano", + "Ebraico", + "Rivoluzionario", + "Persiano", + "Islamico", + "Svedese", + ) _mod_str = ("", "prima del ", "dopo del ", "circa il ", "", "", "") _qual_str = ("", "stimata ", "calcolata ") french = ( - '', - 'vendemmiaio', - 'brumaio', - 'frimaio', - 'nevoso', - 'piovoso', - 'ventoso', - 'germile', - 'fiorile', - 'pratile', - 'messidoro', - 'termidoro', - 'fruttidoro', - 'extra', - ) + "", + "vendemmiaio", + "brumaio", + "frimaio", + "nevoso", + "piovoso", + "ventoso", + "germile", + "fiorile", + "pratile", + "messidoro", + "termidoro", + "fruttidoro", + "extra", + ) formats = ( - "AAAA-MM-DD (ISO)", "Numerico", "Mese Giorno Anno", - "MES Giorno, Anno", "Giorno Mese Anno", "Giorno MES Anno" - ) - # this must agree with DateDisplayEn's "formats" definition - # (since no locale-specific _display_gregorian exists, here) + "AAAA-MM-DD (ISO)", + "Numerico", + "Mese Giorno Anno", + "MES Giorno, Anno", + "Giorno Mese Anno", + "Giorno MES Anno", + ) + # this must agree with DateDisplayEn's "formats" definition + # (since no locale-specific _display_gregorian exists, here) def display(self, date): """ @@ -173,22 +214,25 @@ class DateDisplayIT(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'dal', d1, 'al', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "dal", d1, "al", d2, scal) elif mod == Date.MOD_RANGE: d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'tra', d1, 'e', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "tra", d1, "e", d2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('it_IT', 'it', 'italian', 'Italian', 'it_CH', ('%d/%m/%Y',)), - DateParserIT, DateDisplayIT) + ("it_IT", "it", "italian", "Italian", "it_CH", ("%d/%m/%Y",)), + DateParserIT, + DateDisplayIT, +) diff --git a/gramps/gen/datehandler/_date_ja.py b/gramps/gen/datehandler/_date_ja.py index 14c4a3d03..b2c21b3e8 100644 --- a/gramps/gen/datehandler/_date_ja.py +++ b/gramps/gen/datehandler/_date_ja.py @@ -24,30 +24,30 @@ Japanese-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Japanese parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserJA(DateParser): """ Convert a text string into a Date object. If the date cannot be @@ -56,21 +56,23 @@ class DateParserJA(DateParser): # modifiers after the date modifier_after_to_int = { - '以前' : Date.MOD_BEFORE, - '以降' : Date.MOD_AFTER, - '頃' : Date.MOD_ABOUT, - 'ごろ' : Date.MOD_ABOUT, - } + "以前": Date.MOD_BEFORE, + "以降": Date.MOD_AFTER, + "頃": Date.MOD_ABOUT, + "ごろ": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } month_to_int = DateParser.month_to_int quality_to_int = { - 'およそ' : Date.QUAL_ESTIMATED, - 'ごろ' : Date.QUAL_ESTIMATED, - '位' : Date.QUAL_ESTIMATED, - 'の見積り' : Date.QUAL_ESTIMATED, - '計算上' : Date.QUAL_CALCULATED, - } + "およそ": Date.QUAL_ESTIMATED, + "ごろ": Date.QUAL_ESTIMATED, + "位": Date.QUAL_ESTIMATED, + "の見積り": Date.QUAL_ESTIMATED, + "計算上": Date.QUAL_CALCULATED, + } bce = ["紀元前", "BC"] + DateParser.bce @@ -80,130 +82,138 @@ class DateParserJA(DateParser): """ DateParser.init_strings(self) - DateParser.calendar_to_int.update({ - 'グレゴリオ暦' : Date.CAL_GREGORIAN, - 'g' : Date.CAL_GREGORIAN, - 'ユリウス暦' : Date.CAL_JULIAN, - 'j' : Date.CAL_JULIAN, - 'ユダヤ暦' : Date.CAL_HEBREW, - 'h' : Date.CAL_HEBREW, - 'ヒジュラ暦' : Date.CAL_ISLAMIC, - 'i' : Date.CAL_ISLAMIC, - 'フランス革命暦' : Date.CAL_FRENCH, - '共和暦' : Date.CAL_FRENCH, - 'f' : Date.CAL_FRENCH, - 'イラン暦' : Date.CAL_PERSIAN, - 'p' : Date.CAL_PERSIAN, - 'スウェーデン暦' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - }) + DateParser.calendar_to_int.update( + { + "グレゴリオ暦": Date.CAL_GREGORIAN, + "g": Date.CAL_GREGORIAN, + "ユリウス暦": Date.CAL_JULIAN, + "j": Date.CAL_JULIAN, + "ユダヤ暦": Date.CAL_HEBREW, + "h": Date.CAL_HEBREW, + "ヒジュラ暦": Date.CAL_ISLAMIC, + "i": Date.CAL_ISLAMIC, + "フランス革命暦": Date.CAL_FRENCH, + "共和暦": Date.CAL_FRENCH, + "f": Date.CAL_FRENCH, + "イラン暦": Date.CAL_PERSIAN, + "p": Date.CAL_PERSIAN, + "スウェーデン暦": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } + ) - DateParser.month_to_int.update({ - "一月" : 1, - "ichigatsu" : 1, - "睦月" : 1, - "mutsuki" : 1, - "二月" : 2, - "nigatsu" : 2, - "如月" : 2, - "kisaragi" : 2, - "衣更着" : 2, - "kinusaragi" : 2, - "三月" : 3, - "sangatsu" : 3, - "弥生" : 3, - "yayoi" : 3, - "四月" : 4, - "shigatsu" : 4, - "卯月" : 4, - "uzuki" : 4, - "五月" : 5, - "gogatsu" : 5, - "皐月" : 5, - "satsuki" : 5, - "早苗月" : 5, - "sanaetsuki" : 5, - "六月" : 6, - "rokugatsu" : 6, - "水無月" : 6, - "minazuki" : 6, - "七月" : 7, - "shichigatsu" : 7, - "文月" : 7, - "fumizuki" : 7, - "八月" : 8, - "hachigatsu" : 8, - "葉月" : 8, - "hazuki" : 8, - "九月" : 9, - "kugatsu" : 9, - "長月" : 9, - "nagatsuki" : 9, - "十月" : 10, - "jugatsu" : 10, - "jūgatsu" : 10, - "juugatsu" : 10, - "神無月" : 10, - "kannazuki" : 10, - "kaminazuki" : 10, - "神有月" : 10, - "神在月" : 10, - "kamiarizuki" : 10, - "十一月" : 11, - "juichigatsu" : 11, - "jūichigatsu" : 11, - "juuichigatsu" : 11, - "霜月" : 11, - "shimotsuki" : 11, - "十二月" : 12, - "junigatsu" : 12, - "jūnigatsu" : 12, - "juunigatsu" : 12, - "師走" : 12, - "shiwasu" : 12, - }) + DateParser.month_to_int.update( + { + "一月": 1, + "ichigatsu": 1, + "睦月": 1, + "mutsuki": 1, + "二月": 2, + "nigatsu": 2, + "如月": 2, + "kisaragi": 2, + "衣更着": 2, + "kinusaragi": 2, + "三月": 3, + "sangatsu": 3, + "弥生": 3, + "yayoi": 3, + "四月": 4, + "shigatsu": 4, + "卯月": 4, + "uzuki": 4, + "五月": 5, + "gogatsu": 5, + "皐月": 5, + "satsuki": 5, + "早苗月": 5, + "sanaetsuki": 5, + "六月": 6, + "rokugatsu": 6, + "水無月": 6, + "minazuki": 6, + "七月": 7, + "shichigatsu": 7, + "文月": 7, + "fumizuki": 7, + "八月": 8, + "hachigatsu": 8, + "葉月": 8, + "hazuki": 8, + "九月": 9, + "kugatsu": 9, + "長月": 9, + "nagatsuki": 9, + "十月": 10, + "jugatsu": 10, + "jūgatsu": 10, + "juugatsu": 10, + "神無月": 10, + "kannazuki": 10, + "kaminazuki": 10, + "神有月": 10, + "神在月": 10, + "kamiarizuki": 10, + "十一月": 11, + "juichigatsu": 11, + "jūichigatsu": 11, + "juuichigatsu": 11, + "霜月": 11, + "shimotsuki": 11, + "十二月": 12, + "junigatsu": 12, + "jūnigatsu": 12, + "juunigatsu": 12, + "師走": 12, + "shiwasu": 12, + } + ) - _span_1 = ['から', '~', '〜'] - _span_2 = ['まで'] - _range_1 = ['から', 'と', '~', '〜'] - _range_2 = ['までの間', 'の間'] - self._span = re.compile(r"(?P.+)(%s)(?P.+)(%s)" % - ('|'.join(_span_1), '|'.join(_span_2)), - re.IGNORECASE) - self._range = re.compile(r"(?P.+)(%s)(?P.+)(%s)" % - ('|'.join(_range_1), '|'.join(_range_2)), - re.IGNORECASE) + _span_1 = ["から", "~", "〜"] + _span_2 = ["まで"] + _range_1 = ["から", "と", "~", "〜"] + _range_2 = ["までの間", "の間"] + self._span = re.compile( + r"(?P.+)(%s)(?P.+)(%s)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) + self._range = re.compile( + r"(?P.+)(%s)(?P.+)(%s)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) self._numeric = re.compile(r"((\d+)年\s*)?((\d+)月\s*)?(\d+)?日?\s*$") - self._cal = re.compile(r"(.*?)\s*\(%s\)\s*(.*)" % self._cal_str, - re.IGNORECASE) - self._qual = re.compile(r"(.*?)\s*%s\s*(.*)" % self._qual_str, - re.IGNORECASE) + self._cal = re.compile(r"(.*?)\s*\(%s\)\s*(.*)" % self._cal_str, re.IGNORECASE) + self._qual = re.compile(r"(.*?)\s*%s\s*(.*)" % self._qual_str, re.IGNORECASE) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Japanese display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayJA(DateDisplay): """ Japanese language date display class. """ def formats_changed(self): - """ Allow overriding so a subclass can modify """ + """Allow overriding so a subclass can modify""" # Specify what is actually the "System Default". example = self.dhformat - example = example.replace('%d', "31") - example = example.replace('%m', "12") - example = example.replace('%Y', "1999") + example = example.replace("%d", "31") + example = example.replace("%m", "12") + example = example.replace("%Y", "1999") # This definition must agree with its "_display_gregorian" method - self. formats = ("YYYY-MM-DD (ISO)", # 0 - "システムデフォールト (" + example + ")", # 1 - "1999年12月31日", # 2 - "1999年十二月31日", # 3 - ) + self.formats = ( + "YYYY-MM-DD (ISO)", # 0 + "システムデフォールト (" + example + ")", # 1 + "1999年12月31日", # 2 + "1999年十二月31日", # 3 + ) def _display_gregorian(self, date_val, **kwargs): """ @@ -223,12 +233,12 @@ class DateDisplayJA(DateDisplay): if date_val[0] == date_val[1] == 0: value = str(date_val[2]) else: - value = self.dhformat.replace('%m', str(date_val[1])) - if date_val[0] == 0: # ignore the zero day and its delimiter - i_day = value.find('%d') - value = value.replace(value[i_day:i_day+3], '') - value = value.replace('%d', str(date_val[0])) - value = value.replace('%Y', str(date_val[2])) + value = self.dhformat.replace("%m", str(date_val[1])) + if date_val[0] == 0: # ignore the zero day and its delimiter + i_day = value.find("%d") + value = value.replace(value[i_day : i_day + 3], "") + value = value.replace("%d", str(date_val[0])) + value = value.replace("%Y", str(date_val[2])) elif self.format == 2: # 1999年12月31日 @@ -236,12 +246,9 @@ class DateDisplayJA(DateDisplay): if date_val[1] == 0: value = "%s年" % year else: - value = "%s年%s" % (year, - self.short_months[date_val[1]]) + value = "%s年%s" % (year, self.short_months[date_val[1]]) else: - value = "%s年%s%s日" % (year, - self.short_months[date_val[1]], - date_val[0]) + value = "%s年%s%s日" % (year, self.short_months[date_val[1]], date_val[0]) elif self.format == 3: # 1999年十二月31日 @@ -249,12 +256,9 @@ class DateDisplayJA(DateDisplay): if date_val[1] == 0: value = "%s年" % year else: - value = "%s年%s" % (year, - self.long_months[date_val[1]]) + value = "%s年%s" % (year, self.long_months[date_val[1]]) else: - value = "%s年%s%s日" % (year, - self.long_months[date_val[1]], - date_val[0]) + value = "%s年%s%s日" % (year, self.long_months[date_val[1]], date_val[0]) else: return self.display_iso(date_val) @@ -266,12 +270,13 @@ class DateDisplayJA(DateDisplay): display = DateDisplay.display_formatted -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('ja_JP', 'ja', 'japanese', 'Japanese', ('%Y年%m月%d日',)), - DateParserJA, DateDisplayJA) + ("ja_JP", "ja", "japanese", "Japanese", ("%Y年%m月%d日",)), DateParserJA, DateDisplayJA +) diff --git a/gramps/gen/datehandler/_date_lt.py b/gramps/gen/datehandler/_date_lt.py index 932ae609d..5ed5e0817 100644 --- a/gramps/gen/datehandler/_date_lt.py +++ b/gramps/gen/datehandler/_date_lt.py @@ -23,28 +23,28 @@ Lithuanian-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Lithuanian parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserLT(DateParser): """ Convert a text string into a Date object. If the date cannot be @@ -101,92 +101,137 @@ class DateParserLT(DateParser): month_to_int["gruod"] = 12 modifier_to_int = { - 'prieš' : Date.MOD_BEFORE, - 'po' : Date.MOD_AFTER, - 'apie' : Date.MOD_ABOUT, - } + "prieš": Date.MOD_BEFORE, + "po": Date.MOD_AFTER, + "apie": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } calendar_to_int = { - 'grigaliaus' : Date.CAL_GREGORIAN, - 'g' : Date.CAL_GREGORIAN, - 'julijaus' : Date.CAL_JULIAN, - 'j' : Date.CAL_JULIAN, - 'hebrajų' : Date.CAL_HEBREW, - 'h' : Date.CAL_HEBREW, - 'islamo' : Date.CAL_ISLAMIC, - 'i' : Date.CAL_ISLAMIC, - 'prancūzų respublikos': Date.CAL_FRENCH, - 'r' : Date.CAL_FRENCH, - 'persų' : Date.CAL_PERSIAN, - 'p' : Date.CAL_PERSIAN, - 'švedų' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - } + "grigaliaus": Date.CAL_GREGORIAN, + "g": Date.CAL_GREGORIAN, + "julijaus": Date.CAL_JULIAN, + "j": Date.CAL_JULIAN, + "hebrajų": Date.CAL_HEBREW, + "h": Date.CAL_HEBREW, + "islamo": Date.CAL_ISLAMIC, + "i": Date.CAL_ISLAMIC, + "prancūzų respublikos": Date.CAL_FRENCH, + "r": Date.CAL_FRENCH, + "persų": Date.CAL_PERSIAN, + "p": Date.CAL_PERSIAN, + "švedų": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } quality_to_int = { - 'apytikriai' : Date.QUAL_ESTIMATED, - 'apskaičiuota' : Date.QUAL_CALCULATED, - } + "apytikriai": Date.QUAL_ESTIMATED, + "apskaičiuota": Date.QUAL_CALCULATED, + } def init_strings(self): DateParser.init_strings(self) # this next RE has the (possibly-slashed) year at the string's start self._text2 = re.compile( - r'((\d+)(/\d+)?)?\s+?m\.\s+%s\s*(\d+)?\s*d?\.?$' - % self._mon_str, re.IGNORECASE) - _span_1 = ['nuo'] - _span_2 = ['iki'] - _range_1 = ['tarp'] - _range_2 = ['ir'] - self._span = re.compile(r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_span_1), '|'.join(_span_2)), - re.IGNORECASE) + r"((\d+)(/\d+)?)?\s+?m\.\s+%s\s*(\d+)?\s*d?\.?$" % self._mon_str, + re.IGNORECASE, + ) + _span_1 = ["nuo"] + _span_2 = ["iki"] + _range_1 = ["tarp"] + _range_2 = ["ir"] + self._span = re.compile( + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) self._range = re.compile( - r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_range_1), '|'.join(_range_2)), re.IGNORECASE) + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Lithuanian displayer # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayLT(DateDisplay): """ Lithuanian language date display class. """ - long_months = ( "", "sausio", "vasario", "kovo", "balandžio", "gegužės", - "birželio", "liepos", "rugpjūčio", "rugsėjo", "spalio", - "lapkričio", "gruodžio" ) + long_months = ( + "", + "sausio", + "vasario", + "kovo", + "balandžio", + "gegužės", + "birželio", + "liepos", + "rugpjūčio", + "rugsėjo", + "spalio", + "lapkričio", + "gruodžio", + ) - long_months_vardininkas = ( "", "sausis", "vasaris", "kovas", "balandis", "gegužė", - "birželis", "liepa", "rugpjūtis", "rugsėjis", "spalis", - "lapkritis", "gruodis" ) + long_months_vardininkas = ( + "", + "sausis", + "vasaris", + "kovas", + "balandis", + "gegužė", + "birželis", + "liepa", + "rugpjūtis", + "rugsėjis", + "spalis", + "lapkritis", + "gruodis", + ) - short_months = ( "", "Sau", "Vas", "Kov", "Bal", "Geg", "Bir", - "Lie", "Rgp", "Rgs", "Spa", "Lap", "Grd" ) + short_months = ( + "", + "Sau", + "Vas", + "Kov", + "Bal", + "Geg", + "Bir", + "Lie", + "Rgp", + "Rgs", + "Spa", + "Lap", + "Grd", + ) calendar = ( - "", "julijaus", + "", + "julijaus", "hebrajų", "prancūzų respublikos", "persų", "islamo", - "švedų" - ) + "švedų", + ) - _mod_str = ("", - "prieš ", - "po ", - "apie ", - "", "", "") + _mod_str = ("", "prieš ", "po ", "apie ", "", "", "") _qual_str = ("", "apytikriai ", "apskaičiuota ") formats = ( - "mmmm-MM-DD (ISO)", "mmmm.MM.DD", - "mmmm m. mėnesio diena d.", "Mėn diena, metai") - # this definition must agree with its "_display_gregorian" method + "mmmm-MM-DD (ISO)", + "mmmm.MM.DD", + "mmmm m. mėnesio diena d.", + "Mėn diena, metai", + ) + # this definition must agree with its "_display_gregorian" method def _display_gregorian(self, date_val, **kwargs): """ @@ -206,11 +251,16 @@ class DateDisplayLT(DateDisplay): if date_val[1] == 0: value = year else: - value = "%s m. %s" % (year, self.long_months_vardininkas[date_val[1]]) + value = "%s m. %s" % ( + year, + self.long_months_vardininkas[date_val[1]], + ) else: - value = "%s m. %s %d d." % (year, - self.long_months[date_val[1]], - date_val[0]) + value = "%s m. %s %d d." % ( + year, + self.long_months[date_val[1]], + date_val[0], + ) elif self.format == 3: # month_abbreviation day, year if date_val[0] == 0: @@ -219,8 +269,11 @@ class DateDisplayLT(DateDisplay): else: value = "%s %s" % (self.short_months[date_val[1]], year) else: - value = "%s %d, %s" % (self.short_months[date_val[1]], - date_val[0], year) + value = "%s %d, %s" % ( + self.short_months[date_val[1]], + date_val[0], + year, + ) if date_val[2] < 0: return self._bce_str % value else: @@ -246,25 +299,25 @@ class DateDisplayLT(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'nuo', d1, 'iki', - d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "nuo", d1, "iki", d2, scal) elif mod == Date.MOD_RANGE: d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'tarp', d1, 'ir', - d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "tarp", d1, "ir", d2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) - return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, - scal) + return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('lt_LT', 'lt', 'lithuanian', 'Lithuanian', ('%Y.%m.%d',)), - DateParserLT, DateDisplayLT) + ("lt_LT", "lt", "lithuanian", "Lithuanian", ("%Y.%m.%d",)), + DateParserLT, + DateDisplayLT, +) diff --git a/gramps/gen/datehandler/_date_nb.py b/gramps/gen/datehandler/_date_nb.py index eaec57795..818883a88 100644 --- a/gramps/gen/datehandler/_date_nb.py +++ b/gramps/gen/datehandler/_date_nb.py @@ -23,28 +23,28 @@ Norwegian-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Norwegian parser class # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserNb(DateParser): """ Convert a text string into a Date object, expecting a date @@ -54,66 +54,94 @@ class DateParserNb(DateParser): # modifiers before the date modifier_to_int = { - 'før' : Date.MOD_BEFORE, - 'innen' : Date.MOD_BEFORE, - 'etter' : Date.MOD_AFTER, - 'omkring' : Date.MOD_ABOUT, - 'omtrent' : Date.MOD_ABOUT, - 'ca' : Date.MOD_ABOUT - } + "før": Date.MOD_BEFORE, + "innen": Date.MOD_BEFORE, + "etter": Date.MOD_AFTER, + "omkring": Date.MOD_ABOUT, + "omtrent": Date.MOD_ABOUT, + "ca": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } bce = ["f Kr"] calendar_to_int = { - 'gregoriansk ' : Date.CAL_GREGORIAN, - 'g' : Date.CAL_GREGORIAN, - 'juliansk' : Date.CAL_JULIAN, - 'j' : Date.CAL_JULIAN, - 'hebraisk' : Date.CAL_HEBREW, - 'h' : Date.CAL_HEBREW, - 'islamisk' : Date.CAL_ISLAMIC, - 'muslimsk' : Date.CAL_ISLAMIC, - 'i' : Date.CAL_ISLAMIC, - 'fransk' : Date.CAL_FRENCH, - 'fransk republikansk' : Date.CAL_FRENCH, - 'f' : Date.CAL_FRENCH, - 'persisk' : Date.CAL_PERSIAN, - 'p' : Date.CAL_PERSIAN, - 'svensk' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - } + "gregoriansk ": Date.CAL_GREGORIAN, + "g": Date.CAL_GREGORIAN, + "juliansk": Date.CAL_JULIAN, + "j": Date.CAL_JULIAN, + "hebraisk": Date.CAL_HEBREW, + "h": Date.CAL_HEBREW, + "islamisk": Date.CAL_ISLAMIC, + "muslimsk": Date.CAL_ISLAMIC, + "i": Date.CAL_ISLAMIC, + "fransk": Date.CAL_FRENCH, + "fransk republikansk": Date.CAL_FRENCH, + "f": Date.CAL_FRENCH, + "persisk": Date.CAL_PERSIAN, + "p": Date.CAL_PERSIAN, + "svensk": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } quality_to_int = { - 'estimert' : Date.QUAL_ESTIMATED, - 'beregnet' : Date.QUAL_CALCULATED, - } + "estimert": Date.QUAL_ESTIMATED, + "beregnet": Date.QUAL_CALCULATED, + } def init_strings(self): DateParser.init_strings(self) - self._numeric = re.compile( - r"((\d+)[/\.\s]\s*)?((\d+)[/\.\-\s]\s*)?(\d+)\s*$") + self._numeric = re.compile(r"((\d+)[/\.\s]\s*)?((\d+)[/\.\-\s]\s*)?(\d+)\s*$") self._span = re.compile( - r"(fra)?\s*(?P.+)\s*(til|--|–)\s*(?P.+)", - re.IGNORECASE) + r"(fra)?\s*(?P.+)\s*(til|--|–)\s*(?P.+)", re.IGNORECASE + ) self._range = re.compile( - r"(mellom)\s+(?P.+)\s+og\s+(?P.+)", re.IGNORECASE) + r"(mellom)\s+(?P.+)\s+og\s+(?P.+)", re.IGNORECASE + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Norwegian display class # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayNb(DateDisplay): """ Norwegian language date display class. """ - long_months = ( "", "januar", "februar", "mars", "april", "mai", - "juni", "juli", "august", "september", "oktober", - "november", "desember" ) + long_months = ( + "", + "januar", + "februar", + "mars", + "april", + "mai", + "juni", + "juli", + "august", + "september", + "oktober", + "november", + "desember", + ) - short_months = ( "", "jan", "feb", "mar", "apr", "mai", "jun", - "jul", "aug", "sep", "okt", "nov", "des" ) + short_months = ( + "", + "jan", + "feb", + "mar", + "apr", + "mai", + "jun", + "jul", + "aug", + "sep", + "okt", + "nov", + "des", + ) formats = ( "ÅÅÅÅ-MM-DD (ISO)", @@ -122,9 +150,9 @@ class DateDisplayNb(DateDisplay): "Mån Dag År", "Dag måned år", "Dag Mån År", - ) - # this must agree with DateDisplayEn's "formats" definition - # (since no locale-specific _display_gregorian exists, here) + ) + # this must agree with DateDisplayEn's "formats" definition + # (since no locale-specific _display_gregorian exists, here) calendar = ( "", @@ -133,8 +161,8 @@ class DateDisplayNb(DateDisplay): "fransk republikansk", "persisk", "islamisk", - "svensk" - ) + "svensk", + ) _mod_str = ("", "før ", "etter ", "ca ", "", "", "") @@ -167,23 +195,24 @@ class DateDisplayNb(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%smellom %s og %s%s" % (qual_str, d1, d2, - scal) + return "%smellom %s og %s%s" % (qual_str, d1, d2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) - return "%s%s%s%s" % (qual_str, self._mod_str[mod], - text, scal) + return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal) def dd_dformat01(self, date_val): - """ numerical -- for Norwegian dates """ + """numerical -- for Norwegian dates""" return DateDisplay.dd_dformat01(self, date_val).lstrip() -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('nb_NO', 'nb', 'nn_NO', 'nn', 'norsk', 'Norwegian', ('%d. %b %Y',)), - DateParserNb, DateDisplayNb) + ("nb_NO", "nb", "nn_NO", "nn", "norsk", "Norwegian", ("%d. %b %Y",)), + DateParserNb, + DateDisplayNb, +) diff --git a/gramps/gen/datehandler/_date_nl.py b/gramps/gen/datehandler/_date_nl.py index 83c4fbde1..d5896ed8b 100644 --- a/gramps/gen/datehandler/_date_nl.py +++ b/gramps/gen/datehandler/_date_nl.py @@ -29,28 +29,28 @@ Dutch-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Dutch parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserNL(DateParser): month_to_int = DateParser.month_to_int @@ -63,7 +63,7 @@ class DateParserNL(DateParser): month_to_int["feber"] = 2 month_to_int["februaris"] = 2 month_to_int["merz"] = 3 - #make sure on all distro mrt and maa are accepted + # make sure on all distro mrt and maa are accepted month_to_int["maa"] = 3 month_to_int["mrt"] = 3 month_to_int["aprilis"] = 4 @@ -83,74 +83,112 @@ class DateParserNL(DateParser): month_to_int["xbris"] = 12 modifier_to_int = { - 'voor' : Date.MOD_BEFORE, - 'na' : Date.MOD_AFTER, - 'ca.' : Date.MOD_ABOUT, - 'circa' : Date.MOD_ABOUT, - 'om' : Date.MOD_ABOUT, - 'omstreeks' : Date.MOD_ABOUT, - 'ongeveer' : Date.MOD_ABOUT, - 'rond' : Date.MOD_ABOUT, - 'tegen' : Date.MOD_ABOUT, - } + "voor": Date.MOD_BEFORE, + "na": Date.MOD_AFTER, + "ca.": Date.MOD_ABOUT, + "circa": Date.MOD_ABOUT, + "om": Date.MOD_ABOUT, + "omstreeks": Date.MOD_ABOUT, + "ongeveer": Date.MOD_ABOUT, + "rond": Date.MOD_ABOUT, + "tegen": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } calendar_to_int = { - 'gregoriaans' : Date.CAL_GREGORIAN, - 'greg.' : Date.CAL_GREGORIAN, - 'juliaans' : Date.CAL_JULIAN, - 'jul.' : Date.CAL_JULIAN, - 'hebreeuws' : Date.CAL_HEBREW, - 'hebr.' : Date.CAL_HEBREW, - 'islamitisch' : Date.CAL_ISLAMIC, - 'isl.' : Date.CAL_ISLAMIC, - 'frans republiekeins' : Date.CAL_FRENCH, - 'fran.' : Date.CAL_FRENCH, - 'persisch' : Date.CAL_PERSIAN, - 'zweeds' : Date.CAL_SWEDISH, - 'z' : Date.CAL_SWEDISH, - } + "gregoriaans": Date.CAL_GREGORIAN, + "greg.": Date.CAL_GREGORIAN, + "juliaans": Date.CAL_JULIAN, + "jul.": Date.CAL_JULIAN, + "hebreeuws": Date.CAL_HEBREW, + "hebr.": Date.CAL_HEBREW, + "islamitisch": Date.CAL_ISLAMIC, + "isl.": Date.CAL_ISLAMIC, + "frans republiekeins": Date.CAL_FRENCH, + "fran.": Date.CAL_FRENCH, + "persisch": Date.CAL_PERSIAN, + "zweeds": Date.CAL_SWEDISH, + "z": Date.CAL_SWEDISH, + } quality_to_int = { - 'geschat' : Date.QUAL_ESTIMATED, - 'gesch.' : Date.QUAL_ESTIMATED, - 'berekend' : Date.QUAL_CALCULATED, - 'ber.' : Date.QUAL_CALCULATED, - } + "geschat": Date.QUAL_ESTIMATED, + "gesch.": Date.QUAL_ESTIMATED, + "berekend": Date.QUAL_CALCULATED, + "ber.": Date.QUAL_CALCULATED, + } bce = ["voor onze tijdrekening", "voor Christus", "v. Chr."] + DateParser.bce def init_strings(self): DateParser.init_strings(self) self._span = re.compile( - r"(van)\s+(?P.+)\s+(tot)\s+(?P.+)", re.IGNORECASE) - self._range = re.compile(r"tussen\s+(?P.+)\s+en\s+(?P.+)", - re.IGNORECASE) - self._text2 = re.compile(r'(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' - % self._mon_str, re.IGNORECASE) - self._jtext2 = re.compile(r'(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' - % self._jmon_str, re.IGNORECASE) + r"(van)\s+(?P.+)\s+(tot)\s+(?P.+)", re.IGNORECASE + ) + self._range = re.compile( + r"tussen\s+(?P.+)\s+en\s+(?P.+)", re.IGNORECASE + ) + self._text2 = re.compile( + r"(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?" % self._mon_str, re.IGNORECASE + ) + self._jtext2 = re.compile( + r"(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?" % self._jmon_str, re.IGNORECASE + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Dutch display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayNL(DateDisplay): """ Dutch language date display class. """ - # TODO: Translate these month strings: - long_months = ( "", "januari", "februari", "maart", "april", "mei", - "juni", "juli", "augustus", "september", "oktober", - "november", "december" ) - short_months = ( "", "jan", "feb", "mrt", "apr", "mei", "jun", - "jul", "aug", "sep", "okt", "nov", "dec" ) + # TODO: Translate these month strings: + long_months = ( + "", + "januari", + "februari", + "maart", + "april", + "mei", + "juni", + "juli", + "augustus", + "september", + "oktober", + "november", + "december", + ) + + short_months = ( + "", + "jan", + "feb", + "mrt", + "apr", + "mei", + "jun", + "jul", + "aug", + "sep", + "okt", + "nov", + "dec", + ) calendar = ( - "", "juliaans", "hebreeuws", - "frans republikeins", "persisch", "islamitisch", - "zweeds" ) + "", + "juliaans", + "hebreeuws", + "frans republikeins", + "persisch", + "islamitisch", + "zweeds", + ) _mod_str = ("", "voor ", "na ", "omstreeks ", "", "", "") @@ -159,10 +197,14 @@ class DateDisplayNL(DateDisplay): _bce_str = "%s v. Chr." formats = ( - "JJJJ-MM-DD (ISO)", "Numeriek DD/MM/JJJJ", "Maand Dag, Jaar", - "Mnd. Dag Jaar", "Dag Maand Jaar", "Dag Mnd. Jaar" - ) - # this definition must agree with its "_display_gregorian" method + "JJJJ-MM-DD (ISO)", + "Numeriek DD/MM/JJJJ", + "Maand Dag, Jaar", + "Mnd. Dag Jaar", + "Dag Maand Jaar", + "Dag Mnd. Jaar", + ) + # this definition must agree with its "_display_gregorian" method def _display_gregorian(self, date_val, **kwargs): """ @@ -180,10 +222,10 @@ class DateDisplayNL(DateDisplay): if date_val[0] == date_val[1] == 0: value = str(date_val[2]) else: - value = self.dhformat.replace('%m', str(date_val[1])) - value = value.replace('%d', str(date_val[0])) - value = value.replace('%Y', str(abs(date_val[2]))) - value = value.replace('-', '/') + value = self.dhformat.replace("%m", str(date_val[1])) + value = value.replace("%d", str(date_val[0])) + value = value.replace("%Y", str(abs(date_val[2]))) + value = value.replace("-", "/") elif self.format == 2: # month_name day, year if date_val[0] == 0: @@ -192,8 +234,7 @@ class DateDisplayNL(DateDisplay): else: value = "%s %s" % (self.long_months[date_val[1]], year) else: - value = "%s %d, %s" % (self.long_months[date_val[1]], - date_val[0], year) + value = "%s %d, %s" % (self.long_months[date_val[1]], date_val[0], year) elif self.format == 3: # month_abbreviation day, year if date_val[0] == 0: @@ -202,8 +243,11 @@ class DateDisplayNL(DateDisplay): else: value = "%s %s" % (self.short_months[date_val[1]], year) else: - value = "%s %d, %s" % (self.short_months[date_val[1]], - date_val[0], year) + value = "%s %d, %s" % ( + self.short_months[date_val[1]], + date_val[0], + year, + ) elif self.format == 4: # day month_name year if date_val[0] == 0: @@ -212,8 +256,7 @@ class DateDisplayNL(DateDisplay): else: value = "%s %s" % (self.long_months[date_val[1]], year) else: - value = "%d %s %s" % (date_val[0], - self.long_months[date_val[1]], year) + value = "%d %s %s" % (date_val[0], self.long_months[date_val[1]], year) else: # day month_abbreviation year if date_val[0] == 0: @@ -222,8 +265,7 @@ class DateDisplayNL(DateDisplay): else: value = "%s %s" % (self.short_months[date_val[1]], year) else: - value = "%d %s %s" % (date_val[0], - self.short_months[date_val[1]], year) + value = "%d %s %s" % (date_val[0], self.short_months[date_val[1]], year) if date_val[2] < 0: return self._bce_str % value else: @@ -249,25 +291,25 @@ class DateDisplayNL(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'van', d1, - 'tot', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "van", d1, "tot", d2, scal) elif mod == Date.MOD_RANGE: d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%stussen %s en %s%s" % (qual_str, d1, d2, - scal) + return "%stussen %s en %s%s" % (qual_str, d1, d2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) - return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, - scal) + return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('nl_NL', 'dutch', 'Dutch', 'nl_BE', 'nl', ('%d-%m-%Y',)), - DateParserNL, DateDisplayNL) + ("nl_NL", "dutch", "Dutch", "nl_BE", "nl", ("%d-%m-%Y",)), + DateParserNL, + DateDisplayNL, +) diff --git a/gramps/gen/datehandler/_date_pl.py b/gramps/gen/datehandler/_date_pl.py index 11d475029..b190b168c 100644 --- a/gramps/gen/datehandler/_date_pl.py +++ b/gramps/gen/datehandler/_date_pl.py @@ -26,28 +26,28 @@ Polish-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Polish parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserPL(DateParser): month_to_int = DateParser.month_to_int @@ -112,83 +112,117 @@ class DateParserPL(DateParser): month_to_int["paz"] = 10 modifier_to_int = { - 'przed' : Date.MOD_BEFORE, - 'po' : Date.MOD_AFTER, - 'około' : Date.MOD_ABOUT, - 'ok.' : Date.MOD_ABOUT, - 'circa' : Date.MOD_ABOUT, - 'ca.' : Date.MOD_ABOUT, + "przed": Date.MOD_BEFORE, + "po": Date.MOD_AFTER, + "około": Date.MOD_ABOUT, + "ok.": Date.MOD_ABOUT, + "circa": Date.MOD_ABOUT, + "ca.": Date.MOD_ABOUT, # Alternative forms: misspellings sometimes used in emails - 'okolo' : Date.MOD_ABOUT, - 'ok' : Date.MOD_ABOUT, - } + "okolo": Date.MOD_ABOUT, + "ok": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } calendar_to_int = { - 'gregoriański' : Date.CAL_GREGORIAN, - 'greg.' : Date.CAL_GREGORIAN, - 'juliański' : Date.CAL_JULIAN, - 'jul.' : Date.CAL_JULIAN, - 'hebrajski' : Date.CAL_HEBREW, - 'hebr.' : Date.CAL_HEBREW, - 'islamski' : Date.CAL_ISLAMIC, - 'isl.' : Date.CAL_ISLAMIC, - 'francuski republikański': Date.CAL_FRENCH, - 'franc.' : Date.CAL_FRENCH, - 'perski' : Date.CAL_PERSIAN, - 'szwedzki' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - # Alternative forms: nouns without polish accent letters - # (misspellings sometimes used in emails) - 'gregorianski' : Date.CAL_GREGORIAN, - 'julianski' : Date.CAL_JULIAN, - 'francuski republikanski': Date.CAL_FRENCH, - } + "gregoriański": Date.CAL_GREGORIAN, + "greg.": Date.CAL_GREGORIAN, + "juliański": Date.CAL_JULIAN, + "jul.": Date.CAL_JULIAN, + "hebrajski": Date.CAL_HEBREW, + "hebr.": Date.CAL_HEBREW, + "islamski": Date.CAL_ISLAMIC, + "isl.": Date.CAL_ISLAMIC, + "francuski republikański": Date.CAL_FRENCH, + "franc.": Date.CAL_FRENCH, + "perski": Date.CAL_PERSIAN, + "szwedzki": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + # Alternative forms: nouns without polish accent letters + # (misspellings sometimes used in emails) + "gregorianski": Date.CAL_GREGORIAN, + "julianski": Date.CAL_JULIAN, + "francuski republikanski": Date.CAL_FRENCH, + } quality_to_int = { - 'szacowany' : Date.QUAL_ESTIMATED, - 'szac.' : Date.QUAL_ESTIMATED, - 'obliczony' : Date.QUAL_CALCULATED, - 'obl.' : Date.QUAL_CALCULATED, - } + "szacowany": Date.QUAL_ESTIMATED, + "szac.": Date.QUAL_ESTIMATED, + "obliczony": Date.QUAL_CALCULATED, + "obl.": Date.QUAL_CALCULATED, + } - bce = ["przed naszą erą", "przed Chrystusem", - "p.n.e."] + DateParser.bce + bce = ["przed naszą erą", "przed Chrystusem", "p.n.e."] + DateParser.bce def init_strings(self): DateParser.init_strings(self) self._span = re.compile( - r"(od)\s+(?P.+)\s+(do)\s+(?P.+)", re.IGNORECASE) + r"(od)\s+(?P.+)\s+(do)\s+(?P.+)", re.IGNORECASE + ) # Also handle a common mistakes self._range = re.compile( - r"((?:po)?mi(?:ę|e)dzy)\s+(?P.+)\s+(a)\s+(?P.+)", - re.IGNORECASE) - self._text2 = re.compile(r'(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' - % self._mon_str, re.IGNORECASE) - self._jtext2 = re.compile(r'(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' - % self._jmon_str, re.IGNORECASE) + r"((?:po)?mi(?:ę|e)dzy)\s+(?P.+)\s+(a)\s+(?P.+)", re.IGNORECASE + ) + self._text2 = re.compile( + r"(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?" % self._mon_str, re.IGNORECASE + ) + self._jtext2 = re.compile( + r"(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?" % self._jmon_str, re.IGNORECASE + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Polish display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayPL(DateDisplay): """ Polish language date display class. """ - long_months = ( "", "Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", - "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", - "Listopad", "Grudzień" ) + long_months = ( + "", + "Styczeń", + "Luty", + "Marzec", + "Kwiecień", + "Maj", + "Czerwiec", + "Lipiec", + "Sierpień", + "Wrzesień", + "Październik", + "Listopad", + "Grudzień", + ) - short_months = ( "", "Sty", "Lut", "Mar", "Kwi", "Maj", "Cze", - "Lip", "Sie", "Wrz", "Paź", "Lis", "Gru" ) + short_months = ( + "", + "Sty", + "Lut", + "Mar", + "Kwi", + "Maj", + "Cze", + "Lip", + "Sie", + "Wrz", + "Paź", + "Lis", + "Gru", + ) calendar = ( - "", "juliański", "hebrajski", - "francuski republikański", "perski", "islamski", - "swedish" - ) + "", + "juliański", + "hebrajski", + "francuski republikański", + "perski", + "islamski", + "swedish", + ) _mod_str = ("", "przed ", "po ", "ok. ", "", "", "") @@ -197,10 +231,14 @@ class DateDisplayPL(DateDisplay): _bce_str = "%s p.n.e." formats = ( - "RRRR-MM-DD (ISO)", "Numeryczny", "Miesiąc Dzień, Rok", - "Miesiąc.Dzień.Rok", "Dzień Miesiąc Rok", "Dzień MieRzym Rok" - ) - # this definition must agree with its "_display_gregorian" method + "RRRR-MM-DD (ISO)", + "Numeryczny", + "Miesiąc Dzień, Rok", + "Miesiąc.Dzień.Rok", + "Dzień Miesiąc Rok", + "Dzień MieRzym Rok", + ) + # this definition must agree with its "_display_gregorian" method roman_months = ( "", @@ -215,8 +253,8 @@ class DateDisplayPL(DateDisplay): "IX", "X", "XI", - "XII" - ) + "XII", + ) def _display_gregorian(self, date_val, **kwargs): """ @@ -234,9 +272,9 @@ class DateDisplayPL(DateDisplay): if date_val[0] == date_val[1] == 0: value = str(date_val[2]) else: - value = self.dhformat.replace('%d', str(date_val[0])) - value = value.replace('%m', str(date_val[1])) - value = value.replace('%Y', str(date_val[2])) + value = self.dhformat.replace("%d", str(date_val[0])) + value = value.replace("%m", str(date_val[1])) + value = value.replace("%Y", str(date_val[2])) elif self.format == 2: # month_name day, year if date_val[0] == 0: @@ -245,8 +283,7 @@ class DateDisplayPL(DateDisplay): else: value = "%s %s" % (self.long_months[date_val[1]], year) else: - value = "%s %d, %s" % (self.long_months[date_val[1]], - date_val[0], year) + value = "%s %d, %s" % (self.long_months[date_val[1]], date_val[0], year) elif self.format == 3: # month_number. day. year if date_val[0] == 0: @@ -264,8 +301,7 @@ class DateDisplayPL(DateDisplay): else: value = "%s %s" % (self.long_months[date_val[1]], year) else: - value = "%d %s %s" % (date_val[0], - self.long_months[date_val[1]], year) + value = "%d %s %s" % (date_val[0], self.long_months[date_val[1]], year) else: # day Roman_number_month year if date_val[0] == 0: @@ -274,8 +310,7 @@ class DateDisplayPL(DateDisplay): else: value = "%s %s" % (self.roman_months[date_val[1]], year) else: - value = "%d %s %s" % (date_val[0], - self.roman_months[date_val[1]], year) + value = "%d %s %s" % (date_val[0], self.roman_months[date_val[1]], year) if date_val[2] < 0: return self._bce_str % value else: @@ -301,25 +336,25 @@ class DateDisplayPL(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'od', d1, 'do', d2, - scal) + return "%s%s %s %s %s%s" % (qual_str, "od", d1, "do", d2, scal) elif mod == Date.MOD_RANGE: d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'między', d1, 'a', d2, - scal) + return "%s%s %s %s %s%s" % (qual_str, "między", d1, "a", d2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) - return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, - scal) + return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('pl_PL', 'polish', 'Polish_Poland', 'pl', ('%d.%m.%Y',)), - DateParserPL, DateDisplayPL) + ("pl_PL", "polish", "Polish_Poland", "pl", ("%d.%m.%Y",)), + DateParserPL, + DateDisplayPL, +) diff --git a/gramps/gen/datehandler/_date_pt.py b/gramps/gen/datehandler/_date_pt.py index 330fe63c9..65cefe313 100644 --- a/gramps/gen/datehandler/_date_pt.py +++ b/gramps/gen/datehandler/_date_pt.py @@ -25,128 +25,161 @@ Portuguese-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Portuguese parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserPT(DateParser): modifier_to_int = { - 'antes de' : Date.MOD_BEFORE, - 'antes' : Date.MOD_BEFORE, - 'ant.' : Date.MOD_BEFORE, - 'ant' : Date.MOD_BEFORE, - 'até' : Date.MOD_BEFORE, - 'depois de' : Date.MOD_AFTER, - 'depois' : Date.MOD_AFTER, - 'dep.' : Date.MOD_AFTER, - 'dep' : Date.MOD_AFTER, - 'aprox.' : Date.MOD_ABOUT, - 'aprox' : Date.MOD_ABOUT, - 'apr.' : Date.MOD_ABOUT, - 'apr' : Date.MOD_ABOUT, - 'cerca de' : Date.MOD_ABOUT, - 'ca.' : Date.MOD_ABOUT, - 'ca' : Date.MOD_ABOUT, - 'c.' : Date.MOD_ABOUT, - 'por volta de' : Date.MOD_ABOUT, - 'por volta' : Date.MOD_ABOUT, - 'pvd.' : Date.MOD_ABOUT, - } + "antes de": Date.MOD_BEFORE, + "antes": Date.MOD_BEFORE, + "ant.": Date.MOD_BEFORE, + "ant": Date.MOD_BEFORE, + "até": Date.MOD_BEFORE, + "depois de": Date.MOD_AFTER, + "depois": Date.MOD_AFTER, + "dep.": Date.MOD_AFTER, + "dep": Date.MOD_AFTER, + "aprox.": Date.MOD_ABOUT, + "aprox": Date.MOD_ABOUT, + "apr.": Date.MOD_ABOUT, + "apr": Date.MOD_ABOUT, + "cerca de": Date.MOD_ABOUT, + "ca.": Date.MOD_ABOUT, + "ca": Date.MOD_ABOUT, + "c.": Date.MOD_ABOUT, + "por volta de": Date.MOD_ABOUT, + "por volta": Date.MOD_ABOUT, + "pvd.": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } calendar_to_int = { - 'gregoriano' : Date.CAL_GREGORIAN, - 'g' : Date.CAL_GREGORIAN, - 'juliano' : Date.CAL_JULIAN, - 'j' : Date.CAL_JULIAN, - 'hebreu' : Date.CAL_HEBREW, - 'h' : Date.CAL_HEBREW, - 'islâmico' : Date.CAL_ISLAMIC, - 'i' : Date.CAL_ISLAMIC, - 'revolucionário' : Date.CAL_FRENCH, - 'r' : Date.CAL_FRENCH, - 'persa' : Date.CAL_PERSIAN, - 'p' : Date.CAL_PERSIAN, - 'swedish' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - } + "gregoriano": Date.CAL_GREGORIAN, + "g": Date.CAL_GREGORIAN, + "juliano": Date.CAL_JULIAN, + "j": Date.CAL_JULIAN, + "hebreu": Date.CAL_HEBREW, + "h": Date.CAL_HEBREW, + "islâmico": Date.CAL_ISLAMIC, + "i": Date.CAL_ISLAMIC, + "revolucionário": Date.CAL_FRENCH, + "r": Date.CAL_FRENCH, + "persa": Date.CAL_PERSIAN, + "p": Date.CAL_PERSIAN, + "swedish": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } quality_to_int = { - 'estimado' : Date.QUAL_ESTIMATED, - 'estimada' : Date.QUAL_ESTIMATED, - 'est.' : Date.QUAL_ESTIMATED, - 'est' : Date.QUAL_ESTIMATED, - 'calc.' : Date.QUAL_CALCULATED, - 'calc' : Date.QUAL_CALCULATED, - 'calculado' : Date.QUAL_CALCULATED, - 'calculada' : Date.QUAL_CALCULATED, - } + "estimado": Date.QUAL_ESTIMATED, + "estimada": Date.QUAL_ESTIMATED, + "est.": Date.QUAL_ESTIMATED, + "est": Date.QUAL_ESTIMATED, + "calc.": Date.QUAL_CALCULATED, + "calc": Date.QUAL_CALCULATED, + "calculado": Date.QUAL_CALCULATED, + "calculada": Date.QUAL_CALCULATED, + } def init_strings(self): DateParser.init_strings(self) - _span_1 = ['de'] - _span_2 = ['a'] - _range_1 = ['entre', r'ent\.', 'ent'] - _range_2 = ['e'] - self._span = re.compile(r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" - % ('|'.join(_span_1), '|'.join(_span_2)), - re.IGNORECASE) - self._range = re.compile(r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" - % ('|'.join(_range_1), '|'.join(_range_2)), - re.IGNORECASE) + _span_1 = ["de"] + _span_2 = ["a"] + _range_1 = ["entre", r"ent\.", "ent"] + _range_2 = ["e"] + self._span = re.compile( + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) + self._range = re.compile( + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Portuguese display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayPT(DateDisplay): """ Portuguese language date display class. """ - long_months = ( "", "Janeiro", "Fevereiro", "Março", "Abril", "Maio", - "Junho", "Julho", "Agosto", "Setembro", "Outubro", - "Novembro", "Dezembro" ) - short_months = ( "", "Jan", "Fev", "Mar", "Abr", "Mai", "Jun", - "Jul", "Ago", "Set", "Out", "Nov", "Dez" ) + long_months = ( + "", + "Janeiro", + "Fevereiro", + "Março", + "Abril", + "Maio", + "Junho", + "Julho", + "Agosto", + "Setembro", + "Outubro", + "Novembro", + "Dezembro", + ) - calendar = ( - "", "Juliano", "Hebreu", - "Revolucionário", "Persa", "Islâmico", - "Sueco" - ) + short_months = ( + "", + "Jan", + "Fev", + "Mar", + "Abr", + "Mai", + "Jun", + "Jul", + "Ago", + "Set", + "Out", + "Nov", + "Dez", + ) - _mod_str = ("","antes de ","depois de ","por volta de ","","","") + calendar = ("", "Juliano", "Hebreu", "Revolucionário", "Persa", "Islâmico", "Sueco") - _qual_str = ("","estimado ","calculado ") + _mod_str = ("", "antes de ", "depois de ", "por volta de ", "", "", "") + + _qual_str = ("", "estimado ", "calculado ") formats = ( - "AAAA-MM-DD (ISO)", "Numérica", "Mês Dia, Ano", - "MÊS Dia, Ano", "Dia Mês, Ano", "Dia MÊS, Ano" - ) - # this must agree with DateDisplayEn's "formats" definition - # (since no locale-specific _display_gregorian exists, here) + "AAAA-MM-DD (ISO)", + "Numérica", + "Mês Dia, Ano", + "MÊS Dia, Ano", + "Dia Mês, Ano", + "Dia MÊS, Ano", + ) + # this must agree with DateDisplayEn's "formats" definition + # (since no locale-specific _display_gregorian exists, here) - def display(self,date): + def display(self, date): """ Return a text string representing the date. """ @@ -166,23 +199,33 @@ class DateDisplayPT(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'de', d1, 'a', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "de", d1, "a", d2, scal) elif mod == Date.MOD_RANGE: d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'entre', d1, 'e', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "entre", d1, "e", d2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('pt_PT', 'pt_PT.UTF-8', 'pt_BR', 'pt_BR.UTF-8', - 'pt' 'portuguese', 'Portuguese', ('%d-%m-%Y',)), - DateParserPT, DateDisplayPT) + ( + "pt_PT", + "pt_PT.UTF-8", + "pt_BR", + "pt_BR.UTF-8", + "pt" "portuguese", + "Portuguese", + ("%d-%m-%Y",), + ), + DateParserPT, + DateDisplayPT, +) diff --git a/gramps/gen/datehandler/_date_ru.py b/gramps/gen/datehandler/_date_ru.py index 9437c34ff..93424f479 100644 --- a/gramps/gen/datehandler/_date_ru.py +++ b/gramps/gen/datehandler/_date_ru.py @@ -23,91 +23,97 @@ Russian-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Russian parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserRU(DateParser): modifier_to_int = { - 'перед' : Date.MOD_BEFORE, - 'по' : Date.MOD_BEFORE, - 'до' : Date.MOD_BEFORE, - 'после' : Date.MOD_AFTER, - 'п.' : Date.MOD_AFTER, - 'п' : Date.MOD_AFTER, - 'с' : Date.MOD_AFTER, - 'ок' : Date.MOD_ABOUT, - 'ок.' : Date.MOD_ABOUT, - 'около' : Date.MOD_ABOUT, - 'примерно' : Date.MOD_ABOUT, - 'прим' : Date.MOD_ABOUT, - 'прим.' : Date.MOD_ABOUT, - 'приблизительно' : Date.MOD_ABOUT, - 'приб.' : Date.MOD_ABOUT, - 'прибл.' : Date.MOD_ABOUT, - 'приб' : Date.MOD_ABOUT, - 'прибл' : Date.MOD_ABOUT, - } - + "перед": Date.MOD_BEFORE, + "по": Date.MOD_BEFORE, + "до": Date.MOD_BEFORE, + "после": Date.MOD_AFTER, + "п.": Date.MOD_AFTER, + "п": Date.MOD_AFTER, + "с": Date.MOD_AFTER, + "ок": Date.MOD_ABOUT, + "ок.": Date.MOD_ABOUT, + "около": Date.MOD_ABOUT, + "примерно": Date.MOD_ABOUT, + "прим": Date.MOD_ABOUT, + "прим.": Date.MOD_ABOUT, + "приблизительно": Date.MOD_ABOUT, + "приб.": Date.MOD_ABOUT, + "прибл.": Date.MOD_ABOUT, + "приб": Date.MOD_ABOUT, + "прибл": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } quality_to_int = { - 'оценено' : Date.QUAL_ESTIMATED, - 'оцен.' : Date.QUAL_ESTIMATED, - 'оц.' : Date.QUAL_ESTIMATED, - 'оцен' : Date.QUAL_ESTIMATED, - 'оц' : Date.QUAL_ESTIMATED, - 'вычислено' : Date.QUAL_CALCULATED, - 'вычисл.' : Date.QUAL_CALCULATED, - 'выч.' : Date.QUAL_CALCULATED, - 'вычисл' : Date.QUAL_CALCULATED, - 'выч' : Date.QUAL_CALCULATED, - } + "оценено": Date.QUAL_ESTIMATED, + "оцен.": Date.QUAL_ESTIMATED, + "оц.": Date.QUAL_ESTIMATED, + "оцен": Date.QUAL_ESTIMATED, + "оц": Date.QUAL_ESTIMATED, + "вычислено": Date.QUAL_CALCULATED, + "вычисл.": Date.QUAL_CALCULATED, + "выч.": Date.QUAL_CALCULATED, + "вычисл": Date.QUAL_CALCULATED, + "выч": Date.QUAL_CALCULATED, + } - bce = [ - 'до нашей эры', 'до н. э.', 'до н.э.', - 'до н э', 'до нэ'] + DateParser.bce + bce = ["до нашей эры", "до н. э.", "до н.э.", "до н э", "до нэ"] + DateParser.bce def init_strings(self): DateParser.init_strings(self) - DateParser.calendar_to_int.update({ - 'персидский' : Date.CAL_PERSIAN, - 'п' : Date.CAL_PERSIAN, - }) - _span_1 = ['с', 'от'] - #_span_2 = ['по', 'до'] # <-- clashes with bce parsing :-( - _span_2 = ['по'] - _range_1 = ['между', r'меж\.', 'меж'] - _range_2 = ['и'] - self._span = re.compile(r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" - % ('|'.join(_span_1), '|'.join(_span_2)), - re.IGNORECASE) - self._range = re.compile(r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" - % ('|'.join(_range_1), '|'.join(_range_2)), - re.IGNORECASE) + DateParser.calendar_to_int.update( + { + "персидский": Date.CAL_PERSIAN, + "п": Date.CAL_PERSIAN, + } + ) + _span_1 = ["с", "от"] + # _span_2 = ['по', 'до'] # <-- clashes with bce parsing :-( + _span_2 = ["по"] + _range_1 = ["между", r"меж\.", "меж"] + _range_2 = ["и"] + self._span = re.compile( + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) + self._range = re.compile( + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Russian displayer # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayRU(DateDisplay): """ Russian language date display class. @@ -128,20 +134,19 @@ class DateDisplayRU(DateDisplay): if date_val[1] == 0: return year else: - return self.format_long_month_year(date_val[1], year, - inflect, long_months) - elif date_val[1] == 0: # month is zero but day is not (see 8477) + return self.format_long_month_year( + date_val[1], year, inflect, long_months + ) + elif date_val[1] == 0: # month is zero but day is not (see 8477) return self.display_iso(date_val) - elif not hasattr(long_months[date_val[1]], 'f'): # not a Lexeme + elif not hasattr(long_months[date_val[1]], "f"): # not a Lexeme return "{day:d} {long_month} {year}".format( - day = date_val[0], - long_month = long_months[date_val[1]], - year = year) + day=date_val[0], long_month=long_months[date_val[1]], year=year + ) else: return "{day:d} {long_month.f[Р]} {year}".format( - day = date_val[0], - long_month = long_months[date_val[1]], - year = year) + day=date_val[0], long_month=long_months[date_val[1]], year=year + ) def dd_dformat05(self, date_val, inflect, short_months): """ @@ -152,26 +157,26 @@ class DateDisplayRU(DateDisplay): if date_val[1] == 0: return year else: - return self.format_short_month_year(date_val[1], year, - inflect, short_months) - elif date_val[1] == 0: # month is zero but day is not (see 8477) + return self.format_short_month_year( + date_val[1], year, inflect, short_months + ) + elif date_val[1] == 0: # month is zero but day is not (see 8477) return self.display_iso(date_val) - elif not hasattr(short_months[date_val[1]], 'f'): # not a Lexeme + elif not hasattr(short_months[date_val[1]], "f"): # not a Lexeme return "{day:d} {short_month} {year}".format( - day = date_val[0], - short_month = short_months[date_val[1]], - year = year) + day=date_val[0], short_month=short_months[date_val[1]], year=year + ) else: return "{day:d} {short_month.f[Р]} {year}".format( - day = date_val[0], - short_month = short_months[date_val[1]], - year = year) + day=date_val[0], short_month=short_months[date_val[1]], year=year + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('ru_RU', 'ru', 'russian', 'Russian', ('%d.%m.%Y',)), - DateParserRU, DateDisplayRU) + ("ru_RU", "ru", "russian", "Russian", ("%d.%m.%Y",)), DateParserRU, DateDisplayRU +) diff --git a/gramps/gen/datehandler/_date_sk.py b/gramps/gen/datehandler/_date_sk.py index 473ac77f7..d9c0c0c6a 100644 --- a/gramps/gen/datehandler/_date_sk.py +++ b/gramps/gen/datehandler/_date_sk.py @@ -23,108 +23,149 @@ Slovak-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Slovak parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserSK(DateParser): modifier_to_int = { - 'pred' : Date.MOD_BEFORE, - 'do' : Date.MOD_BEFORE, - 'po' : Date.MOD_AFTER, - 'asi' : Date.MOD_ABOUT, - 'okolo' : Date.MOD_ABOUT, - 'pribl.' : Date.MOD_ABOUT, - } + "pred": Date.MOD_BEFORE, + "do": Date.MOD_BEFORE, + "po": Date.MOD_AFTER, + "asi": Date.MOD_ABOUT, + "okolo": Date.MOD_ABOUT, + "pribl.": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } calendar_to_int = { - 'gregoriánsky' : Date.CAL_GREGORIAN, - 'g' : Date.CAL_GREGORIAN, - 'juliánsky' : Date.CAL_JULIAN, - 'j' : Date.CAL_JULIAN, - 'hebrejský' : Date.CAL_HEBREW, - 'h' : Date.CAL_HEBREW, - 'islamský' : Date.CAL_ISLAMIC, - 'i' : Date.CAL_ISLAMIC, - 'republikánsky' : Date.CAL_FRENCH, - 'r' : Date.CAL_FRENCH, - 'perzský' : Date.CAL_PERSIAN, - 'p' : Date.CAL_PERSIAN, - 'švédsky' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - } + "gregoriánsky": Date.CAL_GREGORIAN, + "g": Date.CAL_GREGORIAN, + "juliánsky": Date.CAL_JULIAN, + "j": Date.CAL_JULIAN, + "hebrejský": Date.CAL_HEBREW, + "h": Date.CAL_HEBREW, + "islamský": Date.CAL_ISLAMIC, + "i": Date.CAL_ISLAMIC, + "republikánsky": Date.CAL_FRENCH, + "r": Date.CAL_FRENCH, + "perzský": Date.CAL_PERSIAN, + "p": Date.CAL_PERSIAN, + "švédsky": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } quality_to_int = { - 'odhadovaný' : Date.QUAL_ESTIMATED, - 'odh.' : Date.QUAL_ESTIMATED, - 'vypočítaný' : Date.QUAL_CALCULATED, - 'vyp.' : Date.QUAL_CALCULATED, - } + "odhadovaný": Date.QUAL_ESTIMATED, + "odh.": Date.QUAL_ESTIMATED, + "vypočítaný": Date.QUAL_CALCULATED, + "vyp.": Date.QUAL_CALCULATED, + } def init_strings(self): DateParser.init_strings(self) - _span_1 = ['od'] - _span_2 = ['do'] - _range_1 = ['medzi'] - _range_2 = ['a'] - self._span = re.compile(r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" - % ('|'.join(_span_1), '|'.join(_span_2)), - re.IGNORECASE) - self._range = re.compile(r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" - % ('|'.join(_range_1), '|'.join(_range_2)), - re.IGNORECASE) + _span_1 = ["od"] + _span_2 = ["do"] + _range_1 = ["medzi"] + _range_2 = ["a"] + self._span = re.compile( + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) + self._range = re.compile( + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Slovak display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplaySK(DateDisplay): """ Slovak language date display class. """ - long_months = ( "", "január", "február", "marec", "apríl", "máj", - "jún", "júl", "august", "september", "október", - "november", "december" ) - short_months = ( "", "jan", "feb", "mar", "apr", "máj", "jún", - "júl", "aug", "sep", "okt", "nov", "dec" ) + long_months = ( + "", + "január", + "február", + "marec", + "apríl", + "máj", + "jún", + "júl", + "august", + "september", + "október", + "november", + "december", + ) + + short_months = ( + "", + "jan", + "feb", + "mar", + "apr", + "máj", + "jún", + "júl", + "aug", + "sep", + "okt", + "nov", + "dec", + ) calendar = ( - "", "juliánsky", "hebrejský", - "republikánsky", "perzský", "islamský", - "švédsky" - ) + "", + "juliánsky", + "hebrejský", + "republikánsky", + "perzský", + "islamský", + "švédsky", + ) _mod_str = ("", "pred ", "po ", "okolo ", "", "", "") _qual_str = ("", "odh. ", "vyp. ") formats = ( - "RRRR-MM-DD (ISO)", "numerický", "Mesiac Deň, Rok", - "MES Deň, Rok", "Deň, Mesiac, Rok", "Deň MES Rok" - ) - # this must agree with DateDisplayEn's "formats" definition - # (since no locale-specific _display_gregorian exists, here) + "RRRR-MM-DD (ISO)", + "numerický", + "Mesiac Deň, Rok", + "MES Deň, Rok", + "Deň, Mesiac, Rok", + "Deň MES Rok", + ) + # this must agree with DateDisplayEn's "formats" definition + # (since no locale-specific _display_gregorian exists, here) def display(self, date): """ @@ -146,25 +187,23 @@ class DateDisplaySK(DateDisplay): d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'od', d1, - 'do', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "od", d1, "do", d2, scal) elif mod == Date.MOD_RANGE: d1 = self.display_cal[cal](start) d2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, 'medzi', - d1, 'a', d2, scal) + return "%s%s %s %s %s%s" % (qual_str, "medzi", d1, "a", d2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) - return "%s%s%s%s" % (qual_str, self._mod_str[mod], - text, scal) + return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('sk_SK', 'sk', 'SK', 'Slovak', ('%d.%m.%Y',)), - DateParserSK, DateDisplaySK) + ("sk_SK", "sk", "SK", "Slovak", ("%d.%m.%Y",)), DateParserSK, DateDisplaySK +) diff --git a/gramps/gen/datehandler/_date_sl.py b/gramps/gen/datehandler/_date_sl.py index a0aa8f648..291818c18 100644 --- a/gramps/gen/datehandler/_date_sl.py +++ b/gramps/gen/datehandler/_date_sl.py @@ -25,61 +25,69 @@ Slovenian-specific classes for parsing and displaying dates - new framework. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Slovenian parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserSL(DateParser): """ Converts a text string into a Date object """ modifier_to_int = { - 'pred' : Date.MOD_BEFORE, - 'pr.' : Date.MOD_BEFORE, - 'po' : Date.MOD_AFTER, - 'okoli' : Date.MOD_ABOUT, - 'okrog' : Date.MOD_ABOUT, - 'okr.' : Date.MOD_ABOUT, - 'ok.' : Date.MOD_ABOUT, - 'cca.' : Date.MOD_ABOUT, - 'cca' : Date.MOD_ABOUT, - 'circa' : Date.MOD_ABOUT, - 'ca.' : Date.MOD_ABOUT, - 'približno' : Date.MOD_ABOUT, - 'pribl.' : Date.MOD_ABOUT, - '~' : Date.MOD_ABOUT, - } + "pred": Date.MOD_BEFORE, + "pr.": Date.MOD_BEFORE, + "po": Date.MOD_AFTER, + "okoli": Date.MOD_ABOUT, + "okrog": Date.MOD_ABOUT, + "okr.": Date.MOD_ABOUT, + "ok.": Date.MOD_ABOUT, + "cca.": Date.MOD_ABOUT, + "cca": Date.MOD_ABOUT, + "circa": Date.MOD_ABOUT, + "ca.": Date.MOD_ABOUT, + "približno": Date.MOD_ABOUT, + "pribl.": Date.MOD_ABOUT, + "~": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } quality_to_int = { - 'ocenjeno' : Date.QUAL_ESTIMATED, - 'oc.' : Date.QUAL_ESTIMATED, - 'po oceni' : Date.QUAL_ESTIMATED, - 'izračunano' : Date.QUAL_CALCULATED, - 'izrač.' : Date.QUAL_CALCULATED, - 'po izračunu': Date.QUAL_CALCULATED, - } + "ocenjeno": Date.QUAL_ESTIMATED, + "oc.": Date.QUAL_ESTIMATED, + "po oceni": Date.QUAL_ESTIMATED, + "izračunano": Date.QUAL_CALCULATED, + "izrač.": Date.QUAL_CALCULATED, + "po izračunu": Date.QUAL_CALCULATED, + } - bce = ["pred našim štetjem", "pred Kristusom", - "p.n.š.", "p. n. š.", "pr.Kr.", "pr. Kr."] + DateParser.bce + bce = [ + "pred našim štetjem", + "pred Kristusom", + "p.n.š.", + "p. n. š.", + "pr.Kr.", + "pr. Kr.", + ] + DateParser.bce def init_strings(self): """ @@ -88,40 +96,48 @@ class DateParserSL(DateParser): DateParser.init_strings(self) # match 'Day. MONTH year.' format with or without dots - self._text2 = re.compile(r'(\d+)?\.?\s*?%s\.?\s*((\d+)(/\d+)?)?\s*\.?$' - % self._mon_str, re.IGNORECASE) + self._text2 = re.compile( + r"(\d+)?\.?\s*?%s\.?\s*((\d+)(/\d+)?)?\s*\.?$" % self._mon_str, + re.IGNORECASE, + ) # match Day.Month.Year. - self._numeric = re.compile( - r"((\d+)[/\.-])?\s*((\d+)[/\.-])?\s*(\d+)\.?$") + self._numeric = re.compile(r"((\d+)[/\.-])?\s*((\d+)[/\.-])?\s*(\d+)\.?$") - self._span = re.compile(r"od\s+(?P.+)\s+do\s+(?P.+)", - re.IGNORECASE) + self._span = re.compile( + r"od\s+(?P.+)\s+do\s+(?P.+)", re.IGNORECASE + ) self._range = re.compile( - r"med\s+(?P.+)\s+in\s+(?P.+)", re.IGNORECASE) - self._jtext2 = re.compile(r'(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' - % self._jmon_str, re.IGNORECASE) + r"med\s+(?P.+)\s+in\s+(?P.+)", re.IGNORECASE + ) + self._jtext2 = re.compile( + r"(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?" % self._jmon_str, re.IGNORECASE + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Slovenian display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplaySL(DateDisplay): """ Slovenian language date display class. """ + # TODO fix BUG 7064: non-Gregorian calendars wrongly use BCE notation for negative dates # not refactoring _bce_str into base class because it'll be gone under #7064 _bce_str = "%s pr.Kr." display = DateDisplay.display_formatted -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ("sl_SI", "sl", "SL", - "slovenščina", "slovenian", "Slovenian", ('%d. %m. %Y',)), - DateParserSL, DateDisplaySL) + ("sl_SI", "sl", "SL", "slovenščina", "slovenian", "Slovenian", ("%d. %m. %Y",)), + DateParserSL, + DateDisplaySL, +) diff --git a/gramps/gen/datehandler/_date_sr.py b/gramps/gen/datehandler/_date_sr.py index b30e6fd0f..c45e14d39 100644 --- a/gramps/gen/datehandler/_date_sr.py +++ b/gramps/gen/datehandler/_date_sr.py @@ -26,32 +26,33 @@ Serbian-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Serbian parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserSR(DateParser): """ Converts a text string into a Date object """ + month_to_int = DateParser.month_to_int month_to_int["januar"] = 1 @@ -145,64 +146,68 @@ class DateParserSR(DateParser): month_to_int["xii"] = 12 modifier_to_int = { - 'pre' : Date.MOD_BEFORE, - 'posle' : Date.MOD_AFTER, - 'oko' : Date.MOD_ABOUT, - 'cca' : Date.MOD_ABOUT, - - 'пре' : Date.MOD_BEFORE, - 'после' : Date.MOD_AFTER, - 'око' : Date.MOD_ABOUT, - } + "pre": Date.MOD_BEFORE, + "posle": Date.MOD_AFTER, + "oko": Date.MOD_ABOUT, + "cca": Date.MOD_ABOUT, + "пре": Date.MOD_BEFORE, + "после": Date.MOD_AFTER, + "око": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } calendar_to_int = { - 'gregorijanski' : Date.CAL_GREGORIAN, - 'greg.' : Date.CAL_GREGORIAN, - 'julijanski' : Date.CAL_JULIAN, - 'jul.' : Date.CAL_JULIAN, - 'hebrejski' : Date.CAL_HEBREW, - 'hebr.' : Date.CAL_HEBREW, - 'islamski' : Date.CAL_ISLAMIC, - 'isl.' : Date.CAL_ISLAMIC, - 'francuski republikanski': Date.CAL_FRENCH, - 'franc.' : Date.CAL_FRENCH, - 'persijski' : Date.CAL_PERSIAN, - 'pers. ' : Date.CAL_PERSIAN, - 'švedski' : Date.CAL_SWEDISH, - 'šv.' : Date.CAL_SWEDISH, - - 'грегоријански' : Date.CAL_GREGORIAN, - 'грег.' : Date.CAL_GREGORIAN, - 'јулијански' : Date.CAL_JULIAN, - 'јул.' : Date.CAL_JULIAN, - 'хебрејски' : Date.CAL_HEBREW, - 'хебр.' : Date.CAL_HEBREW, - 'исламски' : Date.CAL_ISLAMIC, - 'исл.' : Date.CAL_ISLAMIC, - 'француски републикански': Date.CAL_FRENCH, - 'франц.' : Date.CAL_FRENCH, - 'персијски' : Date.CAL_PERSIAN, - 'перс. ' : Date.CAL_PERSIAN, - 'шведски' : Date.CAL_SWEDISH, - 'шв' : Date.CAL_SWEDISH, - } + "gregorijanski": Date.CAL_GREGORIAN, + "greg.": Date.CAL_GREGORIAN, + "julijanski": Date.CAL_JULIAN, + "jul.": Date.CAL_JULIAN, + "hebrejski": Date.CAL_HEBREW, + "hebr.": Date.CAL_HEBREW, + "islamski": Date.CAL_ISLAMIC, + "isl.": Date.CAL_ISLAMIC, + "francuski republikanski": Date.CAL_FRENCH, + "franc.": Date.CAL_FRENCH, + "persijski": Date.CAL_PERSIAN, + "pers. ": Date.CAL_PERSIAN, + "švedski": Date.CAL_SWEDISH, + "šv.": Date.CAL_SWEDISH, + "грегоријански": Date.CAL_GREGORIAN, + "грег.": Date.CAL_GREGORIAN, + "јулијански": Date.CAL_JULIAN, + "јул.": Date.CAL_JULIAN, + "хебрејски": Date.CAL_HEBREW, + "хебр.": Date.CAL_HEBREW, + "исламски": Date.CAL_ISLAMIC, + "исл.": Date.CAL_ISLAMIC, + "француски републикански": Date.CAL_FRENCH, + "франц.": Date.CAL_FRENCH, + "персијски": Date.CAL_PERSIAN, + "перс. ": Date.CAL_PERSIAN, + "шведски": Date.CAL_SWEDISH, + "шв": Date.CAL_SWEDISH, + } quality_to_int = { - 'procenjeno' : Date.QUAL_ESTIMATED, - 'pro.' : Date.QUAL_ESTIMATED, - 'izračunato' : Date.QUAL_CALCULATED, - 'izr.' : Date.QUAL_CALCULATED, + "procenjeno": Date.QUAL_ESTIMATED, + "pro.": Date.QUAL_ESTIMATED, + "izračunato": Date.QUAL_CALCULATED, + "izr.": Date.QUAL_CALCULATED, + "процењено": Date.QUAL_ESTIMATED, + "про.": Date.QUAL_ESTIMATED, + "приближно": Date.QUAL_ESTIMATED, + "израчунато": Date.QUAL_CALCULATED, + "изр.": Date.QUAL_CALCULATED, + "прорачунато": Date.QUAL_CALCULATED, + } - 'процењено' : Date.QUAL_ESTIMATED, - 'про.' : Date.QUAL_ESTIMATED, - 'приближно' : Date.QUAL_ESTIMATED, - 'израчунато' : Date.QUAL_CALCULATED, - 'изр.' : Date.QUAL_CALCULATED, - 'прорачунато': Date.QUAL_CALCULATED, - } - - bce = ["пре нове ере", "пре Христа", "п.н.е." - "pre nove ere", "pre Hrista", "p.n.e."] + DateParser.bce + bce = [ + "пре нове ере", + "пре Христа", + "п.н.е." "pre nove ere", + "pre Hrista", + "p.n.e.", + ] + DateParser.bce def init_strings(self): """ @@ -210,38 +215,54 @@ class DateParserSR(DateParser): """ DateParser.init_strings(self) # match 'Day. MONTH year.' format with or without dots - self._text2 = re.compile(r'(\d+)?\.?\s*?%s\s*((\d+)(/\d+)?)?\.?\s*$' - % self._mon_str, re.IGNORECASE) + self._text2 = re.compile( + r"(\d+)?\.?\s*?%s\s*((\d+)(/\d+)?)?\.?\s*$" % self._mon_str, re.IGNORECASE + ) # match Day.Month.Year. - self._numeric = re.compile( - r"((\d+)[/\. ])?\s*((\d+)[/\.])?\s*(\d+)\.?$") + self._numeric = re.compile(r"((\d+)[/\. ])?\s*((\d+)[/\.])?\s*(\d+)\.?$") - _span_1 = ['od', 'од', 'из'] - _span_2 = ['do', 'до'] - _range_1 = ['između', 'између'] - _range_2 = ['i', 'и'] - self._span = re.compile(r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" - % ('|'.join(_span_1), '|'.join(_span_2)), - re.IGNORECASE) - self._range = re.compile(r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" - % ('|'.join(_range_1), '|'.join(_range_2)), - re.IGNORECASE) + _span_1 = ["od", "од", "из"] + _span_2 = ["do", "до"] + _range_1 = ["između", "између"] + _range_2 = ["i", "и"] + self._span = re.compile( + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) + self._range = re.compile( + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Serbian display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplaySR_Base(DateDisplay): """ Serbian (base) date display class """ roman_months = ( - "", "I", "II", "III", "IV", "V", "VI", - "VII", "VIII", "IX", "X", "XI", "XII" - ) + "", + "I", + "II", + "III", + "IV", + "V", + "VI", + "VII", + "VIII", + "IX", + "X", + "XI", + "XII", + ) def _display_gregorian(self, date_val, **kwargs): """ @@ -259,11 +280,11 @@ class DateDisplaySR_Base(DateDisplay): if date_val[0] == 0 and date_val[1] == 0: value = str(date_val[2]) else: - value = self.dhformat.replace('%m', str(date_val[1])) - value = value.replace('%d', str(date_val[0])) - value = value.replace('%Y', str(abs(date_val[2]))) - #some locale magic already provides the right separator - #value = value.replace('/', '.') + value = self.dhformat.replace("%m", str(date_val[1])) + value = value.replace("%d", str(date_val[0])) + value = value.replace("%Y", str(abs(date_val[2]))) + # some locale magic already provides the right separator + # value = value.replace('/', '.') elif self.format == 2: # day. month_abbreviation year. if date_val[0] == 0: @@ -272,8 +293,11 @@ class DateDisplaySR_Base(DateDisplay): else: value = "%s %s." % (self.short_months[date_val[1]], year) else: - value = "%d. %s %s." % (date_val[0], - self.short_months[date_val[1]], year) + value = "%d. %s %s." % ( + date_val[0], + self.short_months[date_val[1]], + year, + ) elif self.format == 3: # day. month_name year. if date_val[0] == 0: @@ -282,8 +306,11 @@ class DateDisplaySR_Base(DateDisplay): else: value = "%s %s." % (self.long_months[date_val[1]], year) else: - value = "%d. %s %s." % (date_val[0], - self.long_months[date_val[1]], year) + value = "%d. %s %s." % ( + date_val[0], + self.long_months[date_val[1]], + year, + ) else: # day. Roman_number_month year. if date_val[0] == 0: @@ -292,8 +319,11 @@ class DateDisplaySR_Base(DateDisplay): else: value = "%s %s." % (self.roman_months[date_val[1]], year) else: - value = "%d. %s %s." % (date_val[0], - self.roman_months[date_val[1]], year) + value = "%d. %s %s." % ( + date_val[0], + self.roman_months[date_val[1]], + year, + ) if date_val[2] < 0: return self._bce_str % value else: @@ -323,41 +353,64 @@ class DateDisplaySR_Base(DateDisplay): d_1 = self.display_cal[cal](start) d_2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, span1, d_1, span2, d_2, - scal) + return "%s%s %s %s %s%s" % (qual_str, span1, d_1, span2, d_2, scal) elif mod == Date.MOD_RANGE: d_1 = self.display_cal[cal](start) d_2 = self.display_cal[cal](date.get_stop_date()) scal = self.format_extras(cal, newyear) - return "%s%s %s %s %s%s" % (qual_str, range1, d_1, range2, d_2, - scal) + return "%s%s %s %s %s%s" % (qual_str, range1, d_1, range2, d_2, scal) else: text = self.display_cal[date.get_calendar()](start) scal = self.format_extras(cal, newyear) - return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, - scal) + return "%s%s%s%s" % (qual_str, self._mod_str[mod], text, scal) + class DateDisplaySR_Latin(DateDisplaySR_Base): """ Serbian (Latin) date display class """ - long_months = ("", - "januara", "februara", "marta", "aprila", - "maja", "juna", "jula", "avgusta", - "septembra", "oktobra", "novembra", "decembra" - ) + long_months = ( + "", + "januara", + "februara", + "marta", + "aprila", + "maja", + "juna", + "jula", + "avgusta", + "septembra", + "oktobra", + "novembra", + "decembra", + ) - short_months = ("", - "jan", "feb", "mar", "apr", "maj", "jun", - "jul", "avg", "sep", "okt", "nov", "dec" - ) + short_months = ( + "", + "jan", + "feb", + "mar", + "apr", + "maj", + "jun", + "jul", + "avg", + "sep", + "okt", + "nov", + "dec", + ) calendar = ( - "", "julijanski", "hebrejski", - "francuski republikanski", "persijski", "islamski", - "švedski" - ) + "", + "julijanski", + "hebrejski", + "francuski republikanski", + "persijski", + "islamski", + "švedski", + ) _mod_str = ("", "pre ", "posle ", "oko ", "", "", "") @@ -370,36 +423,62 @@ class DateDisplaySR_Latin(DateDisplaySR_Base): "Numerički (DD.MM.GGGG.)", "D. MMM GGGG.", "D. Mesec GGGG.", - "D. Rb GGGG." - ) - # this definition must agree with its "_display_gregorian" method + "D. Rb GGGG.", + ) + # this definition must agree with its "_display_gregorian" method + + _span1 = "od" + _span2 = "do" + _range1 = "između" + _range2 = "i" - _span1 = 'od' - _span2 = 'do' - _range1 = 'između' - _range2 = 'i' class DateDisplaySR_Cyrillic(DateDisplaySR_Base): """ Serbian (Cyrillic) date display class """ - long_months = ("", - "Јануар", "Фебруар", "Март", "Април", - "Мај", "Јуне", "Јули", "Аугуст", - "Септембар", "Оцтобер", "Новембер", "Децембар" - ) + long_months = ( + "", + "Јануар", + "Фебруар", + "Март", + "Април", + "Мај", + "Јуне", + "Јули", + "Аугуст", + "Септембар", + "Оцтобер", + "Новембер", + "Децембар", + ) - short_months = ("", - "Јан", "Феб", "Мар", "Апр", "Мај", "Јун", - "Јул", "Авг", "Сеп", "Окт", "Нов", "Дец" - ) + short_months = ( + "", + "Јан", + "Феб", + "Мар", + "Апр", + "Мај", + "Јун", + "Јул", + "Авг", + "Сеп", + "Окт", + "Нов", + "Дец", + ) calendar = ( - "", "Јулиан", "хебрејски", - "француски републиканац", "Персиан", "исламски", - "шведски" - ) + "", + "Јулиан", + "хебрејски", + "француски републиканац", + "Персиан", + "исламски", + "шведски", + ) _mod_str = ("", "пре ", "после ", "око ", "", "", "") @@ -412,25 +491,45 @@ class DateDisplaySR_Cyrillic(DateDisplaySR_Base): "Нумеричка (ДД.ММ.ГГГГ.)", "Д. МММ ГГГГ.", "Д. Месец ГГГГ.", - "Д. Rb ГГГГ." - ) - # this definition must agree with its "_display_gregorian" method + "Д. Rb ГГГГ.", + ) + # this definition must agree with its "_display_gregorian" method - _span1 = 'из' - _span2 = 'до' - _range1 = 'између' - _range2 = 'и' + _span1 = "из" + _span2 = "до" + _range1 = "између" + _range2 = "и" -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('sr_RS.utf8@latin', 'srpski', 'Srpski', - 'sr_Latn', 'sr_Latn_RS', 'sr_RS@latin', ('%d.%m.%Y.',)), - DateParserSR, DateDisplaySR_Latin) + ( + "sr_RS.utf8@latin", + "srpski", + "Srpski", + "sr_Latn", + "sr_Latn_RS", + "sr_RS@latin", + ("%d.%m.%Y.",), + ), + DateParserSR, + DateDisplaySR_Latin, +) register_datehandler( - ('sr_RS', 'sr', 'sr_Cyrl', 'sr_Cyrl_RS', - 'српски', 'Српски', 'serbian', ('%d.%m.%Y.',)), - DateParserSR, DateDisplaySR_Cyrillic) + ( + "sr_RS", + "sr", + "sr_Cyrl", + "sr_Cyrl_RS", + "српски", + "Српски", + "serbian", + ("%d.%m.%Y.",), + ), + DateParserSR, + DateDisplaySR_Cyrillic, +) diff --git a/gramps/gen/datehandler/_date_sv.py b/gramps/gen/datehandler/_date_sv.py index 9c215f571..99ea3a12c 100644 --- a/gramps/gen/datehandler/_date_sv.py +++ b/gramps/gen/datehandler/_date_sv.py @@ -23,28 +23,28 @@ Swedish-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Swedish parser class # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserSv(DateParser): """ Convert a text string into a Date object, expecting a date @@ -54,63 +54,67 @@ class DateParserSv(DateParser): # modifiers before the date modifier_to_int = { - 'före' : Date.MOD_BEFORE, - 'innan' : Date.MOD_BEFORE, - 'efter' : Date.MOD_AFTER, - 'omkring' : Date.MOD_ABOUT, - 'ca' : Date.MOD_ABOUT, - 'c:a' : Date.MOD_ABOUT - } + "före": Date.MOD_BEFORE, + "innan": Date.MOD_BEFORE, + "efter": Date.MOD_AFTER, + "omkring": Date.MOD_ABOUT, + "ca": Date.MOD_ABOUT, + "c:a": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } bce = ["f Kr"] calendar_to_int = { - 'gregoriansk ' : Date.CAL_GREGORIAN, - 'g' : Date.CAL_GREGORIAN, - 'juliansk' : Date.CAL_JULIAN, - 'j' : Date.CAL_JULIAN, - 'hebreisk' : Date.CAL_HEBREW, - 'h' : Date.CAL_HEBREW, - 'islamisk' : Date.CAL_ISLAMIC, - 'muslimsk' : Date.CAL_ISLAMIC, - 'i' : Date.CAL_ISLAMIC, - 'fransk' : Date.CAL_FRENCH, - 'fransk republikansk' : Date.CAL_FRENCH, - 'f' : Date.CAL_FRENCH, - 'persisk' : Date.CAL_PERSIAN, - 'p' : Date.CAL_PERSIAN, - 'svensk' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - } + "gregoriansk ": Date.CAL_GREGORIAN, + "g": Date.CAL_GREGORIAN, + "juliansk": Date.CAL_JULIAN, + "j": Date.CAL_JULIAN, + "hebreisk": Date.CAL_HEBREW, + "h": Date.CAL_HEBREW, + "islamisk": Date.CAL_ISLAMIC, + "muslimsk": Date.CAL_ISLAMIC, + "i": Date.CAL_ISLAMIC, + "fransk": Date.CAL_FRENCH, + "fransk republikansk": Date.CAL_FRENCH, + "f": Date.CAL_FRENCH, + "persisk": Date.CAL_PERSIAN, + "p": Date.CAL_PERSIAN, + "svensk": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } quality_to_int = { - 'uppskattat' : Date.QUAL_ESTIMATED, - 'uppskattad' : Date.QUAL_ESTIMATED, - 'bedömt' : Date.QUAL_ESTIMATED, - 'bedömd' : Date.QUAL_ESTIMATED, - 'beräknat' : Date.QUAL_CALCULATED, - 'beräknad' : Date.QUAL_CALCULATED, - } + "uppskattat": Date.QUAL_ESTIMATED, + "uppskattad": Date.QUAL_ESTIMATED, + "bedömt": Date.QUAL_ESTIMATED, + "bedömd": Date.QUAL_ESTIMATED, + "beräknat": Date.QUAL_CALCULATED, + "beräknad": Date.QUAL_CALCULATED, + } def init_strings(self): - """ Define, in Swedish, span and range regular expressions""" + """Define, in Swedish, span and range regular expressions""" DateParser.init_strings(self) self._numeric = re.compile(r"((\d+)/)?\s*((\d+)/)?\s*(\d+)[/ ]?$") # this next RE has the (possibly-slashed) year at the string's start - self._text2 = re.compile(r'((\d+)(/\d+)?)?\s+?%s\s*(\d+)?\s*$' - % self._mon_str, re.IGNORECASE) + self._text2 = re.compile( + r"((\d+)(/\d+)?)?\s+?%s\s*(\d+)?\s*$" % self._mon_str, re.IGNORECASE + ) self._span = re.compile( - r"(från)?\s*(?P.+)\s*(till|--|–)\s*(?P.+)", - re.IGNORECASE) + r"(från)?\s*(?P.+)\s*(till|--|–)\s*(?P.+)", re.IGNORECASE + ) self._range = re.compile( - r"(mellan)\s+(?P.+)\s+och\s+(?P.+)", - re.IGNORECASE) + r"(mellan)\s+(?P.+)\s+och\s+(?P.+)", re.IGNORECASE + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Swedish display class # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplaySv(DateDisplay): """ Swedish language date display class. @@ -123,11 +127,10 @@ class DateDisplaySv(DateDisplay): "År/mån/dag", "År månad dag", "År mån dag", - ) - # this definition must agree with its "_display_calendar" method + ) + # this definition must agree with its "_display_calendar" method - def _display_calendar(self, date_val, long_months, short_months = None, - inflect=""): + def _display_calendar(self, date_val, long_months, short_months=None, inflect=""): # this must agree with its locale-specific "formats" definition if short_months is None: @@ -160,7 +163,7 @@ class DateDisplaySv(DateDisplay): return year else: return "%s %s" % (year, long_months[date_val[1]]) - elif date_val[1] == 0: # month is zero but day is not (see 8477) + elif date_val[1] == 0: # month is zero but day is not (see 8477) return self.display_iso(date_val) else: return "%s %s %s" % (year, long_months[date_val[1]], date_val[0]) @@ -173,18 +176,21 @@ class DateDisplaySv(DateDisplay): return year else: return "%s %s" % (year, short_months[date_val[1]]) - elif date_val[1] == 0: # month is zero but day is not (see 8477) + elif date_val[1] == 0: # month is zero but day is not (see 8477) return self.display_iso(date_val) else: return "%s %s %s" % (year, short_months[date_val[1]], date_val[0]) display = DateDisplay.display_formatted -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('sv_SE', 'sv_SE.UTF-8', 'sv', 'Swedish', ('%Y-%m-%d',)), - DateParserSv, DateDisplaySv) + ("sv_SE", "sv_SE.UTF-8", "sv", "Swedish", ("%Y-%m-%d",)), + DateParserSv, + DateDisplaySv, +) diff --git a/gramps/gen/datehandler/_date_uk.py b/gramps/gen/datehandler/_date_uk.py index 82a468a7f..cfbf142e5 100644 --- a/gramps/gen/datehandler/_date_uk.py +++ b/gramps/gen/datehandler/_date_uk.py @@ -24,29 +24,29 @@ Ukrainian-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Ukrainian parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserUK(DateParser): """ Convert a text string into a :class:`.Date` object. If the date cannot be @@ -55,41 +55,42 @@ class DateParserUK(DateParser): # modifiers before the date modifier_to_int = { - 'перед' : Date.MOD_BEFORE, - 'до' : Date.MOD_BEFORE, - 'раніше' : Date.MOD_BEFORE, - - 'після' : Date.MOD_AFTER, - 'п.' : Date.MOD_AFTER, - 'за' : Date.MOD_AFTER, - - 'приблизно': Date.MOD_ABOUT, - 'прибл.' : Date.MOD_ABOUT, - 'приб.' : Date.MOD_ABOUT, - 'близько' : Date.MOD_ABOUT, - 'бл.' : Date.MOD_ABOUT, - 'біля' : Date.MOD_ABOUT, - } + "перед": Date.MOD_BEFORE, + "до": Date.MOD_BEFORE, + "раніше": Date.MOD_BEFORE, + "після": Date.MOD_AFTER, + "п.": Date.MOD_AFTER, + "за": Date.MOD_AFTER, + "приблизно": Date.MOD_ABOUT, + "прибл.": Date.MOD_ABOUT, + "приб.": Date.MOD_ABOUT, + "близько": Date.MOD_ABOUT, + "бл.": Date.MOD_ABOUT, + "біля": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } quality_to_int = { - 'за оцінкою' : Date.QUAL_ESTIMATED, - 'за оц.' : Date.QUAL_ESTIMATED, - 'оцінено' : Date.QUAL_ESTIMATED, - 'орієнтовно' : Date.QUAL_ESTIMATED, - 'приблизно' : Date.QUAL_ESTIMATED, - 'прибл.' : Date.QUAL_ESTIMATED, - - 'підраховано' : Date.QUAL_CALCULATED, - 'підрах.' : Date.QUAL_CALCULATED, - 'розраховано' : Date.QUAL_CALCULATED, - 'розрахунково' : Date.QUAL_CALCULATED, - 'розрах.' : Date.QUAL_CALCULATED, - } + "за оцінкою": Date.QUAL_ESTIMATED, + "за оц.": Date.QUAL_ESTIMATED, + "оцінено": Date.QUAL_ESTIMATED, + "орієнтовно": Date.QUAL_ESTIMATED, + "приблизно": Date.QUAL_ESTIMATED, + "прибл.": Date.QUAL_ESTIMATED, + "підраховано": Date.QUAL_CALCULATED, + "підрах.": Date.QUAL_CALCULATED, + "розраховано": Date.QUAL_CALCULATED, + "розрахунково": Date.QUAL_CALCULATED, + "розрах.": Date.QUAL_CALCULATED, + } bce = [ - 'до нашої ери', 'до н. е.', 'до н.е.', - 'до народження Христа' - ] + DateParser.bce + "до нашої ери", + "до н. е.", + "до н.е.", + "до народження Христа", + ] + DateParser.bce def init_strings(self): """ @@ -99,30 +100,37 @@ class DateParserUK(DateParser): """ DateParser.init_strings(self) - DateParser.hebrew_to_int.update({ - 'мархешван': 2, - 'ве адар' : 7, - 'адар бет' : 7, - 'авів' : 8, - }) + DateParser.hebrew_to_int.update( + { + "мархешван": 2, + "ве адар": 7, + "адар бет": 7, + "авів": 8, + } + ) - _span_1 = ['з', 'від'] + _span_1 = ["з", "від"] # b.c.e. pattern also have "до" so skip "до н." - _span_2 = ['по', r'до(?!\s+н)'] - _range_1 = ['між'] - _range_2 = ['і', 'та'] - self._span = re.compile(r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" % - ('|'.join(_span_1), '|'.join(_span_2)), - re.IGNORECASE) - self._range = re.compile(r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" - % ('|'.join(_range_1), '|'.join(_range_2)), - re.IGNORECASE) + _span_2 = ["по", r"до(?!\s+н)"] + _range_1 = ["між"] + _range_2 = ["і", "та"] + self._span = re.compile( + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) + self._range = re.compile( + r"(%s)\s+(?P.+)\s+(%s)\s+(?P.+)" + % ("|".join(_range_1), "|".join(_range_2)), + re.IGNORECASE, + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Ukrainian displayer # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayUK(DateDisplay): """ Ukrainian language date display class. @@ -133,11 +141,13 @@ class DateDisplayUK(DateDisplay): display = DateDisplay.display_formatted -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('uk_UA', 'uk', 'ukrainian', 'Ukrainian', ('%d.%m.%Y',)), - DateParserUK, DateDisplayUK) + ("uk_UA", "uk", "ukrainian", "Ukrainian", ("%d.%m.%Y",)), + DateParserUK, + DateDisplayUK, +) diff --git a/gramps/gen/datehandler/_date_zh_CN.py b/gramps/gen/datehandler/_date_zh_CN.py index bffe0e560..2e4fa947c 100644 --- a/gramps/gen/datehandler/_date_zh_CN.py +++ b/gramps/gen/datehandler/_date_zh_CN.py @@ -24,29 +24,29 @@ Simplified-Chinese-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Simplified-Chinese parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserZH_CN(DateParser): """ Convert a text string into a Date object. If the date cannot be @@ -55,10 +55,12 @@ class DateParserZH_CN(DateParser): # modifiers before the date modifier_to_int = { - '以前' : Date.MOD_BEFORE, - '以后' : Date.MOD_AFTER, - '大约' : Date.MOD_ABOUT, - } + "以前": Date.MOD_BEFORE, + "以后": Date.MOD_AFTER, + "大约": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } month_to_int = DateParser.month_to_int @@ -91,26 +93,26 @@ class DateParserZH_CN(DateParser): month_to_int["jiǎ rùn yùe"] = 13 calendar_to_int = { - '阳历' : Date.CAL_GREGORIAN, - 'g' : Date.CAL_GREGORIAN, - '儒略历' : Date.CAL_JULIAN, - 'j' : Date.CAL_JULIAN, - '希伯来历' : Date.CAL_HEBREW, - 'h' : Date.CAL_HEBREW, - '伊斯兰历' : Date.CAL_ISLAMIC, - 'i' : Date.CAL_ISLAMIC, - '法国共和历' : Date.CAL_FRENCH, - 'f' : Date.CAL_FRENCH, - '伊郎历' : Date.CAL_PERSIAN, - 'p' : Date.CAL_PERSIAN, - '瑞典历' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - } + "阳历": Date.CAL_GREGORIAN, + "g": Date.CAL_GREGORIAN, + "儒略历": Date.CAL_JULIAN, + "j": Date.CAL_JULIAN, + "希伯来历": Date.CAL_HEBREW, + "h": Date.CAL_HEBREW, + "伊斯兰历": Date.CAL_ISLAMIC, + "i": Date.CAL_ISLAMIC, + "法国共和历": Date.CAL_FRENCH, + "f": Date.CAL_FRENCH, + "伊郎历": Date.CAL_PERSIAN, + "p": Date.CAL_PERSIAN, + "瑞典历": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } quality_to_int = { - '据估计' : Date.QUAL_ESTIMATED, - '据计算' : Date.QUAL_CALCULATED, - } + "据估计": Date.QUAL_ESTIMATED, + "据计算": Date.QUAL_CALCULATED, + } # FIXME translate these English strings into simplified-Chinese ones bce = ["before calendar", "negative year"] + DateParser.bce @@ -120,41 +122,46 @@ class DateParserZH_CN(DateParser): This method compiles regular expression strings for matching dates. """ DateParser.init_strings(self) - _span_1 = ['自'] - _span_2 = ['至'] - _range_1 = ['介于'] - _range_2 = ['与'] - _range_3 = ['之间'] - self._span = re.compile(r"(%s)\s*(?P.+)\s*(%s)\s*(?P.+)" % - ('|'.join(_span_1), '|'.join(_span_2)), - re.IGNORECASE) - self._range = re.compile(r"(%s)\s*(?P.+)\s*(%s)\s*(?P.+)\s*(%s)" % - ('|'.join(_range_1), '|'.join(_range_2), '|'.join(_range_3)), - re.IGNORECASE) + _span_1 = ["自"] + _span_2 = ["至"] + _range_1 = ["介于"] + _range_2 = ["与"] + _range_3 = ["之间"] + self._span = re.compile( + r"(%s)\s*(?P.+)\s*(%s)\s*(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) + self._range = re.compile( + r"(%s)\s*(?P.+)\s*(%s)\s*(?P.+)\s*(%s)" + % ("|".join(_range_1), "|".join(_range_2), "|".join(_range_3)), + re.IGNORECASE, + ) self._numeric = re.compile(r"((\d+)年\s*)?((\d+)月\s*)?(\d+)?日?\s*$") -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Simplified-Chinese display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayZH_CN(DateDisplay): """ Simplified-Chinese language date display class. """ formats = ( - "年年年年-月月-日日 (ISO)", "数字格式", - ) - # this definition must agree with its "_display_calendar" method + "年年年年-月月-日日 (ISO)", + "数字格式", + ) + # this definition must agree with its "_display_calendar" method # FIXME translate these English strings into simplified-Chinese ones _bce_str = "%s B.C.E." display = DateDisplay.display_formatted - def _display_calendar(self, date_val, long_months, short_months = None, - inflect=""): + def _display_calendar(self, date_val, long_months, short_months=None, inflect=""): # this must agree with its locale-specific "formats" definition if short_months is None: @@ -173,12 +180,15 @@ class DateDisplayZH_CN(DateDisplay): else: return value -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('zh_CN', 'zh_SG', 'zh', 'chinese', 'Chinese', ('%Y年%m月%d日',)), - DateParserZH_CN, DateDisplayZH_CN) + ("zh_CN", "zh_SG", "zh", "chinese", "Chinese", ("%Y年%m月%d日",)), + DateParserZH_CN, + DateDisplayZH_CN, +) diff --git a/gramps/gen/datehandler/_date_zh_TW.py b/gramps/gen/datehandler/_date_zh_TW.py index fbfdfc383..e8b6bac02 100644 --- a/gramps/gen/datehandler/_date_zh_TW.py +++ b/gramps/gen/datehandler/_date_zh_TW.py @@ -24,29 +24,29 @@ Traditional-Chinese-specific classes for parsing and displaying dates. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ._dateparser import DateParser from ._datedisplay import DateDisplay from ._datehandler import register_datehandler -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Traditional-Chinese parser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParserZH_TW(DateParser): """ Convert a text string into a Date object. If the date cannot be @@ -55,10 +55,12 @@ class DateParserZH_TW(DateParser): # modifiers before the date modifier_to_int = { - '以前' : Date.MOD_BEFORE, - '以後' : Date.MOD_AFTER, - '大約' : Date.MOD_ABOUT, - } + "以前": Date.MOD_BEFORE, + "以後": Date.MOD_AFTER, + "大約": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } month_to_int = DateParser.month_to_int @@ -91,26 +93,26 @@ class DateParserZH_TW(DateParser): month_to_int["jiǎ rùn yùe"] = 13 calendar_to_int = { - '陽曆' : Date.CAL_GREGORIAN, - 'g' : Date.CAL_GREGORIAN, - '儒略曆' : Date.CAL_JULIAN, - 'j' : Date.CAL_JULIAN, - '希伯來歷' : Date.CAL_HEBREW, - 'h' : Date.CAL_HEBREW, - '伊斯蘭曆' : Date.CAL_ISLAMIC, - 'i' : Date.CAL_ISLAMIC, - '法國共和歷' : Date.CAL_FRENCH, - 'f' : Date.CAL_FRENCH, - '伊郎歷' : Date.CAL_PERSIAN, - 'p' : Date.CAL_PERSIAN, - '瑞典歷' : Date.CAL_SWEDISH, - 's' : Date.CAL_SWEDISH, - } + "陽曆": Date.CAL_GREGORIAN, + "g": Date.CAL_GREGORIAN, + "儒略曆": Date.CAL_JULIAN, + "j": Date.CAL_JULIAN, + "希伯來歷": Date.CAL_HEBREW, + "h": Date.CAL_HEBREW, + "伊斯蘭曆": Date.CAL_ISLAMIC, + "i": Date.CAL_ISLAMIC, + "法國共和歷": Date.CAL_FRENCH, + "f": Date.CAL_FRENCH, + "伊郎歷": Date.CAL_PERSIAN, + "p": Date.CAL_PERSIAN, + "瑞典歷": Date.CAL_SWEDISH, + "s": Date.CAL_SWEDISH, + } quality_to_int = { - '據估計' : Date.QUAL_ESTIMATED, - '據計算' : Date.QUAL_CALCULATED, - } + "據估計": Date.QUAL_ESTIMATED, + "據計算": Date.QUAL_CALCULATED, + } # FIXME translate these English strings into traditional-Chinese ones bce = ["before calendar", "negative year"] + DateParser.bce @@ -120,41 +122,46 @@ class DateParserZH_TW(DateParser): This method compiles regular expression strings for matching dates. """ DateParser.init_strings(self) - _span_1 = ['自'] - _span_2 = ['至'] - _range_1 = ['介於'] - _range_2 = ['與'] - _range_3 = ['之間'] - self._span = re.compile(r"(%s)\s*(?P.+)\s*(%s)\s*(?P.+)" % - ('|'.join(_span_1), '|'.join(_span_2)), - re.IGNORECASE) - self._range = re.compile(r"(%s)\s*(?P.+)\s*(%s)\s*(?P.+)\s*(%s)" % - ('|'.join(_range_1), '|'.join(_range_2), '|'.join(_range_3)), - re.IGNORECASE) + _span_1 = ["自"] + _span_2 = ["至"] + _range_1 = ["介於"] + _range_2 = ["與"] + _range_3 = ["之間"] + self._span = re.compile( + r"(%s)\s*(?P.+)\s*(%s)\s*(?P.+)" + % ("|".join(_span_1), "|".join(_span_2)), + re.IGNORECASE, + ) + self._range = re.compile( + r"(%s)\s*(?P.+)\s*(%s)\s*(?P.+)\s*(%s)" + % ("|".join(_range_1), "|".join(_range_2), "|".join(_range_3)), + re.IGNORECASE, + ) self._numeric = re.compile(r"((\d+)年\s*)?((\d+)月\s*)?(\d+)?日?\s*$") -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Traditional-Chinese display # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplayZH_TW(DateDisplay): """ Traditional-Chinese language date display class. """ formats = ( - "年年年年-月月-日日 (ISO)", "數字格式", - ) - # this definition must agree with its "_display_calendar" method + "年年年年-月月-日日 (ISO)", + "數字格式", + ) + # this definition must agree with its "_display_calendar" method # FIXME translate these English strings into traditional-Chinese ones _bce_str = "%s B.C.E." display = DateDisplay.display_formatted - def _display_calendar(self, date_val, long_months, short_months = None, - inflect=""): + def _display_calendar(self, date_val, long_months, short_months=None, inflect=""): # this must agree with its locale-specific "formats" definition if short_months is None: @@ -173,12 +180,13 @@ class DateDisplayZH_TW(DateDisplay): else: return value -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Register classes # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- register_datehandler( - ('zh_TW', 'zh_HK', ('西元%Y年%m月%d日',)), - DateParserZH_TW, DateDisplayZH_TW) + ("zh_TW", "zh_HK", ("西元%Y年%m月%d日",)), DateParserZH_TW, DateDisplayZH_TW +) diff --git a/gramps/gen/datehandler/_datedisplay.py b/gramps/gen/datehandler/_datedisplay.py index 01d4a99ec..a72830d46 100644 --- a/gramps/gen/datehandler/_datedisplay.py +++ b/gramps/gen/datehandler/_datedisplay.py @@ -26,40 +26,42 @@ U.S English date display class. Should serve as the base class for all localized tasks. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import datetime -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # set up logging # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import logging + log = logging.getLogger(".DateDisplay") -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date from ..const import GRAMPS_LOCALE as glocale from ..utils.grampslocale import GrampsLocale from ._datestrings import DateStrings # _T_ is a gramps-defined keyword -- see po/update_po.py and po/genpot.sh -def _T_(value, context=''): # enable deferred translations +def _T_(value, context=""): # enable deferred translations return "%s\x04%s" % (context, value) if context else value -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # DateDisplay # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateDisplay: """ Base date display class. @@ -69,7 +71,6 @@ class DateDisplay: # format 0 - must always be ISO # Translators: Numeric year, month, day _T_("YYYY-MM-DD (ISO)"), - # format # 1 - must always be locale-preferred numerical format # such as YY.MM.DD, MM-DD-YY, or whatever your locale prefers. # This should be the format that is used under the locale by @@ -77,19 +78,15 @@ class DateDisplay: # Translators: You may translate this as "Numerical", # "System preferred", or similar. _T_("Numerical", "date format"), - # Translators: Full month name, day, year _T_("Month Day, Year"), - # Translators: Abbreviated month name, day, year _T_("MON DAY, YEAR"), - # Translators: Day, full month name, year _T_("Day Month Year"), - # Translators: Day, abbreviated month name, year - _T_("DAY MON YEAR") - ) + _T_("DAY MON YEAR"), + ) """ .. note:: Will be overridden if a locale-specific date displayer exists. @@ -110,19 +107,20 @@ class DateDisplay: :param blocale: allow translation of dates and date formats :type blocale: a :class:`.GrampsLocale` instance """ - from ._datehandler import locale_tformat # circular import if above + from ._datehandler import locale_tformat # circular import if above + if blocale: self._locale = blocale - elif not hasattr(self, '_locale'): + elif not hasattr(self, "_locale"): self._locale = glocale if self._locale.calendar in locale_tformat: - self.dhformat = locale_tformat[self._locale.calendar] # date format + self.dhformat = locale_tformat[self._locale.calendar] # date format else: - self.dhformat = locale_tformat['en_GB'] # something is required - self.formats_changed() # allow overriding so a subclass can modify + self.dhformat = locale_tformat["en_GB"] # something is required + self.formats_changed() # allow overriding so a subclass can modify self._ds = DateStrings(self._locale) calendar = list(self._ds.calendar) - calendar[Date.CAL_GREGORIAN] = "" # that string only used in parsing, + calendar[Date.CAL_GREGORIAN] = "" # that string only used in parsing, # gregorian cal name shouldn't be output! self.calendar = tuple(calendar) self.short_months = self._ds.short_months @@ -138,11 +136,12 @@ class DateDisplay: self._display_french, self._display_persian, self._display_islamic, - self._display_swedish] + self._display_swedish, + ] self._mod_str = self._ds.modifiers self._qual_str = self._ds.qualifiers self.long_days = self._ds.long_days - self.short_days = self._ds.short_days # Icelandic needs this + self.short_days = self._ds.short_days # Icelandic needs this if format is None: self.format = 0 @@ -151,179 +150,159 @@ class DateDisplay: self._ = _ = self._locale.translation.sgettext self.FORMATS_long_month_year = { -# Inflection control due to modifier. -# Protocol: DateDisplayXX passes a key to the dictionary in the -# parameter ``inflect`` to ``_display_calendar``. -# The modifier passed is not necessarily the one printed, it's just -# a representative that induces the same inflection control. -# For example, in Russian "before May", "after May", and "about May" -# all require genitive form for May, whereas no modifier (just "May 1234") -# require nominative, so DateDisplayRU.display will pass "before" -# in all 3 cases, collapsing the 3 modifiers into 1. -# -# Another example in Russian is that "between April 1234 and June 1235" -# requires the same inflection for both April and June, so just "between" -# is used by DateDisplayRU.display, collapsing two more modifiers into 1. -# -# If inflect is not specified, then it means that the modifier doesn't have -# grammatical control over the format, and so the format can be -# localized in a context-free way. -# The translator is responsible for: -# 1) proper collapse of modifier classes -# 2) translating the formats that are selected in runtime -# 3) ignoring the other formats in .po (it does no harm to translate them, -# it's just a lot of extra work) -# -# To prevent POT pollution, not all possibilities are populated here yet. -# To be amended as the actual localized handlers use it. -# -# Not moving to DateStrings, as this is part of display code only, -# coupled tightly with the formats used in this file. - "" - : _("{long_month} {year}"), - - "from" - # first date in a span - # Translators: If "from " needs a special inflection - # in your language, translate to "{long_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{long_month} {year}", "from"), - - "to" - # second date in a span - # Translators: If "to " needs a special inflection - # in your language, translate to "{long_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{long_month} {year}", "to"), - - "between" - # first date in a range - # Translators: If "between " needs a special inflection - # in your language, translate to "{long_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{long_month} {year}", "between"), - - "and" - # second date in a range - # Translators: If "and " needs a special inflection - # in your language, translate to "{long_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{long_month} {year}", "and"), - - "before" - # Translators: If "before " needs a special inflection - # in your language, translate to "{long_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{long_month} {year}", "before"), - - "after" - # Translators: If "after " needs a special inflection - # in your language, translate to "{long_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{long_month} {year}", "after"), - - "about" - # Translators: If "about " needs a special inflection - # in your language, translate to "{long_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{long_month} {year}", "about"), - - "estimated" - # Translators: If "estimated " needs a special inflection - # in your language, translate to "{long_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{long_month} {year}", "estimated"), - - "calculated" - # Translators: If "calculated " needs a special inflection - # in your language, translate to "{long_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{long_month} {year}", "calculated"), + # Inflection control due to modifier. + # Protocol: DateDisplayXX passes a key to the dictionary in the + # parameter ``inflect`` to ``_display_calendar``. + # The modifier passed is not necessarily the one printed, it's just + # a representative that induces the same inflection control. + # For example, in Russian "before May", "after May", and "about May" + # all require genitive form for May, whereas no modifier (just "May 1234") + # require nominative, so DateDisplayRU.display will pass "before" + # in all 3 cases, collapsing the 3 modifiers into 1. + # + # Another example in Russian is that "between April 1234 and June 1235" + # requires the same inflection for both April and June, so just "between" + # is used by DateDisplayRU.display, collapsing two more modifiers into 1. + # + # If inflect is not specified, then it means that the modifier doesn't have + # grammatical control over the format, and so the format can be + # localized in a context-free way. + # The translator is responsible for: + # 1) proper collapse of modifier classes + # 2) translating the formats that are selected in runtime + # 3) ignoring the other formats in .po (it does no harm to translate them, + # it's just a lot of extra work) + # + # To prevent POT pollution, not all possibilities are populated here yet. + # To be amended as the actual localized handlers use it. + # + # Not moving to DateStrings, as this is part of display code only, + # coupled tightly with the formats used in this file. + "": _("{long_month} {year}"), + "from" + # first date in a span + # Translators: If "from " needs a special inflection + # in your language, translate to "{long_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{long_month} {year}", "from"), + "to" + # second date in a span + # Translators: If "to " needs a special inflection + # in your language, translate to "{long_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{long_month} {year}", "to"), + "between" + # first date in a range + # Translators: If "between " needs a special inflection + # in your language, translate to "{long_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{long_month} {year}", "between"), + "and" + # second date in a range + # Translators: If "and " needs a special inflection + # in your language, translate to "{long_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{long_month} {year}", "and"), + "before" + # Translators: If "before " needs a special inflection + # in your language, translate to "{long_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{long_month} {year}", "before"), + "after" + # Translators: If "after " needs a special inflection + # in your language, translate to "{long_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{long_month} {year}", "after"), + "about" + # Translators: If "about " needs a special inflection + # in your language, translate to "{long_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{long_month} {year}", "about"), + "estimated" + # Translators: If "estimated " needs a special inflection + # in your language, translate to "{long_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{long_month} {year}", "estimated"), + "calculated" + # Translators: If "calculated " needs a special inflection + # in your language, translate to "{long_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{long_month} {year}", "calculated"), } self.FORMATS_short_month_year = { - "" - : _("{short_month} {year}"), - - "from" - # first date in a span - # Translators: If "from " needs a special inflection - # in your language, translate to "{short_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{short_month} {year}", "from"), - - "to" - # second date in a span - # Translators: If "to " needs a special inflection - # in your language, translate to "{short_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{short_month} {year}", "to"), - - "between" - # first date in a range - # Translators: If "between " needs a special inflection - # in your language, translate to "{short_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{short_month} {year}", "between"), - - "and" - # second date in a range - # Translators: If "and " needs a special inflection - # in your language, translate to "{short_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{short_month} {year}", "and"), - - "before" - # Translators: If "before " needs a special inflection - # in your language, translate to "{short_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{short_month} {year}", "before"), - - "after" - # Translators: If "after " needs a special inflection - # in your language, translate to "{short_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{short_month} {year}", "after"), - - "about" - # Translators: If "about " needs a special inflection - # in your language, translate to "{short_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{short_month} {year}", "about"), - - "estimated" - # Translators: If "estimated " needs a special inflection - # in your language, translate to "{short_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{short_month} {year}", "estimated"), - - "calculated" - # Translators: If "calculated " needs a special inflection - # in your language, translate to "{short_month.f[X]} {year}" - # (where X is one of the month-name inflections you defined) - # else leave it untranslated - : _("{short_month} {year}", "calculated"), + "": _("{short_month} {year}"), + "from" + # first date in a span + # Translators: If "from " needs a special inflection + # in your language, translate to "{short_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{short_month} {year}", "from"), + "to" + # second date in a span + # Translators: If "to " needs a special inflection + # in your language, translate to "{short_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{short_month} {year}", "to"), + "between" + # first date in a range + # Translators: If "between " needs a special inflection + # in your language, translate to "{short_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{short_month} {year}", "between"), + "and" + # second date in a range + # Translators: If "and " needs a special inflection + # in your language, translate to "{short_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{short_month} {year}", "and"), + "before" + # Translators: If "before " needs a special inflection + # in your language, translate to "{short_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{short_month} {year}", "before"), + "after" + # Translators: If "after " needs a special inflection + # in your language, translate to "{short_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{short_month} {year}", "after"), + "about" + # Translators: If "about " needs a special inflection + # in your language, translate to "{short_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{short_month} {year}", "about"), + "estimated" + # Translators: If "estimated " needs a special inflection + # in your language, translate to "{short_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{short_month} {year}", "estimated"), + "calculated" + # Translators: If "calculated " needs a special inflection + # in your language, translate to "{short_month.f[X]} {year}" + # (where X is one of the month-name inflections you defined) + # else leave it untranslated + : _("{short_month} {year}", "calculated"), } def formats_changed(self): - """ Allow overriding so a subclass can modify """ + """Allow overriding so a subclass can modify""" pass def set_format(self, format): @@ -386,15 +365,15 @@ class DateDisplay: def _slash_year(self, val, slash): if val < 0: - val = - val + val = -val if slash: - if (val-1) % 100 == 99: - year = "%d/%d" % (val - 1, (val%1000)) - elif (val-1) % 10 == 9: - year = "%d/%d" % (val - 1, (val%100)) + if (val - 1) % 100 == 99: + year = "%d/%d" % (val - 1, (val % 1000)) + elif (val - 1) % 10 == 9: + year = "%d/%d" % (val - 1, (val % 100)) else: - year = "%d/%d" % (val - 1, (val%10)) + year = "%d/%d" % (val - 1, (val % 10)) else: year = "%d" % (val) @@ -425,22 +404,28 @@ class DateDisplay: cal = date.get_calendar() qual_str = self._qual_str[date.get_quality()] scal = self.format_extras(cal, date.get_new_year()) - d1 = self.display_cal[cal](date.get_start_date(), + d1 = self.display_cal[cal]( + date.get_start_date(), # Translators: If there is no special inflection for # "from " in your language, DON'T translate this. # Otherwise, translate to "from" in ENGLISH!!! ENGLISH!!! - inflect=self._("", "from-date")) - d2 = self.display_cal[cal](date.get_stop_date(), + inflect=self._("", "from-date"), + ) + d2 = self.display_cal[cal]( + date.get_stop_date(), # Translators: If there is no special inflection for # "to " in your language, DON'T translate this. # Otherwise, translate to "to" in ENGLISH!!! ENGLISH!!! - inflect=self._("", "to-date")) - return self._("{date_quality}from {date_start} to {date_stop}" - "{nonstd_calendar_and_ny}").format( - date_quality=qual_str, - date_start=d1, - date_stop=d2, - nonstd_calendar_and_ny=scal) + inflect=self._("", "to-date"), + ) + return self._( + "{date_quality}from {date_start} to {date_stop}" "{nonstd_calendar_and_ny}" + ).format( + date_quality=qual_str, + date_start=d1, + date_stop=d2, + nonstd_calendar_and_ny=scal, + ) def dd_range(self, date): """ @@ -450,22 +435,29 @@ class DateDisplay: cal = date.get_calendar() qual_str = self._qual_str[date.get_quality()] scal = self.format_extras(cal, date.get_new_year()) - d1 = self.display_cal[cal](date.get_start_date(), + d1 = self.display_cal[cal]( + date.get_start_date(), # Translators: If there is no special inflection for # "between " in your language, DON'T translate this. # Otherwise, translate to "between" in ENGLISH!!! ENGLISH!!! - inflect=self._("", "between-date")) - d2 = self.display_cal[cal](date.get_stop_date(), + inflect=self._("", "between-date"), + ) + d2 = self.display_cal[cal]( + date.get_stop_date(), # Translators: If there is no special inflection for # "and " in your language, DON'T translate this. # Otherwise, translate to "and" in ENGLISH!!! ENGLISH!!! - inflect=self._("", "and-date")) - return self._("{date_quality}between {date_start} and {date_stop}" - "{nonstd_calendar_and_ny}").format( - date_quality=qual_str, - date_start=d1, - date_stop=d2, - nonstd_calendar_and_ny=scal) + inflect=self._("", "and-date"), + ) + return self._( + "{date_quality}between {date_start} and {date_stop}" + "{nonstd_calendar_and_ny}" + ).format( + date_quality=qual_str, + date_start=d1, + date_stop=d2, + nonstd_calendar_and_ny=scal, + ) def display_formatted(self, date): """ @@ -499,6 +491,16 @@ class DateDisplay: # "after " in your language, DON'T translate this. # Otherwise, translate to "after" in ENGLISH!!! ENGLISH!!! date_type = _("", "after-date") + elif mod == Date.MOD_FROM: + # Translators: If there is no special inflection for + # "after " in your language, DON'T translate this. + # Otherwise, translate to "after" in ENGLISH!!! ENGLISH!!! + date_type = _("", "from-date") + elif mod == Date.MOD_TO: + # Translators: If there is no special inflection for + # "after " in your language, DON'T translate this. + # Otherwise, translate to "after" in ENGLISH!!! ENGLISH!!! + date_type = _("", "to-date") elif mod == Date.MOD_ABOUT: # Translators: If there is no special inflection for # "about " in your language, DON'T translate this. @@ -528,70 +530,89 @@ class DateDisplay: modifier = self._mod_str[mod] # some languages have a modifier after the date (e.g. Finnish) # (if so, they are specified in DateParser.modifier_after_to_int) - if modifier.startswith(' '): + if modifier.startswith(" "): text += modifier - modifier = '' + modifier = "" scal = self.format_extras(cal, newyear) - return _("{date_quality}{noncompound_modifier}{date}" - "{nonstd_calendar_and_ny}").format( - date_quality=qual_str, - noncompound_modifier=modifier, - date=text, - nonstd_calendar_and_ny=scal) + return _( + "{date_quality}{noncompound_modifier}{date}" "{nonstd_calendar_and_ny}" + ).format( + date_quality=qual_str, + noncompound_modifier=modifier, + date=text, + nonstd_calendar_and_ny=scal, + ) def _display_gregorian(self, date_val, **kwargs): - return self._display_calendar(date_val, self.long_months, - self.short_months, **kwargs) + return self._display_calendar( + date_val, self.long_months, self.short_months, **kwargs + ) # Julian and Swedish date display is the same as Gregorian _display_julian = _display_swedish = _display_gregorian def format_long_month_year(self, month, year, inflect, long_months): - if not hasattr(long_months[1], 'f'): # not a Lexeme: no inflection + if not hasattr(long_months[1], "f"): # not a Lexeme: no inflection return "{long_month} {year}".format( - long_month = long_months[month], year = year) + long_month=long_months[month], year=year + ) return self.FORMATS_long_month_year[inflect].format( - long_month = long_months[month], year = year) + long_month=long_months[month], year=year + ) def format_short_month_year(self, month, year, inflect, short_months): - if not hasattr(short_months[1], 'f'): # not a Lexeme: no inflection + if not hasattr(short_months[1], "f"): # not a Lexeme: no inflection return "{short_month} {year}".format( - short_month = short_months[month], year = year) + short_month=short_months[month], year=year + ) return self.FORMATS_short_month_year[inflect].format( - short_month = short_months[month], year = year) + short_month=short_months[month], year=year + ) def format_long_month(self, month, inflect, long_months): - if not hasattr(long_months[1], 'f'): # not a Lexeme: no inflection - return "{long_month}".format(long_month = long_months[month]) - return self.FORMATS_long_month_year[inflect].format( - long_month = long_months[month], year = '').rstrip() + if not hasattr(long_months[1], "f"): # not a Lexeme: no inflection + return "{long_month}".format(long_month=long_months[month]) + return ( + self.FORMATS_long_month_year[inflect] + .format(long_month=long_months[month], year="") + .rstrip() + ) def format_short_month(self, month, inflect, short_months): - if not hasattr(short_months[1], 'f'): # not a Lexeme: no inflection - return "{short_month}".format(short_month = short_months[month]) - return self.FORMATS_short_month_year[inflect].format( - short_month = short_months[month], year = '').rstrip() + if not hasattr(short_months[1], "f"): # not a Lexeme: no inflection + return "{short_month}".format(short_month=short_months[month]) + return ( + self.FORMATS_short_month_year[inflect] + .format(short_month=short_months[month], year="") + .rstrip() + ) def _get_short_weekday(self, date_val): - if (date_val[0] == 0 or date_val[1] == 0 # no day or no month or both - or date_val[1] == 13 # Hebrew has 13 months - or date_val[2] > datetime.MAXYEAR # bug 10815 - or date_val[2] < 0): # B.C.E. date - return '' - w_day = datetime.date(date_val[2], date_val[1], date_val[0]) # y, m, d + if ( + date_val[0] == 0 + or date_val[1] == 0 # no day or no month or both + or date_val[1] == 13 # Hebrew has 13 months + or date_val[2] > datetime.MAXYEAR # bug 10815 + or date_val[2] < 0 + ): # B.C.E. date + return "" + w_day = datetime.date(date_val[2], date_val[1], date_val[0]) # y, m, d return self.short_days[((w_day.weekday() + 1) % 7) + 1] def _get_long_weekday(self, date_val): - if (date_val[0] == 0 or date_val[1] == 0 # no day or no month or both - or date_val[1] == 13 # Hebrew has 13 months - or date_val[2] > datetime.MAXYEAR # bug 10815 - or date_val[2] < 0): # B.C.E. date - return '' - w_day = datetime.date(date_val[2], date_val[1], date_val[0]) # y, m, d + if ( + date_val[0] == 0 + or date_val[1] == 0 # no day or no month or both + or date_val[1] == 13 # Hebrew has 13 months + or date_val[2] > datetime.MAXYEAR # bug 10815 + or date_val[2] < 0 + ): # B.C.E. date + return "" + w_day = datetime.date(date_val[2], date_val[1], date_val[0]) # y, m, d return self.long_days[((w_day.weekday() + 1) % 7) + 1] def _get_localized_year(self, year): - """ Allow a subclass to modify the year, e.g. add a period """ + """Allow a subclass to modify the year, e.g. add a period""" return year def dd_dformat01(self, date_val): @@ -607,30 +628,28 @@ class DateDisplay: if date_val[0] == date_val[1] == 0: return self._get_localized_year(str(date_val[2])) else: - value = self.dhformat.replace('%m', str(date_val[1])) - if '%b' in value or '%B' in value: + value = self.dhformat.replace("%m", str(date_val[1])) + if "%b" in value or "%B" in value: # some locales have %b for the month (ar_EG, is_IS, nb_NO) # so it would be "Jan" but as it's "numeric" make it "1" - value = value.replace('%b', str(date_val[1])) + value = value.replace("%b", str(date_val[1])) # some locales have %B for the month, e.g. ta_IN # so it would be "January" but as it's "numeric" make it 1 - value = value.replace('%B', str(date_val[1])) - if '%a' in value or '%A' in value: + value = value.replace("%B", str(date_val[1])) + if "%a" in value or "%A" in value: # some locales have %a for the abbreviated day, e.g. is_IS - value = value.replace('%a', - self._get_short_weekday(date_val)) + value = value.replace("%a", self._get_short_weekday(date_val)) # some locales have %A for the long/full day, e.g. ta_IN - value = value.replace('%A', - self._get_long_weekday(date_val)) - if date_val[0] == 0: # ignore the zero day and its delimiter - i_day = value.find('%d') - if len(value) == i_day + 2: # delimiter is left of the day - value = value.replace(value[i_day-1:i_day+2], '') - else: # delimiter is to the right of the day - value = value.replace(value[i_day:i_day+3], '') - value = value.replace('%d', str(date_val[0])) - value = value.replace('%Y', str(abs(date_val[2]))) - return value.replace('-', '/') + value = value.replace("%A", self._get_long_weekday(date_val)) + if date_val[0] == 0: # ignore the zero day and its delimiter + i_day = value.find("%d") + if len(value) == i_day + 2: # delimiter is left of the day + value = value.replace(value[i_day - 1 : i_day + 2], "") + else: # delimiter is to the right of the day + value = value.replace(value[i_day : i_day + 3], "") + value = value.replace("%d", str(date_val[0])) + value = value.replace("%Y", str(abs(date_val[2]))) + return value.replace("-", "/") def dd_dformat02(self, date_val, inflect, long_months): """ @@ -645,18 +664,18 @@ class DateDisplay: if date_val[1] == 0: return self._get_localized_year(year) else: - return self.format_long_month_year(date_val[1], year, - inflect, long_months) - elif date_val[1] == 0: # month is zero but day is not (see 8477) + return self.format_long_month_year( + date_val[1], year, inflect, long_months + ) + elif date_val[1] == 0: # month is zero but day is not (see 8477) return self.display_iso(date_val) else: # Translators: this month is ALREADY inflected: ignore it return _("{long_month} {day:d}, {year}").format( - long_month = self.format_long_month(date_val[1], - inflect, - long_months), - day = date_val[0], - year = year) + long_month=self.format_long_month(date_val[1], inflect, long_months), + day=date_val[0], + year=year, + ) def dd_dformat03(self, date_val, inflect, short_months): """ @@ -671,18 +690,18 @@ class DateDisplay: if date_val[1] == 0: return self._get_localized_year(year) else: - return self.format_short_month_year(date_val[1], year, - inflect, short_months) - elif date_val[1] == 0: # month is zero but day is not (see 8477) + return self.format_short_month_year( + date_val[1], year, inflect, short_months + ) + elif date_val[1] == 0: # month is zero but day is not (see 8477) return self.display_iso(date_val) else: # Translators: this month is ALREADY inflected: ignore it return _("{short_month} {day:d}, {year}").format( - short_month = self.format_short_month(date_val[1], - inflect, - short_months), - day = date_val[0], - year = year) + short_month=self.format_short_month(date_val[1], inflect, short_months), + day=date_val[0], + year=year, + ) def dd_dformat04(self, date_val, inflect, long_months): """ @@ -697,18 +716,18 @@ class DateDisplay: if date_val[1] == 0: return self._get_localized_year(year) else: - return self.format_long_month_year(date_val[1], year, - inflect, long_months) - elif date_val[1] == 0: # month is zero but day is not (see 8477) + return self.format_long_month_year( + date_val[1], year, inflect, long_months + ) + elif date_val[1] == 0: # month is zero but day is not (see 8477) return self.display_iso(date_val) else: # Translators: this month is ALREADY inflected: ignore it return _("{day:d} {long_month} {year}").format( - day = date_val[0], - long_month = self.format_long_month(date_val[1], - inflect, - long_months), - year = year) + day=date_val[0], + long_month=self.format_long_month(date_val[1], inflect, long_months), + year=year, + ) def dd_dformat05(self, date_val, inflect, short_months): """ @@ -723,21 +742,20 @@ class DateDisplay: if date_val[1] == 0: return self._get_localized_year(year) else: - return self.format_short_month_year(date_val[1], year, - inflect, short_months) - elif date_val[1] == 0: # month is zero but day is not (see 8477) + return self.format_short_month_year( + date_val[1], year, inflect, short_months + ) + elif date_val[1] == 0: # month is zero but day is not (see 8477) return self.display_iso(date_val) else: # Translators: this month is ALREADY inflected: ignore it return _("{day:d} {short_month} {year}").format( - day = date_val[0], - short_month = self.format_short_month(date_val[1], - inflect, - short_months), - year = year) + day=date_val[0], + short_month=self.format_short_month(date_val[1], inflect, short_months), + year=year, + ) - def _display_calendar(self, date_val, long_months, short_months = None, - inflect=""): + def _display_calendar(self, date_val, long_months, short_months=None, inflect=""): """ this must agree with DateDisplayEn's "formats" definition (it may be overridden if a locale-specific date displayer exists) @@ -772,7 +790,6 @@ class DateDisplay: else: return value - def _display_french(self, date_val, **kwargs): return self._display_calendar(date_val, self.french, **kwargs) @@ -785,14 +802,18 @@ class DateDisplay: def _display_islamic(self, date_val, **kwargs): return self._display_calendar(date_val, self.islamic, **kwargs) + class DateDisplayEn(DateDisplay): """ English language date display class. """ + display = DateDisplay.display_formatted + class DateDisplayGB(DateDisplay): """ British-English language date display class (its format is different). """ + display = DateDisplay.display_formatted diff --git a/gramps/gen/datehandler/_dateparser.py b/gramps/gen/datehandler/_dateparser.py index d07c6a877..93b39b8f8 100644 --- a/gramps/gen/datehandler/_dateparser.py +++ b/gramps/gen/datehandler/_dateparser.py @@ -26,42 +26,44 @@ Date parsing class. Serves as the base class for any localized date parsing class. The default base class provides parsing for English. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re import calendar -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # set up logging # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import logging + log = logging.getLogger(".DateParser") -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ..lib.date import Date, DateError, Today from ..const import GRAMPS_LOCALE as glocale from ..utils.grampslocale import GrampsLocale from ._datestrings import DateStrings -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Top-level module functions # -#------------------------------------------------------------------------- -_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 ] +# ------------------------------------------------------------------------- +_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): - """ Checks if date_tuple is a valid date in Gregorian Calendar """ + """Checks if date_tuple is a valid date in Gregorian Calendar""" day = date_tuple[0] month = date_tuple[1] valid = True @@ -69,16 +71,17 @@ def gregorian_valid(date_tuple): if month > 12: valid = False elif calendar.isleap(date_tuple[2]): - if day > _leap_days[month-1]: + if day > _leap_days[month - 1]: valid = False - elif day > _max_days[month-1]: + elif day > _max_days[month - 1]: valid = False except: valid = False return valid + def julian_valid(date_tuple): - """ Checks if date_tuple is a valid date in Julian Calendar """ + """Checks if date_tuple is a valid date in Julian Calendar""" day = date_tuple[0] month = date_tuple[1] valid = True @@ -87,20 +90,21 @@ def julian_valid(date_tuple): valid = False elif (date_tuple[2]) % 4 == 0: # julian always have leapyear every 4 year - if day > _leap_days[month-1]: + if day > _leap_days[month - 1]: valid = False - elif day > _max_days[month-1]: + elif day > _max_days[month - 1]: valid = False except: valid = False return valid + def swedish_valid(date_tuple): - """ Checks if date_tuple is a valid date in Swedish Calendar """ + """Checks if date_tuple is a valid date in Swedish Calendar""" valid_J = julian_valid(date_tuple) date_tuple = (date_tuple[2], date_tuple[1], date_tuple[0]) # Swedish calendar starts as Julian 1700-03-01 and ends 1712-03-01 as Julian - if date_tuple >= (1700, 2, 29) and date_tuple < (1712, 3, 1): + if date_tuple >= (1700, 2, 29) and date_tuple < (1712, 3, 1): if date_tuple == (1712, 2, 30): # extra day was inserted 1712, not valid Julian return True if valid_J: @@ -112,26 +116,28 @@ def swedish_valid(date_tuple): else: return False + def french_valid(date_tuple): - """ Checks if date_tuple is a valid date in French Calendar """ + """Checks if date_tuple is a valid date in French Calendar""" valid = True # year 1 starts on 22.9.1792 if date_tuple[2] < 1: valid = False return valid + def _build_prefix_table(month_to_int, month_variants): """ Populate a DateParser.month_to_int-like dict with all the prefixes found in month_variants. """ - month_variants = list(month_variants) # drain the generator, if any + month_variants = list(month_variants) # drain the generator, if any month_to_int_new = {} # Populate with full names first, w/o prefixes log.debug("Mapping full names...") - for i in range(0,len(month_variants)): + for i in range(0, len(month_variants)): for month in month_variants[i]: m = month.lower() log.debug("Mapping {} -> {}".format(m, i)) @@ -142,7 +148,7 @@ def _build_prefix_table(month_to_int, month_variants): months_sorted = list(month_to_int_new.keys()) months_sorted.sort(key=len, reverse=True) for m in months_sorted: - for prefixlen in reversed(range(1,len(m))): + for prefixlen in reversed(range(1, len(m))): mp = m[:prefixlen] if mp.strip() != mp: continue @@ -153,6 +159,7 @@ def _build_prefix_table(month_to_int, month_variants): log.debug("Mapping {} -> {}".format(mp, i)) month_to_int[mp] = i + def _generate_variants(months): """ Generate all month variants for passing to _build_prefix_table @@ -179,15 +186,16 @@ def _generate_variants(months): # plain string, not a lexeme with inflections... # Maybe a '|'-separated list of alternatives, maybe empty, # maybe a single string. Suppress empty strings! - mv = (s for s in m.split('|') if s) + mv = (s for s in m.split("|") if s) v.extend(mv) - yield(list(set(v))) + yield (list(set(v))) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # DateParser class # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateParser: """ Convert a text string into a :class:`.Date` object. If the date cannot be @@ -197,12 +205,21 @@ class DateParser: _dhformat_parse = re.compile(r".*%(\S).*%(\S).*%(\S).*") # RFC-2822 only uses capitalized English abbreviated names, no locales. - _rfc_days = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat') + _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, + } # seeded with __init_prefix_tables swedish_to_int = month_to_int = {} @@ -214,99 +231,150 @@ class DateParser: # modifiers before the date # (overridden if a locale-specific date parser exists) modifier_to_int = { - 'before' : Date.MOD_BEFORE, 'bef' : Date.MOD_BEFORE, - 'bef.' : Date.MOD_BEFORE, 'after' : Date.MOD_AFTER, - 'aft' : Date.MOD_AFTER, 'aft.' : Date.MOD_AFTER, - 'about' : Date.MOD_ABOUT, 'abt.' : Date.MOD_ABOUT, - 'abt' : Date.MOD_ABOUT, 'circa' : Date.MOD_ABOUT, - 'c.' : Date.MOD_ABOUT, 'around' : Date.MOD_ABOUT, - } + "before": Date.MOD_BEFORE, + "bef": Date.MOD_BEFORE, + "bef.": Date.MOD_BEFORE, + "after": Date.MOD_AFTER, + "aft": Date.MOD_AFTER, + "aft.": Date.MOD_AFTER, + "about": Date.MOD_ABOUT, + "abt.": Date.MOD_ABOUT, + "abt": Date.MOD_ABOUT, + "circa": Date.MOD_ABOUT, + "c.": Date.MOD_ABOUT, + "around": Date.MOD_ABOUT, + "from": Date.MOD_FROM, + "to": Date.MOD_TO, + } # in some languages some of above listed modifiers are after the date, # in that case the subclass should put them into this dictionary instead modifier_after_to_int = {} hebrew_to_int = { - "tishri" : 1, "heshvan" : 2, "kislev" : 3, - "tevet" : 4, "shevat" : 5, "adari" : 6, - "adarii" : 7, "nisan" : 8, "iyyar" : 9, - "sivan" : 10, "tammuz" : 11, "av" : 12, - "elul" : 13, - #alternative spelling - "cheshvan": 2, "adar sheni": 7, "iyar" : 9, - #GEDCOM months - "tsh" : 1, "csh": 5, "ksl": 3, "tvt": 4, "shv": 5, "adr": 6, - "ads" : 7, "nsn": 8, "iyr": 9, "svn":10, "tmz":11, "aav":12, - "ell":13, - } + "tishri": 1, + "heshvan": 2, + "kislev": 3, + "tevet": 4, + "shevat": 5, + "adari": 6, + "adarii": 7, + "nisan": 8, + "iyyar": 9, + "sivan": 10, + "tammuz": 11, + "av": 12, + "elul": 13, + # alternative spelling + "cheshvan": 2, + "adar sheni": 7, + "iyar": 9, + # GEDCOM months + "tsh": 1, + "csh": 5, + "ksl": 3, + "tvt": 4, + "shv": 5, + "adr": 6, + "ads": 7, + "nsn": 8, + "iyr": 9, + "svn": 10, + "tmz": 11, + "aav": 12, + "ell": 13, + } french_to_int = { -# the long ones are seeded with __init_prefix_tables - #GEDCOM months - 'vend' : 1, 'brum' : 2, - 'frim' : 3, 'nivo' : 4, - 'pluv' : 5, 'vent' : 6, - 'germ' : 7, 'flor' : 8, - 'prai' : 9, 'mess' : 10, - 'ther' : 11, 'fruc' : 12, - 'comp' : 13, - } + # the long ones are seeded with __init_prefix_tables + # GEDCOM months + "vend": 1, + "brum": 2, + "frim": 3, + "nivo": 4, + "pluv": 5, + "vent": 6, + "germ": 7, + "flor": 8, + "prai": 9, + "mess": 10, + "ther": 11, + "fruc": 12, + "comp": 13, + } islamic_to_int = { -# some are already seeded with __init_prefix_tables, -# but it is a pain to separate them out from the variants... - "muharram" : 1, "muharram ul haram" : 1, - "safar" : 2, "rabi`al-awwal" : 3, - "rabi'l" : 3, "rabi`ul-akhir" : 4, - "rabi`ath-thani" : 4, "rabi` ath-thani" : 4, - "rabi`al-thaany" : 4, "rabi` al-thaany" : 4, - "rabi' ii" : 4, "jumada l-ula" : 5, - "jumaada-ul-awwal" : 5, "jumaada i" : 5, - "jumada t-tania" : 6, "jumaada-ul-akhir" : 6, - "jumaada al-thaany" : 6, "jumaada ii" : 5, - "rajab" : 7, "sha`ban" : 8, - "sha`aban" : 8, "ramadan" : 9, - "ramadhan" : 9, "shawwal" : 10, - "dhu l-qa`da" : 11, "dhu qadah" : 11, - "thw al-qi`dah" : 11, "dhu l-hijja" : 12, - "dhu hijja" : 12, "thw al-hijjah" : 12, - } + # some are already seeded with __init_prefix_tables, + # but it is a pain to separate them out from the variants... + "muharram": 1, + "muharram ul haram": 1, + "safar": 2, + "rabi`al-awwal": 3, + "rabi'l": 3, + "rabi`ul-akhir": 4, + "rabi`ath-thani": 4, + "rabi` ath-thani": 4, + "rabi`al-thaany": 4, + "rabi` al-thaany": 4, + "rabi' ii": 4, + "jumada l-ula": 5, + "jumaada-ul-awwal": 5, + "jumaada i": 5, + "jumada t-tania": 6, + "jumaada-ul-akhir": 6, + "jumaada al-thaany": 6, + "jumaada ii": 5, + "rajab": 7, + "sha`ban": 8, + "sha`aban": 8, + "ramadan": 9, + "ramadhan": 9, + "shawwal": 10, + "dhu l-qa`da": 11, + "dhu qadah": 11, + "thw al-qi`dah": 11, + "dhu l-hijja": 12, + "dhu hijja": 12, + "thw al-hijjah": 12, + } # seeded with __init_prefix_tables - persian_to_int = { } + persian_to_int = {} - bce = ["B.C.E.", "B.C.E", "BCE", "B.C.", "B.C", "BC" ] + bce = ["B.C.E.", "B.C.E", "BCE", "B.C.", "B.C", "BC"] # (overridden if a locale-specific date parser exists) # seeded with __init_prefix_tables - calendar_to_int = { - } - # (probably overridden if a locale-specific date parser exists) + calendar_to_int = {} + # (probably overridden if a locale-specific date parser exists) newyear_to_int = { - "jan1": Date.NEWYEAR_JAN1, - "mar1": Date.NEWYEAR_MAR1, + "jan1": Date.NEWYEAR_JAN1, + "mar1": Date.NEWYEAR_MAR1, "mar25": Date.NEWYEAR_MAR25, - "sep1" : Date.NEWYEAR_SEP1, - } + "sep1": Date.NEWYEAR_SEP1, + } quality_to_int = { - 'estimated' : Date.QUAL_ESTIMATED, - 'est.' : Date.QUAL_ESTIMATED, - 'est' : Date.QUAL_ESTIMATED, - 'calc.' : Date.QUAL_CALCULATED, - 'calc' : Date.QUAL_CALCULATED, - 'calculated' : Date.QUAL_CALCULATED, - } - # (overridden if a locale-specific date parser exists) + "estimated": Date.QUAL_ESTIMATED, + "est.": Date.QUAL_ESTIMATED, + "est": Date.QUAL_ESTIMATED, + "calc.": Date.QUAL_CALCULATED, + "calc": Date.QUAL_CALCULATED, + "calculated": Date.QUAL_CALCULATED, + } + # (overridden if a locale-specific date parser exists) - today = ["$T",] - # Override with a list of *synonyms* for "today" in your language. - # Note: the word "today" itself will already be pulled in from your translation DB, - # see init_strings, so there is no need to override this if you have no aliases - # for "today". - # We also secretly support "$T" like in some reports. + today = [ + "$T", + ] + # Override with a list of *synonyms* for "today" in your language. + # Note: the word "today" itself will already be pulled in from your translation DB, + # see init_strings, so there is no need to override this if you have no aliases + # for "today". + # We also secretly support "$T" like in some reports. _langs = set() + def __init_prefix_tables(self): ds = self._ds = DateStrings(self._locale) lang = self._locale.lang @@ -316,56 +384,69 @@ class DateParser: else: DateParser._langs.add(lang) log.debug("Begin building parser prefix tables for {}".format(lang)) - _build_prefix_table(DateParser.month_to_int, + _build_prefix_table( + DateParser.month_to_int, _generate_variants( - zip(ds.long_months, ds.short_months, - ds.swedish_SV, ds.alt_long_months))) - _build_prefix_table(DateParser.hebrew_to_int, - _generate_variants(zip(ds.hebrew))) - _build_prefix_table(DateParser.french_to_int, - _generate_variants(zip(ds.french))) - _build_prefix_table(DateParser.islamic_to_int, - _generate_variants(zip(ds.islamic))) - _build_prefix_table(DateParser.persian_to_int, - _generate_variants(zip(ds.persian))) - _build_prefix_table(DateParser.calendar_to_int, - _generate_variants(zip(ds.calendar))) + zip(ds.long_months, ds.short_months, ds.swedish_SV, ds.alt_long_months) + ), + ) + _build_prefix_table( + DateParser.hebrew_to_int, _generate_variants(zip(ds.hebrew)) + ) + _build_prefix_table( + DateParser.french_to_int, _generate_variants(zip(ds.french)) + ) + _build_prefix_table( + DateParser.islamic_to_int, _generate_variants(zip(ds.islamic)) + ) + _build_prefix_table( + DateParser.persian_to_int, _generate_variants(zip(ds.persian)) + ) + _build_prefix_table( + DateParser.calendar_to_int, _generate_variants(zip(ds.calendar)) + ) def __init__(self, plocale=None): """ :param plocale: allow correct date format to be loaded and parsed :type plocale: a :class:`.GrampsLocale` instance """ - from ._datehandler import locale_tformat # circular import if above + from ._datehandler import locale_tformat # circular import if above + if plocale: self._locale = plocale - elif not hasattr(self, '_locale'): + elif not hasattr(self, "_locale"): self._locale = glocale if self._locale.calendar in locale_tformat: - self.dhformat = locale_tformat[self._locale.calendar] # date format + self.dhformat = locale_tformat[self._locale.calendar] # date format else: - self.dhformat = locale_tformat['en_GB'] # something is required - self.dhformat_changed() # Allow overriding so a subclass can modify it + self.dhformat = locale_tformat["en_GB"] # something is required + self.dhformat_changed() # Allow overriding so a subclass can modify it self.init_strings() self.parser = { - Date.CAL_GREGORIAN : self._parse_gregorian, - Date.CAL_JULIAN : self._parse_julian, - Date.CAL_FRENCH : self._parse_french, - Date.CAL_PERSIAN : self._parse_persian, - Date.CAL_HEBREW : self._parse_hebrew, - Date.CAL_ISLAMIC : self._parse_islamic, - Date.CAL_SWEDISH : self._parse_swedish, - } + Date.CAL_GREGORIAN: self._parse_gregorian, + Date.CAL_JULIAN: self._parse_julian, + Date.CAL_FRENCH: self._parse_french, + Date.CAL_PERSIAN: self._parse_persian, + Date.CAL_HEBREW: self._parse_hebrew, + Date.CAL_ISLAMIC: self._parse_islamic, + Date.CAL_SWEDISH: self._parse_swedish, + } match = self._dhformat_parse.match(self.dhformat.lower()) if match: - self._ddmy = match.groups() == ('a', 'e', 'b', 'y') # Icelandic - self.dmy = (match.groups() == ('d', 'm', 'y') or - match.groups() == ('e', 'm', 'y') or # Bulgarian - match.groups() == ('d', 'b', 'y') or - match.groups() == ('a', 'e', 'b', 'y')) - self.ymd = (match.groups() == ('y', 'm', 'd') or \ - match.groups() == ('y', 'b', 'd')) + self._ddmy = match.groups() == ("a", "e", "b", "y") # Icelandic + self.dmy = ( + match.groups() == ("d", "m", "y") + or match.groups() == ("e", "m", "y") + or match.groups() == ("d", "b", "y") # Bulgarian + or match.groups() == ("a", "e", "b", "y") + ) + self.ymd = match.groups() == ("y", "m", "d") or match.groups() == ( + "y", + "b", + "d", + ) # note ('m','d','y') is valid -- in which case both will be False else: self.dmy = True @@ -373,7 +454,7 @@ class DateParser: self._ddmy = False def dhformat_changed(self): - """ Allow overriding so a subclass can modify it """ + """Allow overriding so a subclass can modify it""" pass def re_longest_first(self, keys): @@ -383,7 +464,7 @@ class DateParser: are quoted. """ keys.sort(key=len, reverse=True) - return '(' + '|'.join([re.escape(key) for key in keys]) + ')' + return "(" + "|".join([re.escape(key) for key in keys]) + ")" def init_strings(self): """ @@ -401,14 +482,15 @@ class DateParser: _ = self._locale.translation.gettext self.__init_prefix_tables() - self._rfc_mon_str = '(' + '|'.join(list(self._rfc_mons_to_int.keys())) + ')' - self._rfc_day_str = '(' + '|'.join(self._rfc_days) + ')' + self._rfc_mon_str = "(" + "|".join(list(self._rfc_mons_to_int.keys())) + ")" + self._rfc_day_str = "(" + "|".join(self._rfc_days) + ")" self._bce_str = self.re_longest_first(self.bce) self._qual_str = self.re_longest_first(list(self.quality_to_int.keys())) self._mod_str = self.re_longest_first(list(self.modifier_to_int.keys())) self._mod_after_str = self.re_longest_first( - list(self.modifier_after_to_int.keys())) + list(self.modifier_after_to_int.keys()) + ) self._mon_str = self.re_longest_first(list(self.month_to_int.keys())) self._jmon_str = self.re_longest_first(list(self.hebrew_to_int.keys())) @@ -419,43 +501,48 @@ class DateParser: self._cal_str = self.re_longest_first(list(self.calendar_to_int.keys())) self._ny_str = self.re_longest_first(list(self.newyear_to_int.keys())) - self._today_str = self.re_longest_first(self.today + [_("today"),]) + self._today_str = self.re_longest_first( + self.today + + [ + _("today"), + ] + ) # bce, calendar type and quality may be either at the end or at # the beginning of the given date string, therefore they will # be parsed from the middle and will be in match.group(2). self._bce_re = re.compile(r"(.*)\s+%s( ?.*)" % self._bce_str) - self._cal = re.compile(r"(.*)\s+\(%s\)( ?.*)" % self._cal_str, - re.IGNORECASE) - self._calny = re.compile(r"(.*)\s+\(%s,\s*%s\)( ?.*)" % - (self._cal_str, self._ny_str), re.IGNORECASE) + self._cal = re.compile(r"(.*)\s+\(%s\)( ?.*)" % self._cal_str, re.IGNORECASE) + self._calny = re.compile( + r"(.*)\s+\(%s,\s*%s\)( ?.*)" % (self._cal_str, self._ny_str), re.IGNORECASE + ) self._calny_iso = re.compile( - r"(.*)\s+\(%s,\s*(\d{1,2}-\d{1,2})\)( ?.*)" % self._cal_str, - re.IGNORECASE) + r"(.*)\s+\(%s,\s*(\d{1,2}-\d{1,2})\)( ?.*)" % self._cal_str, re.IGNORECASE + ) - self._ny = re.compile(r"(.*)\s+\(%s\)( ?.*)" % self._ny_str, - re.IGNORECASE) + self._ny = re.compile(r"(.*)\s+\(%s\)( ?.*)" % self._ny_str, re.IGNORECASE) self._ny_iso = re.compile(r"(.*)\s+\((\d{1,2}-\d{1,2})\)( ?.*)") - self._qual = re.compile(r"(.* ?)%s\s+(.+)" % self._qual_str, - re.IGNORECASE) + self._qual = re.compile(r"(.* ?)%s\s+(.+)" % self._qual_str, re.IGNORECASE) - self._span = re.compile(r"(from)\s+(?P.+)\s+to\s+(?P.+)", - re.IGNORECASE) + self._span = re.compile( + r"(from)\s+(?P.+)\s+to\s+(?P.+)", re.IGNORECASE + ) self._range = re.compile( - r"(bet|bet.|between)\s+(?P.+)\s+and\s+(?P.+)", - re.IGNORECASE) + r"(bet|bet.|between)\s+(?P.+)\s+and\s+(?P.+)", re.IGNORECASE + ) self._quarter = re.compile( - r"[qQ](?P[1-4])\s+(?P.+)", - re.IGNORECASE) - self._modifier = re.compile(r'%s\s+(.*)' % self._mod_str, - re.IGNORECASE) - self._modifier_after = re.compile(r'(.*)\s+%s' % self._mod_after_str, - re.IGNORECASE) - self._abt2 = re.compile('<(.*)>', re.IGNORECASE) - self._text = re.compile(r'%s\.?(\s+\d+)?\s*,?\s+((\d+)(/\d+)?)?\s*$' - % self._mon_str, re.IGNORECASE) + r"[qQ](?P[1-4])\s+(?P.+)", re.IGNORECASE + ) + self._modifier = re.compile(r"%s\s+(.*)" % self._mod_str, re.IGNORECASE) + self._modifier_after = re.compile( + r"(.*)\s+%s" % self._mod_after_str, re.IGNORECASE + ) + self._abt2 = re.compile("<(.*)>", re.IGNORECASE) + self._text = re.compile( + r"%s\.?(\s+\d+)?\s*,?\s+((\d+)(/\d+)?)?\s*$" % self._mon_str, re.IGNORECASE + ) # this next RE has the (possibly-slashed) year at the string's end self._text2 = re.compile(r'(\d+)?\s+?%s\.?\s*((\d+)(/\d+)?)?\s*$' % self._mon_str, re.IGNORECASE) @@ -484,12 +571,13 @@ class DateParser: self._iso = re.compile(r"(\d+)(/(\d+))?-(\d+)(-(\d+))?\s*$") self._isotimestamp = re.compile( r"^\s*?(\d{4})([01]\d)([0123]\d)(?:(?:[012]\d[0-5]\d[0-5]\d)|" - r"(?:\s+[012]\d:[0-5]\d(?::[0-5]\d)?))?\s*?$") + r"(?:\s+[012]\d:[0-5]\d(?::[0-5]\d)?))?\s*?$" + ) self._rfc = re.compile( r"(%s,)?\s+(\d|\d\d)\s+%s\s+(\d+)\s+\d\d:\d\d(:\d\d)?\s+" - r"(\+|-)\d\d\d\d" % (self._rfc_day_str, self._rfc_mon_str)) - self._today = re.compile(r"^\s*%s\s*$" % self._today_str, - re.IGNORECASE) + r"(\+|-)\d\d\d\d" % (self._rfc_day_str, self._rfc_mon_str) + ) + self._today = re.compile(r"^\s*%s\s*$" % self._today_str, re.IGNORECASE) def _get_int(self, val): """ @@ -502,37 +590,41 @@ class DateParser: return int(val) def _parse_hebrew(self, text): - return self._parse_calendar(text, self._jtext, self._jtext2, - self.hebrew_to_int) + return self._parse_calendar(text, self._jtext, self._jtext2, self.hebrew_to_int) def _parse_islamic(self, text): - return self._parse_calendar(text, self._itext, self._itext2, - self.islamic_to_int) + return self._parse_calendar( + text, self._itext, self._itext2, self.islamic_to_int + ) def _parse_persian(self, text): - return self._parse_calendar(text, self._ptext, self._ptext2, - self.persian_to_int) + return self._parse_calendar( + text, self._ptext, self._ptext2, self.persian_to_int + ) def _parse_french(self, text): - return self._parse_calendar(text, self._ftext, self._ftext2, - self.french_to_int, french_valid) + return self._parse_calendar( + text, self._ftext, self._ftext2, self.french_to_int, french_valid + ) def _parse_gregorian(self, text): - return self._parse_calendar(text, self._text, self._text2, - self.month_to_int, gregorian_valid) + return self._parse_calendar( + text, self._text, self._text2, self.month_to_int, gregorian_valid + ) def _parse_julian(self, text): - return self._parse_calendar(text, self._text, self._text2, - self.month_to_int, julian_valid) + return self._parse_calendar( + text, self._text, self._text2, self.month_to_int, julian_valid + ) def _parse_swedish(self, text): - return self._parse_calendar(text, self._stext, self._stext2, - self.swedish_to_int,swedish_valid) - + return self._parse_calendar( + text, self._stext, self._stext2, self.swedish_to_int, swedish_valid + ) def _parse_calendar(self, text, regex1, regex2, mmap, check=None): match = regex1.match(text.lower()) - if match: # user typed in 'month-name day year' or 'month-name year' + if match: # user typed in 'month-name day year' or 'month-name year' groups = match.groups() if groups[0] is None: m = 0 @@ -546,20 +638,20 @@ class DateParser: else: d = self._get_int(groups[1]) if groups[4] is not None: - y = int(groups[3]) + 1 # fullyear + 1 - s = True # slash year - else: # regular year + y = int(groups[3]) + 1 # fullyear + 1 + s = True # slash year + else: # regular year y = int(groups[3]) s = False value = (d, m, y, s) - if s and julian_valid(value): # slash year + if s and julian_valid(value): # slash year pass elif check and not check((d, m, y)): value = Date.EMPTY return value match = regex2.match(text.lower()) - if match: # user typed in day month-name year or year month-name day + if match: # user typed in day month-name year or year month-name day groups = match.groups() if self.ymd: if groups[3] is None: @@ -572,9 +664,9 @@ class DateParser: s = False else: if groups[2] is not None: - y = int(groups[1]) + 1 # fullyear + 1 - s = True # slash year - else: # regular year + y = int(groups[1]) + 1 # fullyear + 1 + s = True # slash year + else: # regular year y = int(groups[1]) s = False else: @@ -588,9 +680,9 @@ class DateParser: s = False else: if groups[4] is not None: - y = int(groups[3]) + 1 # fullyear + 1 - s = True # slash year - else: # regular year + y = int(groups[3]) + 1 # fullyear + 1 + s = True # slash year + else: # regular year y = int(groups[3]) s = False value = (d, m, y, s) @@ -632,7 +724,7 @@ class DateParser: m = self._get_int(groups[3]) d = self._get_int(groups[5]) if groups[2] and julian_valid((d, m, y + 1)): - return (d, m, y + 1, True) # slash year + return (d, m, y + 1, True) # slash year if check is None or check((d, m, y)): return (d, m, y, False) return Date.EMPTY @@ -666,8 +758,8 @@ class DateParser: groups = match.groups() if groups == (None, None, None, None, None): return Date.EMPTY - if self._ddmy: # Icelandic - groups = groups[1:] # ignore the day of the week at the start + if self._ddmy: # Icelandic + groups = groups[1:] # ignore the day of the week at the start if self.ymd: # '1789' and ymd: incomplete date if groups[1] is None: @@ -682,7 +774,7 @@ class DateParser: y = self._get_int(groups[1]) m = self._get_int(groups[3]) d = self._get_int(groups[4]) - if m > 12: # maybe a slash year, not a month (1722/3 is March) + if m > 12: # maybe a slash year, not a month (1722/3 is March) if y % 100 == 99: modyear = (y + 1) % 1000 elif y % 10 == 9: @@ -690,7 +782,7 @@ class DateParser: else: modyear = (y + 1) % 10 if m == modyear: - return (0, 0, y + 1, True) # slash year + return (0, 0, y + 1, True) # slash year else: y = self._get_int(groups[4]) if self.dmy: @@ -703,7 +795,7 @@ class DateParser: else: m = self._get_int(groups[1]) d = self._get_int(groups[3]) - if m > 12: # maybe a slash year, not a month + if m > 12: # maybe a slash year, not a month if m % 100 == 99: modyear = (m + 1) % 1000 elif m % 10 == 9: @@ -711,7 +803,7 @@ class DateParser: else: modyear = (m + 1) % 10 if y == modyear: - return (0, 0, m + 1, True) # slash year + return (0, 0, m + 1, True) # slash year value = (d, m, y, False) if check and not check((d, m, y)): value = Date.EMPTY @@ -795,14 +887,14 @@ class DateParser: match = self._span.match(text) if match: text_parser = self.parser[cal] - (text1, bc1) = self.match_bce(match.group('start')) + (text1, bc1) = self.match_bce(match.group("start")) start = self._parse_subdate(text1, text_parser, cal) if start == Date.EMPTY and text1 != "": return 0 if bc1: start = self.invert_year(start) - (text2, bc2) = self.match_bce(match.group('stop')) + (text2, bc2) = self.match_bce(match.group("stop")) stop = self._parse_subdate(text2, text_parser, cal) if stop == Date.EMPTY and text2 != "": return 0 @@ -822,14 +914,14 @@ class DateParser: match = self._range.match(text) if match: text_parser = self.parser[cal] - (text1, bc1) = self.match_bce(match.group('start')) + (text1, bc1) = self.match_bce(match.group("start")) start = self._parse_subdate(text1, text_parser, cal) if start == Date.EMPTY and text1 != "": return 0 if bc1: start = self.invert_year(start) - (text2, bc2) = self.match_bce(match.group('stop')) + (text2, bc2) = self.match_bce(match.group("stop")) stop = self._parse_subdate(text2, text_parser, cal) if stop == Date.EMPTY and text2 != "": return 0 @@ -848,20 +940,33 @@ class DateParser: """ match = self._quarter.match(text) if match: - quarter = self._get_int(match.group('quarter')) + quarter = self._get_int(match.group("quarter")) text_parser = self.parser[cal] - (text, bc) = self.match_bce(match.group('year')) + (text, bc) = self.match_bce(match.group("year")) start = self._parse_subdate(text, text_parser, cal) - if (start == Date.EMPTY and text != "") or (start[0] != 0) or (start[1] != 0): # reject dates where the day or month have been set + if ( + (start == Date.EMPTY and text != "") + or (start[0] != 0) + or (start[1] != 0) + ): # reject dates where the day or month have been set return 0 if bc: start = self.invert_year(start) stop_month = quarter * 3 - stop_day = _max_days[stop_month - 1] # no need to worry about leap years since no quarter ends in February + stop_day = _max_days[ + stop_month - 1 + ] # no need to worry about leap years since no quarter ends in February - date.set(qual, Date.MOD_RANGE, cal, (1, stop_month - 2, start[2], start[3]) + (stop_day, stop_month, start[2], start[3]), newyear=ny) + date.set( + qual, + Date.MOD_RANGE, + cal, + (1, stop_month - 2, start[2], start[3]) + + (stop_day, stop_month, start[2], start[3]), + newyear=ny, + ) return 1 return 0 @@ -874,7 +979,7 @@ class DateParser: match = self._bce_re.match(text) bc = False if match: - # bce is in the match.group(2) + # bce is in the match.group(2) try: text = match.group(1) + match.group(3) except: @@ -908,8 +1013,7 @@ class DateParser: if match: grps = match.groups() start = self._parse_subdate(grps[0], self.parser[cal], cal) - mod = self.modifier_after_to_int.get(grps[1].lower(), - Date.MOD_NONE) + mod = self.modifier_after_to_int.get(grps[1].lower(), Date.MOD_NONE) if start == Date.EMPTY: date.set_modifier(Date.MOD_TEXTONLY) date.set_text_value(text) @@ -937,7 +1041,7 @@ class DateParser: """ Parses the text and sets the date according to the parsing. """ - text = text.strip() # otherwise spaces can make it a bad date + text = text.strip() # otherwise spaces can make it a bad date date.set_text_value(text) qual = Date.QUAL_NONE cal = Date.CAL_GREGORIAN @@ -969,7 +1073,9 @@ class DateParser: return if bc: - date.set(qual, Date.MOD_NONE, cal, self.invert_year(subdate), newyear=newyear) + date.set( + qual, Date.MOD_NONE, cal, self.invert_year(subdate), newyear=newyear + ) else: date.set(qual, Date.MOD_NONE, cal, subdate, newyear=newyear) diff --git a/gramps/gen/datehandler/_datestrings.py b/gramps/gen/datehandler/_datestrings.py index 86dcfa37c..930f511da 100644 --- a/gramps/gen/datehandler/_datestrings.py +++ b/gramps/gen/datehandler/_datestrings.py @@ -38,19 +38,20 @@ strings as needed. Then remove the strings from your language's :class:`DateParserXX` and :class:`DateHandlerXX` classes. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # set up logging # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import logging + log = logging.getLogger(".DateStrings") -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # DateStrings # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateStrings: """ String tables for :class:`.DateDisplay` and :class:`.DateParser`. @@ -61,17 +62,26 @@ class DateStrings: # Display of these months uses the regular long_months. # TODO should we pack these into alt_long_months instead? swedish_SV = ( - "", "Januari", "Februari", "Mars", - "April", "Maj", "Juni", - "Juli", "Augusti", "September", - "Oktober", "November", "December" - ) - + "", + "Januari", + "Februari", + "Mars", + "April", + "Maj", + "Juni", + "Juli", + "Augusti", + "September", + "Oktober", + "November", + "December", + ) def __init__(self, locale): _ = locale.translation.lexgettext - self.long_months = ( "", + self.long_months = ( + "", # Translators: see # http://gramps-project.org/wiki/index.php?title=Translating_Gramps#Translating_dates # to learn how to select proper inflection to be used in your localized @@ -89,7 +99,8 @@ class DateStrings: _("November", "localized lexeme inflections"), _("December", "localized lexeme inflections") ) - self.short_months = ( "", + self.short_months = ( + "", # Translators: see # http://gramps-project.org/wiki/index.php?title=Translating_Gramps#Translating_dates # to learn how to select proper inflection to be used in your localized @@ -108,7 +119,8 @@ class DateStrings: _("Dec", "localized lexeme inflections - short month form") ) _ = locale.translation.sgettext - self.alt_long_months = ( "", + self.alt_long_months = ( + "", # Translators: see # http://gramps-project.org/wiki/index.php?title=Translating_Gramps#Translating_dates # to learn how to add proper alternatives to be recognized in your localized @@ -127,14 +139,15 @@ class DateStrings: _("", "alternative month names for December") ) self.calendar = ( -# Must appear in the order indexed by Date.CAL_... numeric constants - _("Gregorian", "calendar"), - _("Julian", "calendar"), - _("Hebrew", "calendar"), - _("French Republican", "calendar"), - _("Persian", "calendar"), - _("Islamic", "calendar"), - _("Swedish", "calendar") ) + # Must appear in the order indexed by Date.CAL_... numeric constants + _("Gregorian", "calendar"), + _("Julian", "calendar"), + _("Hebrew", "calendar"), + _("French Republican", "calendar"), + _("Persian", "calendar"), + _("Islamic", "calendar"), + _("Swedish", "calendar"), + ) _ = locale.translation.lexgettext self.hebrew = ( @@ -155,8 +168,8 @@ class DateStrings: _("Sivan", "Hebrew month lexeme"), _("Tammuz", "Hebrew month lexeme"), _("Av", "Hebrew month lexeme"), - _("Elul", "Hebrew month lexeme") - ) + _("Elul", "Hebrew month lexeme"), + ) self.french = ( "", @@ -177,7 +190,7 @@ class DateStrings: _("Thermidor", "French month lexeme"), _("Fructidor", "French month lexeme"), _("Extra", "French month lexeme"), - ) + ) self.islamic = ( "", @@ -197,7 +210,7 @@ class DateStrings: _("Shawwal", "Islamic month lexeme"), _("Dhu l-Qa`da", "Islamic month lexeme"), _("Dhu l-Hijja", "Islamic month lexeme"), - ) + ) self.persian = ( "", @@ -217,76 +230,98 @@ class DateStrings: _("Dey", "Persian month lexeme"), _("Bahman", "Persian month lexeme"), _("Esfand", "Persian month lexeme"), - ) + ) - self.modifiers = ("", - # Translators: if the modifier is after the date - # put the space ahead of the word instead of after it - _("before ", "date modifier"), - # Translators: if the modifier is after the date - # put the space ahead of the word instead of after it - _("after ", "date modifier"), - # Translators: if the modifier is after the date - # put the space ahead of the word instead of after it - _("about ", "date modifier"), - "", "", "") + self.modifiers = ( + "", + # Translators: if the modifier is after the date + # put the space ahead of the word instead of after it + _("before ", "date modifier"), + # Translators: if the modifier is after the date + # put the space ahead of the word instead of after it + _("after ", "date modifier"), + # Translators: if the modifier is after the date + # put the space ahead of the word instead of after it + _("about ", "date modifier"), + "", + "", + "", + # Translators: if the modifier is after the date + # put the space ahead of the word instead of after it + _("from ", "date modifier"), + # Translators: if the modifier is after the date + # put the space ahead of the word instead of after it + _("to ", "date modifier"), + ) - self.qualifiers = ("", - _("estimated ", "date quality"), - _("calculated ", "date quality"), - ) + self.qualifiers = ( + "", + _("estimated ", "date quality"), + _("calculated ", "date quality"), + ) # 6753: localized day names. Eventually should sprout into # a per-calendar type thing instead. - self.long_days = ("", - _("Sunday"), - _("Monday"), - _("Tuesday"), - _("Wednesday"), - _("Thursday"), - _("Friday"), - _("Saturday"), - ) + self.long_days = ( + "", + _("Sunday"), + _("Monday"), + _("Tuesday"), + _("Wednesday"), + _("Thursday"), + _("Friday"), + _("Saturday"), + ) - self.short_days = ("", # Icelandic needs them + self.short_days = ( + "", # Icelandic needs them _("Sun"), _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), - _("Sat")) + _("Sat"), + ) + # set GRAMPS_RESOURCES then: python3 -m gramps.gen.datehandler._datestrings -if __name__ == '__main__': +if __name__ == "__main__": import sys from ..utils.grampslocale import GrampsLocale from ..const import GRAMPS_LOCALE as glocale - from ._grampslocale import (_deprecated_long_months as old_long, - _deprecated_short_months as old_short, - _deprecated_short_days as old_short_days, # Icelandic needs them - _deprecated_long_days as old_days) + from ._grampslocale import ( + _deprecated_long_months as old_long, + _deprecated_short_months as old_short, + _deprecated_short_days as old_short_days, # Icelandic needs them + _deprecated_long_days as old_days, + ) from ._datedisplay import DateDisplay import gettext + lang = glocale.lang lang_short = lang[:2] - available_langs = glocale.languages # get the cached list + available_langs = glocale.languages # get the cached list if glocale.check_available_translations(lang) is None: - print ("Translation for current language {lang} not available.\n" - "Available translations: {list}.\n" - "Does po/{lang_short}*.po exist in gramps source tree?!\n" - "Please set your LANG / LC_ALL environment to something else...\n".format( - lang=lang, list=available_langs, lang_short=lang_short), - file=sys.stderr) + print( + "Translation for current language {lang} not available.\n" + "Available translations: {list}.\n" + "Does po/{lang_short}*.po exist in gramps source tree?!\n" + "Please set your LANG / LC_ALL environment to something else...\n".format( + lang=lang, list=available_langs, lang_short=lang_short + ), + file=sys.stderr, + ) sys.exit(1) - print ("# Generating snippets for {}*.po\n" - "# Available languages: {}".format( - lang_short, available_langs)) - glocale = GrampsLocale(languages=(lang)) # in __main__ + print( + "# Generating snippets for {}*.po\n" + "# Available languages: {}".format(lang_short, available_langs) + ) + glocale = GrampsLocale(languages=(lang)) # in __main__ dd = glocale.date_displayer ds = dd._ds - glocale_EN = GrampsLocale(languages=('en')) # in __main__ + glocale_EN = GrampsLocale(languages=("en")) # in __main__ ds_EN = DateStrings(glocale_EN) filename = __file__ @@ -297,35 +332,43 @@ if __name__ == '__main__': localized_months = old_long def print_po_snippet(en_loc_old_lists, context): - for m,localized,old in zip(*en_loc_old_lists): + for m, localized, old in zip(*en_loc_old_lists): if m == "": continue if m == localized: localized = old - print ('#: {file}:{line}\n' - 'msgid "{context}{en_month}"\n' - 'msgstr "{localized_month}"\n'.format( - context = context, - file = filename, - line = print_po_snippet.line, - en_month = m, - localized_month = localized)) + print( + "#: {file}:{line}\n" + 'msgid "{context}{en_month}"\n' + 'msgstr "{localized_month}"\n'.format( + context=context, + file=filename, + line=print_po_snippet.line, + en_month=m, + localized_month=localized, + ) + ) print_po_snippet.line += 1 + print_po_snippet.line = 10000 try: localized_months = dd.__class__.long_months except AttributeError: localized_months = old_long - print_po_snippet((ds_EN.long_months, localized_months, old_long), - "localized lexeme inflections||") + print_po_snippet( + (ds_EN.long_months, localized_months, old_long), + "localized lexeme inflections||", + ) try: localized_months = dd.__class__.short_months except AttributeError: localized_months = old_short - print_po_snippet((ds_EN.short_months, localized_months, old_short), - "localized lexeme inflections - short month form||") + print_po_snippet( + (ds_EN.short_months, localized_months, old_short), + "localized lexeme inflections - short month form||", + ) print_po_snippet((ds_EN.long_days, old_days, old_days), "") @@ -333,42 +376,36 @@ if __name__ == '__main__': try: loc = dd.__class__.hebrew - print_po_snippet((ds_EN.hebrew, loc, loc), - "Hebrew month lexeme|") + print_po_snippet((ds_EN.hebrew, loc, loc), "Hebrew month lexeme|") except AttributeError: pass try: loc = dd.__class__.french - print_po_snippet((ds_EN.french, loc, loc), - "French month lexeme|") + print_po_snippet((ds_EN.french, loc, loc), "French month lexeme|") except AttributeError: pass try: loc = dd.__class__.islamic - print_po_snippet((ds_EN.islamic, loc, loc), - "Islamic month lexeme|") + print_po_snippet((ds_EN.islamic, loc, loc), "Islamic month lexeme|") except AttributeError: pass try: loc = dd.__class__.persian - print_po_snippet((ds_EN.persian, loc, loc), - "Persian month lexeme|") + print_po_snippet((ds_EN.persian, loc, loc), "Persian month lexeme|") except AttributeError: pass try: loc = dd.__class__._mod_str - print_po_snippet((ds_EN.modifiers, loc, loc), - "date modifier|") + print_po_snippet((ds_EN.modifiers, loc, loc), "date modifier|") except AttributeError: pass try: loc = dd.__class__._qual_str - print_po_snippet((ds_EN.qualifiers, loc, loc), - "date quality|") + print_po_snippet((ds_EN.qualifiers, loc, loc), "date quality|") except AttributeError: pass diff --git a/gramps/gen/datehandler/test/datehandler_test.py b/gramps/gen/datehandler/test/datehandler_test.py index e75d51923..5f4fd6ecf 100644 --- a/gramps/gen/datehandler/test/datehandler_test.py +++ b/gramps/gen/datehandler/test/datehandler_test.py @@ -29,44 +29,46 @@ Validate localized date parser and displayer. Based on the Check Localized Date Displayer and Parser tool. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # standard python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import unittest import sys -if '-v' in sys.argv or '--verbose' in sys.argv: + +if "-v" in sys.argv or "--verbose" in sys.argv: import logging - logging.getLogger('').addHandler(logging.StreamHandler()) + + logging.getLogger("").addHandler(logging.StreamHandler()) log = logging.getLogger(".Date") log.setLevel(logging.DEBUG) -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ...config import config from ...lib import Date, DateError from ...utils.grampslocale import GrampsLocale, _LOCALE_NAMES from .. import LANG_TO_PARSER -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class DateHandlerTest(unittest.TestCase): - def setUp(self): - config.set('preferences.date-format', 0) + config.set("preferences.date-format", 0) def __base_test_all_languages(self, dates): - languages = [lang for lang in LANG_TO_PARSER.keys() - if lang in _LOCALE_NAMES.keys()] + languages = [ + lang for lang in LANG_TO_PARSER.keys() if lang in _LOCALE_NAMES.keys() + ] for language in languages: with self.subTest(lang=language): self.__test_language(language, dates) @@ -80,28 +82,43 @@ class DateHandlerTest(unittest.TestCase): datestr = displayer.display(test_date) new_date = parser.parse(datestr) with self.subTest(date=datestr): - self.assertTrue(test_date.is_equal(new_date), - "{} -> {}\n{} -> {}".format( - test_date, new_date, - test_date.__dict__, new_date.__dict__)) + self.assertTrue( + test_date.is_equal(new_date), + "{} -> {}\n{} -> {}".format( + test_date, new_date, test_date.__dict__, new_date.__dict__ + ), + ) def test_simple(self): dates = [] for calendar in (Date.CAL_GREGORIAN, Date.CAL_JULIAN): - for newyear in (Date.NEWYEAR_JAN1, Date.NEWYEAR_MAR25, (5,5)): - for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, - Date.QUAL_CALCULATED): - for modifier in (Date.MOD_NONE, Date.MOD_BEFORE, - Date.MOD_AFTER, Date.MOD_ABOUT): - for slash1 in (False,True): + for newyear in (Date.NEWYEAR_JAN1, Date.NEWYEAR_MAR25, (5, 5)): + for quality in ( + Date.QUAL_NONE, + Date.QUAL_ESTIMATED, + Date.QUAL_CALCULATED, + ): + for modifier in ( + Date.MOD_NONE, + Date.MOD_BEFORE, + Date.MOD_AFTER, + Date.MOD_ABOUT, + Date.MOD_FROM, + Date.MOD_TO, + ): + for slash1 in (False, True): for month in (2, 6, 12): for day in (5, 27): d = Date() - d.set(quality, modifier, calendar, - (day, month, 1789, slash1), - "Text comment", - newyear) + d.set( + quality, + modifier, + calendar, + (day, month, 1789, slash1), + "Text comment", + newyear, + ) dates.append(d) self.__base_test_all_languages(dates) @@ -109,36 +126,83 @@ class DateHandlerTest(unittest.TestCase): dates = [] calendar = Date.CAL_GREGORIAN - for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, - Date.QUAL_CALCULATED): + for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, Date.QUAL_CALCULATED): for modifier in (Date.MOD_RANGE, Date.MOD_SPAN): for slash1 in (False, True): for slash2 in (False, True): for month in (2, 6, 12): for day in (5, 27): d = Date() - d.set(quality, modifier, calendar, - (day, month, 1789, slash1, - day, month, 1876, slash2), - "Text comment") + d.set( + quality, + modifier, + calendar, + ( + day, + month, + 1789, + slash1, + day, + month, + 1876, + slash2, + ), + "Text comment", + ) dates.append(d) d = Date() - d.set(quality, modifier, calendar, - (day, month, 1789, slash1, - day, 13-month, 1876, slash2), - "Text comment") + d.set( + quality, + modifier, + calendar, + ( + day, + month, + 1789, + slash1, + day, + 13 - month, + 1876, + slash2, + ), + "Text comment", + ) dates.append(d) d = Date() - d.set(quality, modifier, calendar, - (day, month, 1789, slash1, - 32-day, month, 1876, slash2), - "Text comment") + d.set( + quality, + modifier, + calendar, + ( + day, + month, + 1789, + slash1, + 32 - day, + month, + 1876, + slash2, + ), + "Text comment", + ) dates.append(d) d = Date() - d.set(quality, modifier, calendar, - (day, month, 1789, slash1, - 32-day, 13-month, 1876, slash2), - "Text comment") + d.set( + quality, + modifier, + calendar, + ( + day, + month, + 1789, + slash1, + 32 - day, + 13 - month, + 1876, + slash2, + ), + "Text comment", + ) dates.append(d) self.__base_test_all_languages(dates) @@ -147,11 +211,11 @@ class DateHandlerTest(unittest.TestCase): dates = [] calendar = Date.CAL_GREGORIAN modifier = Date.MOD_TEXTONLY - for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, - Date.QUAL_CALCULATED): + for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, Date.QUAL_CALCULATED): test_date = Date() - test_date.set(quality, modifier, calendar, Date.EMPTY, - "This is a textual date") + test_date.set( + quality, modifier, calendar, Date.EMPTY, "This is a textual date" + ) dates.append(test_date) self.__base_test_all_languages(dates) @@ -160,46 +224,83 @@ class DateHandlerTest(unittest.TestCase): for l in range(1, len(dateval)): d = Date() with self.assertRaises(DateError): - d.set(Date.QUAL_NONE, Date.MOD_NONE, Date.CAL_GREGORIAN, - dateval[:l], "Text comment") + d.set( + Date.QUAL_NONE, + Date.MOD_NONE, + Date.CAL_GREGORIAN, + dateval[:l], + "Text comment", + ) def test_too_few_span_arguments(self): dateval = (4, 7, 1789, False, 5, 8, 1876, False) for l in range(1, len(dateval)): d = Date() with self.assertRaises(DateError): - d.set(Date.QUAL_NONE, Date.MOD_SPAN, Date.CAL_GREGORIAN, - dateval[:l], "Text comment") + d.set( + Date.QUAL_NONE, + Date.MOD_SPAN, + Date.CAL_GREGORIAN, + dateval[:l], + "Text comment", + ) def test_invalid_day(self): d = Date() with self.assertRaises(DateError): - d.set(Date.QUAL_NONE, Date.MOD_NONE, Date.CAL_GREGORIAN, - (44, 7, 1789,False), "Text comment") + d.set( + Date.QUAL_NONE, + Date.MOD_NONE, + Date.CAL_GREGORIAN, + (44, 7, 1789, False), + "Text comment", + ) def test_invalid_month(self): d = Date() with self.assertRaises(DateError): - d.set(Date.QUAL_NONE,Date.MOD_NONE, Date.CAL_GREGORIAN, - (4, 77, 1789, False), "Text comment") + d.set( + Date.QUAL_NONE, + Date.MOD_NONE, + Date.CAL_GREGORIAN, + (4, 77, 1789, False), + "Text comment", + ) def test_invalid_month_with_ny(self): d = Date() with self.assertRaises(DateError): - d.set(Date.QUAL_NONE,Date.MOD_NONE, Date.CAL_GREGORIAN, - (4, 77, 1789, False), "Text comment", newyear=2) + d.set( + Date.QUAL_NONE, + Date.MOD_NONE, + Date.CAL_GREGORIAN, + (4, 77, 1789, False), + "Text comment", + newyear=2, + ) def test_invalid_span_day(self): d = Date() with self.assertRaises(DateError): - d.set(Date.QUAL_NONE, Date.MOD_SPAN, Date.CAL_GREGORIAN, - (4, 7, 1789, False, 55, 8, 1876, False), "Text comment") + d.set( + Date.QUAL_NONE, + Date.MOD_SPAN, + Date.CAL_GREGORIAN, + (4, 7, 1789, False, 55, 8, 1876, False), + "Text comment", + ) def test_invalid_span_month(self): d = Date() with self.assertRaises(DateError): - d.set(Date.QUAL_NONE, Date.MOD_SPAN, Date.CAL_GREGORIAN, - (4, 7, 1789, False, 5, 88, 1876, False), "Text comment") + d.set( + Date.QUAL_NONE, + Date.MOD_SPAN, + Date.CAL_GREGORIAN, + (4, 7, 1789, False, 5, 88, 1876, False), + "Text comment", + ) + if __name__ == "__main__": unittest.main() diff --git a/gramps/gen/lib/date.py b/gramps/gen/lib/date.py index d2a7fdbf8..78870982f 100644 --- a/gramps/gen/lib/date.py +++ b/gramps/gen/lib/date.py @@ -24,37 +24,50 @@ """Support for dates.""" -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ # # Set up logging # -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ import logging -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gnome/GTK modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ # # Gramps modules # -#------------------------------------------------------------------------ -from .gcalendar import (gregorian_sdn, julian_sdn, hebrew_sdn, - french_sdn, persian_sdn, islamic_sdn, swedish_sdn, - gregorian_ymd, julian_ymd, hebrew_ymd, - french_ymd, persian_ymd, islamic_ymd, - swedish_ymd) +# ------------------------------------------------------------------------ +from .gcalendar import ( + gregorian_sdn, + julian_sdn, + hebrew_sdn, + french_sdn, + persian_sdn, + islamic_sdn, + swedish_sdn, + gregorian_ymd, + julian_ymd, + hebrew_ymd, + french_ymd, + persian_ymd, + islamic_ymd, + swedish_ymd, +) from ..config import config from ..errors import DateError from ..const import GRAMPS_LOCALE as glocale + _ = glocale.translation.sgettext LOG = logging.getLogger(".Date") + class Span: """ Span is used to represent the difference between two dates for three @@ -64,12 +77,14 @@ class Span: minmax = (min days, max days) """ - BEFORE = config.get('behavior.date-before-range') - AFTER = config.get('behavior.date-after-range') - ABOUT = config.get('behavior.date-about-range') - ALIVE = config.get('behavior.max-age-prob-alive') + + BEFORE = config.get("behavior.date-before-range") + AFTER = config.get("behavior.date-after-range") + ABOUT = config.get("behavior.date-about-range") + ALIVE = config.get("behavior.max-age-prob-alive") + def __init__(self, date1, date2): - self.valid = (date1.sortval != 0 and date2.sortval != 0) + self.valid = date1.sortval != 0 and date2.sortval != 0 self.date1 = date1 self.date2 = date2 self.sort = (-9999, -9999) @@ -86,15 +101,15 @@ class Span: if self.date2.calendar != Date.CAL_GREGORIAN: self.date2 = self.date2.to_calendar("gregorian") if self.date1.get_modifier() == Date.MOD_NONE: - if self.date2.get_modifier() == Date.MOD_NONE: + if self.date2.get_modifier() == Date.MOD_NONE: val = self.date1.sortval - self.date2.sortval self.sort = (val, 0) self.minmax = (val, val) - elif self.date2.get_modifier() == Date.MOD_BEFORE: + elif self.date2.get_modifier() in [Date.MOD_BEFORE, Date.MOD_TO]: val = self.date1.sortval - self.date2.sortval self.sort = (val, -Span.BEFORE) self.minmax = (val - Span.BEFORE, val) - elif self.date2.get_modifier() == Date.MOD_AFTER: + elif self.date2.get_modifier() in [Date.MOD_AFTER, Date.MOD_FROM]: val = self.date1.sortval - self.date2.sortval self.sort = (val, Span.AFTER) self.minmax = (val, val + Span.AFTER) @@ -107,19 +122,19 @@ class Span: start = Date(*start) stop = Date(*stop) val1 = self.date1.sortval - stop.sortval # min - val2 = self.date1.sortval - start.sortval # max + val2 = self.date1.sortval - start.sortval # max self.sort = (val1, val2 - val1) self.minmax = (val1, val2) elif self.date1.get_modifier() == Date.MOD_BEFORE: - if self.date2.get_modifier() == Date.MOD_NONE: + if self.date2.get_modifier() == Date.MOD_NONE: val = self.date1.sortval - self.date2.sortval self.sort = (val, 0) self.minmax = (0, val) - elif self.date2.get_modifier() == Date.MOD_BEFORE: + elif self.date2.get_modifier() in [Date.MOD_BEFORE, Date.MOD_TO]: val = self.date1.sortval - self.date2.sortval self.sort = (val, -Span.BEFORE) self.minmax = (val, val + Span.BEFORE) - elif self.date2.get_modifier() == Date.MOD_AFTER: + elif self.date2.get_modifier() in [Date.MOD_AFTER, Date.MOD_FROM]: val = self.date1.sortval - self.date2.sortval self.sort = (val, -Span.AFTER) self.minmax = (0, val) @@ -136,11 +151,11 @@ class Span: val = self.date1.sortval - self.date2.sortval self.sort = (val, Span.AFTER) self.minmax = (val, val + Span.AFTER) - elif self.date2.get_modifier() == Date.MOD_BEFORE: + elif self.date2.get_modifier() in [Date.MOD_BEFORE, Date.MOD_TO]: val = self.date1.sortval - self.date2.sortval self.sort = (val, Span.AFTER) self.minmax = (val - Span.BEFORE, val + Span.AFTER) - elif self.date2.get_modifier() == Date.MOD_AFTER: + elif self.date2.get_modifier() in [Date.MOD_AFTER, Date.MOD_FROM]: val = self.date1.sortval - self.date2.sortval self.sort = (val, Span.AFTER) self.minmax = (val, val + Span.AFTER) @@ -157,11 +172,11 @@ class Span: val = self.date1.sortval - self.date2.sortval self.sort = (val, -Span.ABOUT) self.minmax = (val - Span.ABOUT, val + Span.ABOUT) - elif self.date2.get_modifier() == Date.MOD_BEFORE: + elif self.date2.get_modifier() in [Date.MOD_BEFORE, Date.MOD_TO]: val = self.date1.sortval - self.date2.sortval self.sort = (val, -Span.BEFORE) self.minmax = (val - Span.BEFORE, val + Span.ABOUT) - elif self.date2.get_modifier() == Date.MOD_AFTER: + elif self.date2.get_modifier() in [Date.MOD_AFTER, Date.MOD_FROM]: val = self.date1.sortval - self.date2.sortval self.sort = (val, Span.AFTER) self.minmax = (val - Span.ABOUT, val + Span.ABOUT) @@ -178,15 +193,15 @@ class Span: start, stop = self.date1.get_start_stop_range() start = Date(*start) stop = Date(*stop) - val1 = start.sortval - self.date2.sortval # min - val2 = stop.sortval - self.date2.sortval # max + val1 = start.sortval - self.date2.sortval # min + val2 = stop.sortval - self.date2.sortval # max self.sort = (val1, val2 - val1) self.minmax = (val1, val2) - elif self.date2.get_modifier() == Date.MOD_BEFORE: + elif self.date2.get_modifier() in [Date.MOD_BEFORE, Date.MOD_TO]: val = self.date1.sortval - self.date2.sortval self.sort = (val, Span.BEFORE) self.minmax = (val - Span.BEFORE, val + Span.BEFORE) - elif self.date2.get_modifier() == Date.MOD_AFTER: + elif self.date2.get_modifier() in [Date.MOD_AFTER, Date.MOD_FROM]: val = self.date1.sortval - self.date2.sortval self.sort = (val, -Span.AFTER) self.minmax = (val - Span.AFTER, val + Span.AFTER) @@ -202,7 +217,7 @@ class Span: stop1 = Date(*stop1) stop2 = Date(*stop2) val1 = start1.sortval - stop2.sortval # min - val2 = stop1.sortval - start2.sortval # max + val2 = stop1.sortval - start2.sortval # max self.sort = (val1, val2 - val1) self.minmax = (val1, val2) @@ -225,20 +240,20 @@ class Span: else: return self.sort[0] + self.sort[1] -## def __cmp__(self, other): -## """ -## DEPRECATED - not available in python 3 -## -## Comparing two Spans for SORTING purposes. -## Use cmp(abs(int(span1)), abs(int(span2))) for comparing -## actual spans of times, as spans have directionality -## as indicated by negative values. -## """ -## raise NotImplementedError -## if other is None: -## return cmp(int(self), -9999) -## else: -## return cmp(int(self), int(other)) + ## def __cmp__(self, other): + ## """ + ## DEPRECATED - not available in python 3 + ## + ## Comparing two Spans for SORTING purposes. + ## Use cmp(abs(int(span1)), abs(int(span2))) for comparing + ## actual spans of times, as spans have directionality + ## as indicated by negative values. + ## """ + ## raise NotImplementedError + ## if other is None: + ## return cmp(int(self), -9999) + ## else: + ## return cmp(int(self), int(other)) def as_age(self): """ @@ -275,8 +290,9 @@ class Span: # FIXME all this concatenation will fail for RTL languages -- really?? if self.valid: fdate12 = self._format(self._diff(self.date1, self.date2), dlocale) - fdate12p1 = self._format(self._diff(self.date1, self.date2), - dlocale).format(precision=1) + fdate12p1 = self._format( + self._diff(self.date1, self.date2), dlocale + ).format(precision=1) if as_age and self._diff(self.date1, self.date2)[0] > Span.ALIVE: _repr = trans_text("greater than %s years") % Span.ALIVE elif self.date1.get_modifier() == Date.MOD_NONE: @@ -292,14 +308,17 @@ class Span: start, stop = self.date2.get_start_stop_range() start = Date(*start) stop = Date(*stop) - _repr = (trans_text("between") + " " + - self._format(self._diff(self.date1, stop), - dlocale) + " " + - trans_text("and") + " " + - self._format(self._diff(self.date1, start), - dlocale)) + _repr = ( + trans_text("between") + + " " + + self._format(self._diff(self.date1, stop), dlocale) + + " " + + trans_text("and") + + " " + + self._format(self._diff(self.date1, start), dlocale) + ) elif self.date1.get_modifier() == Date.MOD_BEFORE: - if self.date2.get_modifier() == Date.MOD_NONE: + if self.date2.get_modifier() == Date.MOD_NONE: _repr = trans_text("less than") + " " + fdate12 elif self.date2.get_modifier() == Date.MOD_BEFORE: _repr = self._format((-1, -1, -1)) @@ -310,7 +329,7 @@ class Span: elif self.date2.is_compound(): _repr = trans_text("less than") + " " + fdate12 elif self.date1.get_modifier() == Date.MOD_AFTER: - if self.date2.get_modifier() == Date.MOD_NONE: + if self.date2.get_modifier() == Date.MOD_NONE: _repr = trans_text("more than") + " " + fdate12 elif self.date2.get_modifier() == Date.MOD_BEFORE: _repr = trans_text("more than") + " " + fdate12 @@ -321,7 +340,7 @@ class Span: elif self.date2.is_compound(): _repr = trans_text("more than") + " " + fdate12 elif self.date1.get_modifier() == Date.MOD_ABOUT: - if self.date2.get_modifier() == Date.MOD_NONE: + if self.date2.get_modifier() == Date.MOD_NONE: _repr = trans_text("about", "age") + " " + fdate12p1 elif self.date2.get_modifier() == Date.MOD_BEFORE: _repr = trans_text("more than about") + " " + fdate12p1 @@ -332,16 +351,19 @@ class Span: elif self.date2.is_compound(): _repr = trans_text("about", "age") + " " + fdate12p1 elif self.date1.is_compound(): - if self.date2.get_modifier() == Date.MOD_NONE: + if self.date2.get_modifier() == Date.MOD_NONE: start, stop = self.date1.get_start_stop_range() start = Date(*start) stop = Date(*stop) - _repr = (trans_text("between") + " " + - self._format(self._diff(start, self.date2), - dlocale) + " " + - trans_text("and") + " " + - self._format(self._diff(stop, self.date2), - dlocale)) + _repr = ( + trans_text("between") + + " " + + self._format(self._diff(start, self.date2), dlocale) + + " " + + trans_text("and") + + " " + + self._format(self._diff(stop, self.date2), dlocale) + ) elif self.date2.get_modifier() == Date.MOD_BEFORE: _repr = trans_text("more than") + " " + fdate12 elif self.date2.get_modifier() == Date.MOD_AFTER: @@ -355,14 +377,19 @@ class Span: start2 = Date(*start2) stop1 = Date(*stop1) stop2 = Date(*stop2) - _repr = (trans_text("between") + " " + - self._format(self._diff(start1, stop2), dlocale) + - " " + trans_text("and") + " " + - self._format(self._diff(stop1, start2), dlocale)) - if _repr.find('-') == -1: # we don't have a negative value to return. + _repr = ( + trans_text("between") + + " " + + self._format(self._diff(start1, stop2), dlocale) + + " " + + trans_text("and") + + " " + + self._format(self._diff(stop1, start2), dlocale) + ) + if _repr.find("-") == -1: # we don't have a negative value to return. return _repr else: - return '(' + _repr.replace('-', '') + ')' + return "(" + _repr.replace("-", "") + ")" def __eq__(self, other): """ @@ -415,7 +442,7 @@ class Span: :param dlocale: allow deferred translation of strings :type dlocale: a :class:`.GrampsLocale` instance """ - ngettext = dlocale.translation.ngettext # to see "nearby" comments + ngettext = dlocale.translation.ngettext # to see "nearby" comments # trans_text is a defined keyword (see po/update_po.py, po/genpot.sh) trans_text = dlocale.translation.sgettext if diff_tuple == (-1, -1, -1): @@ -424,25 +451,25 @@ class Span: detail = 0 if diff_tuple[0] != 0: # Translators: leave all/any {...} untranslated - retval += ngettext("{number_of} year", "{number_of} years", - diff_tuple[0] - ).format(number_of=diff_tuple[0]) + retval += ngettext( + "{number_of} year", "{number_of} years", diff_tuple[0] + ).format(number_of=diff_tuple[0]) detail += 1 if self.precision == detail: - if diff_tuple[1] >= 6: # round up years + if diff_tuple[1] >= 6: # round up years # Translators: leave all/any {...} untranslated - retval = ngettext("{number_of} year", "{number_of} years", - diff_tuple[0] + 1 - ).format(number_of=diff_tuple[0] + 1) + retval = ngettext( + "{number_of} year", "{number_of} years", diff_tuple[0] + 1 + ).format(number_of=diff_tuple[0] + 1) return retval if diff_tuple[1] != 0: if retval != "": # Translators: needed for Arabic, ignore otherwise retval += trans_text(", ") # Translators: leave all/any {...} untranslated - retval += ngettext("{number_of} month", "{number_of} months", - diff_tuple[1] - ).format(number_of=diff_tuple[1]) + retval += ngettext( + "{number_of} month", "{number_of} months", diff_tuple[1] + ).format(number_of=diff_tuple[1]) detail += 1 if self.precision == detail: return retval @@ -451,9 +478,9 @@ class Span: # Translators: needed for Arabic, ignore otherwise retval += trans_text(", ") # Translators: leave all/any {...} untranslated - retval += ngettext("{number_of} day", "{number_of} days", - diff_tuple[2] - ).format(number_of=diff_tuple[2]) + retval += ngettext( + "{number_of} day", "{number_of} days", diff_tuple[2] + ).format(number_of=diff_tuple[2]) detail += 1 if self.precision == detail: return retval @@ -487,7 +514,7 @@ class Span: # months: if ymd2[1] > ymd1[1]: ymd1[0] -= 1 # from years - ymd1[1] += 12 # to months + ymd1[1] += 12 # to months days = ymd1[2] - ymd2[2] months = ymd1[1] - ymd2[1] years = ymd1[0] - ymd2[0] @@ -501,7 +528,7 @@ class Span: # Check transitivity: if date1.is_full() and date2.is_full(): edate = date1 - (years, months, days) - if edate < date2: # too small, strictly less than + if edate < date2: # too small, strictly less than diff = 0 while edate << date2 and diff < 60: diff += 1 @@ -528,17 +555,19 @@ class Span: else: return (years, months, days) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Date class # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class Date: """ The core date handling class for Gramps. Supports partial dates, compound dates and alternate calendars. """ + MOD_NONE = 0 # CODE MOD_BEFORE = 1 MOD_AFTER = 2 @@ -546,13 +575,15 @@ class Date: MOD_RANGE = 4 MOD_SPAN = 5 MOD_TEXTONLY = 6 + MOD_FROM = 7 + MOD_TO = 8 - QUAL_NONE = 0 # BITWISE + QUAL_NONE = 0 # BITWISE QUAL_ESTIMATED = 1 QUAL_CALCULATED = 2 - #QUAL_INTERPRETED = 4 unused in source!! + # QUAL_INTERPRETED = 4 unused in source!! - CAL_GREGORIAN = 0 # CODE + CAL_GREGORIAN = 0 # CODE CAL_JULIAN = 1 CAL_HEBREW = 2 CAL_FRENCH = 3 @@ -561,7 +592,7 @@ class Date: CAL_SWEDISH = 6 CALENDARS = range(7) - NEWYEAR_JAN1 = 0 # CODE + NEWYEAR_JAN1 = 0 # CODE NEWYEAR_MAR1 = 1 NEWYEAR_MAR25 = 2 NEWYEAR_SEP1 = 3 @@ -585,7 +616,7 @@ class Date: persian_sdn, islamic_sdn, swedish_sdn, - ] + ] _calendar_change = [ gregorian_ymd, @@ -595,24 +626,27 @@ class Date: persian_ymd, islamic_ymd, swedish_ymd, - ] + ] - calendar_names = ["Gregorian", - "Julian", - "Hebrew", - "French Republican", - "Persian", - "Islamic", - "Swedish"] + calendar_names = [ + "Gregorian", + "Julian", + "Hebrew", + "French Republican", + "Persian", + "Islamic", + "Swedish", + ] - - ui_calendar_names = [_("Gregorian", "calendar"), - _("Julian", "calendar"), - _("Hebrew", "calendar"), - _("French Republican", "calendar"), - _("Persian", "calendar"), - _("Islamic", "calendar"), - _("Swedish", "calendar")] + ui_calendar_names = [ + _("Gregorian", "calendar"), + _("Julian", "calendar"), + _("Hebrew", "calendar"), + _("French Republican", "calendar"), + _("Persian", "calendar"), + _("Islamic", "calendar"), + _("Swedish", "calendar"), + ] def __init__(self, *source): """ @@ -629,7 +663,7 @@ class Date: elif len(source) == 2: source = (source[0], source[1], 0) elif len(source) == 3: - pass # source is ok + pass # source is ok else: raise AttributeError("invalid args to Date: %s" % source) self.format = None @@ -665,28 +699,48 @@ class Date: Convert to a series of tuples for data storage. """ if no_text_date: - text = '' + text = "" else: text = self.text - return (self.calendar, self.modifier, self.quality, - self.dateval, text, self.sortval, self.newyear) + return ( + self.calendar, + self.modifier, + self.quality, + self.dateval, + text, + self.sortval, + self.newyear, + ) def unserialize(self, data): """ Load from the format created by serialize. """ - #FIXME: work around 3.1.0 error: - #2792: Dates in sourcereferences in person_ref_list not upgraded - #Added 2009/03/09 + # FIXME: work around 3.1.0 error: + # 2792: Dates in sourcereferences in person_ref_list not upgraded + # Added 2009/03/09 if len(data) == 7: # This is correct: - (self.calendar, self.modifier, self.quality, - self.dateval, self.text, self.sortval, self.newyear) = data + ( + self.calendar, + self.modifier, + self.quality, + self.dateval, + self.text, + self.sortval, + self.newyear, + ) = data elif len(data) == 6: # This is necessary to fix 3.1.0 bug: - (self.calendar, self.modifier, self.quality, - self.dateval, self.text, self.sortval) = data + ( + self.calendar, + self.modifier, + self.quality, + self.dateval, + self.text, + self.sortval, + ) = data self.newyear = 0 # Remove all except if-part after 3.1.1 else: @@ -706,22 +760,18 @@ class Date: "title": _("Date"), "properties": { "_class": {"enum": [cls.__name__]}, - "calendar": {"type": "integer", - "title": _("Calendar")}, - "modifier": {"type": "integer", - "title": _("Modifier")}, - "quality": {"type": "integer", - "title": _("Quality")}, - "dateval": {"type": "array", - "title": _("Values"), - "items": {"type": ["integer", "boolean"]}}, - "text": {"type": "string", - "title": _("Text")}, - "sortval": {"type": "integer", - "title": _("Sort value")}, - "newyear": {"type": "integer", - "title": _("New year begins")} - } + "calendar": {"type": "integer", "title": _("Calendar")}, + "modifier": {"type": "integer", "title": _("Modifier")}, + "quality": {"type": "integer", "title": _("Quality")}, + "dateval": { + "type": "array", + "title": _("Values"), + "items": {"type": ["integer", "boolean"]}, + }, + "text": {"type": "string", "title": _("Text")}, + "sortval": {"type": "integer", "title": _("Sort value")}, + "newyear": {"type": "integer", "title": _("New year begins")}, + }, } def copy(self, source): @@ -737,21 +787,21 @@ class Date: self.sortval = source.sortval self.newyear = source.newyear -## PYTHON 3 no __cmp__ -## def __cmp__(self, other): -## """ -## Compare two dates. -## -## Comparison function. Allows the usage of equality tests. -## This allows you do run statements like 'date1 <= date2' -## """ -## if isinstance(other, Date): -## return cmp(self.sortval, other.sortval) -## else: -## return -1 + ## PYTHON 3 no __cmp__ + ## def __cmp__(self, other): + ## """ + ## Compare two dates. + ## + ## Comparison function. Allows the usage of equality tests. + ## This allows you do run statements like 'date1 <= date2' + ## """ + ## if isinstance(other, Date): + ## return cmp(self.sortval, other.sortval) + ## else: + ## return -1 # Can't use this (as is) as this breaks comparing dates to None - #def __eq__(self, other): + # def __eq__(self, other): # return self.sortval == other.sortval def __eq__(self, other): @@ -761,7 +811,7 @@ class Date: if isinstance(other, Date): return self.sortval == other.sortval else: - #indicate this is not supported + # indicate this is not supported return False def __ne__(self, other): @@ -771,7 +821,7 @@ class Date: if isinstance(other, Date): return self.sortval != other.sortval else: - #indicate this is not supported + # indicate this is not supported return True def __le__(self, other): @@ -782,7 +832,7 @@ class Date: if isinstance(other, Date): return self.sortval <= other.sortval else: - #indicate this is not supported + # indicate this is not supported return NotImplemented def __ge__(self, other): @@ -793,7 +843,7 @@ class Date: if isinstance(other, Date): return self.sortval >= other.sortval else: - #indicate this is not supported + # indicate this is not supported return NotImplemented def __add__(self, other): @@ -817,11 +867,11 @@ class Date: """ Date arithmetic: Date() - years, Date - (y,m,d), or Date() - Date(). """ - if isinstance(other, int): # Date - value -> Date + if isinstance(other, int): # Date - value -> Date return self.copy_offset_ymd(-other) - elif isinstance(other, (tuple, list)): # Date - (y, m, d) -> Date + elif isinstance(other, (tuple, list)): # Date - (y, m, d) -> Date return self.copy_offset_ymd(*[-i for i in other]) - elif isinstance(other, type(self)): # Date1 - Date2 -> tuple + elif isinstance(other, type(self)): # Date1 - Date2 -> tuple return Span(self, other) else: raise AttributeError("unknown date sub type: %s " % type(other)) @@ -864,14 +914,15 @@ class Date: Needed, because the __cmp__ only looks at the sorting value, and ignores the modifiers/comments. """ - if self.modifier == other.modifier \ - and self.modifier == Date.MOD_TEXTONLY: + if self.modifier == other.modifier and self.modifier == Date.MOD_TEXTONLY: value = self.text == other.text else: - value = (self.calendar == other.calendar and - self.modifier == other.modifier and - self.quality == other.quality and - self.dateval == other.dateval) + value = ( + self.calendar == other.calendar + and self.modifier == other.modifier + and self.quality == other.quality + and self.dateval == other.dateval + ) return value def get_start_stop_range(self): @@ -894,8 +945,12 @@ class Date: Slash date is already taken care of. """ - return (dateval[Date._POS_YR], dateval[Date._POS_MON], - dateval[Date._POS_DAY]) + return ( + dateval[Date._POS_YR], + dateval[Date._POS_MON], + dateval[Date._POS_DAY], + ) + def date_offset(dateval, offset): """ Local function to do date arithmetic: add the offset, return @@ -906,7 +961,7 @@ class Date: return new_date.offset(offset) datecopy = Date(self) - #we do all calculation in Gregorian calendar + # we do all calculation in Gregorian calendar datecopy.convert_calendar(Date.CAL_GREGORIAN) start = yr_mon_day(datecopy.get_start_date()) @@ -916,7 +971,7 @@ class Date: stop = start stopmax = list(stop) - if stopmax[0] == 0: # then use start_year, if one + if stopmax[0] == 0: # then use start_year, if one stopmax[0] = start[Date._POS_YR] if stopmax[1] == 0: stopmax[1] = 12 @@ -928,17 +983,18 @@ class Date: if startmin[2] == 0: startmin[2] = 1 # if BEFORE, AFTER, or ABOUT/EST, adjust: - if self.modifier == Date.MOD_BEFORE: - stopmax = date_offset(startmin, -1) - fdiff = config.get('behavior.date-before-range') + if self.modifier in [Date.MOD_BEFORE, Date.MOD_TO]: + if self.modifier == Date.MOD_BEFORE: + stopmax = date_offset(startmin, -1) + fdiff = config.get("behavior.date-before-range") startmin = (stopmax[0] - fdiff, stopmax[1], stopmax[2]) - elif self.modifier == Date.MOD_AFTER: - startmin = date_offset(stopmax, 1) - fdiff = config.get('behavior.date-after-range') + elif self.modifier in [Date.MOD_AFTER, Date.MOD_FROM]: + if self.modifier == Date.MOD_AFTER: + startmin = date_offset(stopmax, 1) + fdiff = config.get("behavior.date-after-range") stopmax = (startmin[0] + fdiff, startmin[1], startmin[2]) - elif (self.modifier == Date.MOD_ABOUT or - self.quality == Date.QUAL_ESTIMATED): - fdiff = config.get('behavior.date-about-range') + elif self.modifier == Date.MOD_ABOUT or self.quality == Date.QUAL_ESTIMATED: + fdiff = config.get("behavior.date-about-range") startmin = (startmin[0] - fdiff, startmin[1], startmin[2]) stopmax = (stopmax[0] + fdiff, stopmax[1], stopmax[2]) # return tuples not lists, for comparisons @@ -951,9 +1007,9 @@ class Date: """ if other_date.modifier == Date.MOD_NONE: return other_date.sortval == self.sortval - elif other_date.modifier == Date.MOD_BEFORE: + elif other_date.modifier in [Date.MOD_BEFORE, Date.MOD_TO]: return other_date.sortval > self.sortval - elif other_date.modifier == Date.MOD_AFTER: + elif other_date.modifier in [Date.MOD_AFTER, Date.MOD_FROM]: return other_date.sortval < self.sortval elif other_date.is_compound(): start, stop = other_date.get_start_stop_range() @@ -977,13 +1033,17 @@ class Date: ========== ======================================================= =,== True if any part of other_date matches any part of self < True if any part of other_date < any part of self + <= True if any part of other_date <= any part of self << True if all parts of other_date < all parts of self > True if any part of other_date > any part of self + >= True if any part of other_date >= any part of self >> True if all parts of other_date > all parts of self ========== ======================================================= """ - if (other_date.modifier == Date.MOD_TEXTONLY or - self.modifier == Date.MOD_TEXTONLY): + if ( + other_date.modifier == Date.MOD_TEXTONLY + or self.modifier == Date.MOD_TEXTONLY + ): if comparison == "=": return self.text.upper().find(other_date.text.upper()) != -1 elif comparison == "==": @@ -999,14 +1059,15 @@ class Date: if comparison == "=": # If some overlap then match is True, otherwise False. - return ((self_start <= other_start <= self_stop) or - (self_start <= other_stop <= self_stop) or - (other_start <= self_start <= other_stop) or - (other_start <= self_stop <= other_stop)) + return ( + (self_start <= other_start <= self_stop) + or (self_start <= other_stop <= self_stop) + or (other_start <= self_start <= other_stop) + or (other_start <= self_stop <= other_stop) + ) elif comparison == "==": # If they match exactly on start and stop - return ((self_start == other_start) and - (other_stop == other_stop)) + return (self_start == other_start) and (other_stop == other_stop) elif comparison == "<": # If any < any return self_start < other_stop @@ -1026,8 +1087,7 @@ class Date: # If all > all return self_start > other_stop else: - raise AttributeError("invalid match comparison operator: '%s'" % - comparison) + raise AttributeError("invalid match comparison operator: '%s'" % comparison) def __str__(self): """ @@ -1049,6 +1109,10 @@ class Date: pref = "bef " elif self.modifier == Date.MOD_AFTER: pref = "aft " + elif self.modifier == Date.MOD_FROM: + pref = "from " + elif self.modifier == Date.MOD_TO: + pref = "to " elif self.modifier == Date.MOD_ABOUT: pref = "abt " else: @@ -1074,16 +1138,23 @@ class Date: self.dateval[Date._POS_YR] - 1, (self.dateval[Date._POS_YR]) % 10, self.dateval[Date._POS_MON], - self.dateval[Date._POS_DAY]) + self.dateval[Date._POS_DAY], + ) elif self.is_compound(): val = "%04d-%02d-%02d - %04d-%02d-%02d" % ( - self.dateval[Date._POS_YR], self.dateval[Date._POS_MON], - self.dateval[Date._POS_DAY], self.dateval[Date._POS_RYR], - self.dateval[Date._POS_RMON], self.dateval[Date._POS_RDAY]) + self.dateval[Date._POS_YR], + self.dateval[Date._POS_MON], + self.dateval[Date._POS_DAY], + self.dateval[Date._POS_RYR], + self.dateval[Date._POS_RMON], + self.dateval[Date._POS_RDAY], + ) else: val = "%04d-%02d-%02d" % ( - self.dateval[Date._POS_YR], self.dateval[Date._POS_MON], - self.dateval[Date._POS_DAY]) + self.dateval[Date._POS_YR], + self.dateval[Date._POS_MON], + self.dateval[Date._POS_DAY], + ) return "%s%s%s%s" % (qual, pref, val, cal) def newyear_to_str(self): @@ -1156,6 +1227,8 @@ class Date: MOD_AFTER after MOD_ABOUT about MOD_RANGE date range + MOD_FROM open ended date span + MOD_TO open ended date span MOD_SPAN date span MOD_TEXTONLY text only ============ ===================== @@ -1166,9 +1239,17 @@ class Date: """ Set the modifier for the date. """ - if val not in (Date.MOD_NONE, Date.MOD_BEFORE, Date.MOD_AFTER, - Date.MOD_ABOUT, Date.MOD_RANGE, Date.MOD_SPAN, - Date.MOD_TEXTONLY): + if val not in ( + Date.MOD_NONE, + Date.MOD_BEFORE, + Date.MOD_AFTER, + Date.MOD_ABOUT, + Date.MOD_RANGE, + Date.MOD_FROM, + Date.MOD_TO, + Date.MOD_SPAN, + Date.MOD_TEXTONLY, + ): raise DateError("Invalid modifier") self.modifier = val @@ -1190,8 +1271,7 @@ class Date: """ Set the quality selected for the date. """ - if val not in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, - Date.QUAL_CALCULATED): + if val not in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, Date.QUAL_CALCULATED): raise DateError("Invalid quality") self.quality = val @@ -1340,8 +1420,9 @@ class Date: if self.is_compound() and remove_stop_date is None: raise DateError("Required parameter remove_stop_date not set!") - self.__set_yr_mon_day(year, month, day, - Date._POS_YR, Date._POS_MON, Date._POS_DAY) + self.__set_yr_mon_day( + year, month, day, Date._POS_YR, Date._POS_MON, Date._POS_DAY + ) self._calc_sort_value() if remove_stop_date and self.is_compound(): self.set2_yr_mon_day(year, month, day) @@ -1356,11 +1437,11 @@ class Date: a compound date (range or span). """ self._assert_compound() - self.__set_yr_mon_day(year, month, day, - Date._POS_RYR, Date._POS_RMON, Date._POS_RDAY) + self.__set_yr_mon_day( + year, month, day, Date._POS_RYR, Date._POS_RMON, Date._POS_RDAY + ) - def __set_yr_mon_day_offset(self, year, month, day, - pos_yr, pos_mon, pos_day): + def __set_yr_mon_day_offset(self, year, month, day, pos_yr, pos_mon, pos_day): dlist = list(self.dateval) if dlist[pos_yr]: dlist[pos_yr] += year @@ -1374,13 +1455,13 @@ class Date: else: dlist[pos_mon] = month # Fix if month out of bounds: - if month != 0: # only check if changed - if dlist[pos_mon] == 0: # subtraction + if month != 0: # only check if changed + if dlist[pos_mon] == 0: # subtraction dlist[pos_mon] = 12 dlist[pos_yr] -= 1 - elif dlist[pos_mon] < 0: # subtraction + elif dlist[pos_mon] < 0: # subtraction dlist[pos_yr] -= int((-dlist[pos_mon]) // 12) + 1 - dlist[pos_mon] = (dlist[pos_mon] % 12) + dlist[pos_mon] = dlist[pos_mon] % 12 elif dlist[pos_mon] > 12 or dlist[pos_mon] < 1: dlist[pos_yr] += int(dlist[pos_mon] // 12) dlist[pos_mon] = dlist[pos_mon] % 12 @@ -1392,8 +1473,9 @@ class Date: """ Offset the date by the given year, month, and day values. """ - if self.__set_yr_mon_day_offset(year, month, day, Date._POS_YR, - Date._POS_MON, Date._POS_DAY): + if self.__set_yr_mon_day_offset( + year, month, day, Date._POS_YR, Date._POS_MON, Date._POS_DAY + ): self.set_yr_mon_day(*self.offset(day), remove_stop_date=False) if self.is_compound(): self.set2_yr_mon_day_offset(year, month, day) @@ -1404,8 +1486,9 @@ class Date: of a compound date (range or span). """ self._assert_compound() - if self.__set_yr_mon_day_offset(year, month, day, Date._POS_RYR, - Date._POS_RMON, Date._POS_RDAY): + if self.__set_yr_mon_day_offset( + year, month, day, Date._POS_RYR, Date._POS_RMON, Date._POS_RDAY + ): stop = Date(self.get_stop_ymd()) self.set2_yr_mon_day(*stop.offset(day)) @@ -1440,7 +1523,7 @@ class Date: """ Set the year value. """ - self.dateval = self.dateval[0:2] + (year, ) + self.dateval[3:] + self.dateval = self.dateval[0:2] + (year,) + self.dateval[3:] self._calc_sort_value() def get_year_valid(self): @@ -1560,7 +1643,7 @@ class Date: """ nyear = self.get_new_year() year_delta = 0 - if nyear: # new year offset? + if nyear: # new year offset? if nyear == Date.NEWYEAR_MAR1: split = (3, 1) elif nyear == Date.NEWYEAR_MAR25: @@ -1573,15 +1656,23 @@ class Date: split = (0, 0) if (self.get_month(), self.get_day()) >= split and split != (0, 0): year_delta = -1 - new_date = Date(self.get_year() + year_delta, self.get_month(), - self.get_day()) + new_date = Date( + self.get_year() + year_delta, self.get_month(), self.get_day() + ) new_date.set_calendar(self.calendar) new_date.recalc_sort_value() self.sortval = new_date.sortval return year_delta - def set(self, quality=None, modifier=None, calendar=None, - value=None, text=None, newyear=0): + def set( + self, + quality=None, + modifier=None, + calendar=None, + value=None, + text=None, + newyear=0, + ): """ Set the date to the specified value. @@ -1618,25 +1709,45 @@ class Date: if value is None: value = self.dateval - if modifier in (Date.MOD_NONE, Date.MOD_BEFORE, - Date.MOD_AFTER, Date.MOD_ABOUT) and len(value) < 4: + if ( + modifier + in ( + Date.MOD_NONE, + Date.MOD_BEFORE, + Date.MOD_AFTER, + Date.MOD_ABOUT, + Date.MOD_FROM, + Date.MOD_TO, + ) + and len(value) < 4 + ): raise DateError("Invalid value. Should be: (DD, MM, YY, slash)") if modifier in (Date.MOD_RANGE, Date.MOD_SPAN) and len(value) < 8: - raise DateError("Invalid value. Should be: (DD, MM, " - "YY, slash1, DD, MM, YY, slash2)") - if modifier not in (Date.MOD_NONE, Date.MOD_BEFORE, Date.MOD_AFTER, - Date.MOD_ABOUT, Date.MOD_RANGE, Date.MOD_SPAN, - Date.MOD_TEXTONLY): + raise DateError( + "Invalid value. Should be: (DD, MM, " "YY, slash1, DD, MM, YY, slash2)" + ) + if modifier not in ( + Date.MOD_NONE, + Date.MOD_BEFORE, + Date.MOD_AFTER, + Date.MOD_ABOUT, + Date.MOD_RANGE, + Date.MOD_FROM, + Date.MOD_TO, + Date.MOD_SPAN, + Date.MOD_TEXTONLY, + ): raise DateError("Invalid modifier") - if quality not in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, - Date.QUAL_CALCULATED): + if quality not in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, Date.QUAL_CALCULATED): raise DateError("Invalid quality") if calendar not in Date.CALENDARS: raise DateError("Invalid calendar") if newyear != 0 and calendar_has_fixed_newyear(calendar): raise DateError( "May not adjust newyear to {ny} for calendar {cal}".format( - ny=newyear, cal=calendar)) + ny=newyear, cal=calendar + ) + ) self.quality = quality self.modifier = modifier @@ -1644,9 +1755,8 @@ class Date: self.dateval = value self.set_new_year(newyear) year, month, day = self._zero_adjust_ymd( - value[Date._POS_YR], - value[Date._POS_MON], - value[Date._POS_DAY]) + value[Date._POS_YR], value[Date._POS_MON], value[Date._POS_DAY] + ) if year == month == day == 0: self.sortval = 0 @@ -1683,32 +1793,37 @@ class Date: try: self.__compare(sanity.dateval, value, year_delta) except DateError as err: - LOG.debug("Sanity check failed - self: {}, sanity: {}". - format(self.__dict__, sanity.__dict__)) + LOG.debug( + "Sanity check failed - self: {}, sanity: {}".format( + self.__dict__, sanity.__dict__ + ) + ) err.date = self raise def __compare(self, sanity, value, year_delta): ziplist = zip(sanity, value) # Loop over all values present, whether compound or not - for day, month, year, slash in zip(*[iter(ziplist)]*4): + for day, month, year, slash in zip(*[iter(ziplist)] * 4): # each of d,m,y,sl is a pair from dateval and value, to compare adjusted, original = slash if adjusted != original: - raise DateError("Invalid date value {}". - format(value)) + raise DateError("Invalid date value {}".format(value)) for adjusted, original in day, month: - if adjusted != original and not(original == 0 and - adjusted == 1): - raise DateError("Invalid day/month {} passed in value {}". - format(original, value)) + if adjusted != original and not (original == 0 and adjusted == 1): + raise DateError( + "Invalid day/month {} passed in value {}".format( + original, value + ) + ) adjusted, original = year adjusted -= year_delta - if adjusted != original and not(original == 0 and adjusted == 1): - raise DateError("Invalid year {} passed in value {}". - format(original, value)) + if adjusted != original and not (original == 0 and adjusted == 1): + raise DateError( + "Invalid year {} passed in value {}".format(original, value) + ) def recalc_sort_value(self): """ @@ -1725,7 +1840,8 @@ class Date: year, month, day = self._zero_adjust_ymd( self.dateval[Date._POS_YR], self.dateval[Date._POS_MON], - self.dateval[Date._POS_DAY]) + self.dateval[Date._POS_DAY], + ) if year == month == 0 and day == 0: self.sortval = 0 else: @@ -1736,20 +1852,22 @@ class Date: """ Convert the date from the current calendar to the specified calendar. """ - if (known_valid # if not known valid, round-trip convert anyway - and calendar == self.calendar - and self.newyear == Date.NEWYEAR_JAN1): + if ( + known_valid # if not known valid, round-trip convert anyway + and calendar == self.calendar + and self.newyear == Date.NEWYEAR_JAN1 + ): return (year, month, day) = Date._calendar_change[calendar](self.sortval) if self.is_compound(): ryear, rmonth, rday = self._zero_adjust_ymd( self.dateval[Date._POS_RYR], self.dateval[Date._POS_RMON], - self.dateval[Date._POS_RDAY]) + self.dateval[Date._POS_RDAY], + ) sdn = Date._calendar_convert[self.calendar](ryear, rmonth, rday) (nyear, nmonth, nday) = Date._calendar_change[calendar](sdn) - self.dateval = (day, month, year, False, - nday, nmonth, nyear, False) + self.dateval = (day, month, year, False, nday, nmonth, nyear, False) else: self.dateval = (day, month, year, False) self.calendar = calendar @@ -1773,16 +1891,17 @@ class Date: """ Return True if the date contains no information (empty text). """ - return not((self.modifier == Date.MOD_TEXTONLY and self.text) - or self.get_start_date() != Date.EMPTY - or self.get_stop_date() != Date.EMPTY) + return not ( + (self.modifier == Date.MOD_TEXTONLY and self.text) + or self.get_start_date() != Date.EMPTY + or self.get_stop_date() != Date.EMPTY + ) def is_compound(self): """ Return True if the date is a date range or a date span. """ - return self.modifier == Date.MOD_RANGE \ - or self.modifier == Date.MOD_SPAN + return self.modifier == Date.MOD_RANGE or self.modifier == Date.MOD_SPAN def is_regular(self): """ @@ -1792,18 +1911,19 @@ class Date: a range or a span, not estimated/calculated, not about/before/after date, and having year, month, and day all non-zero. """ - return self.modifier == Date.MOD_NONE \ - and self.quality == Date.QUAL_NONE \ - and self.get_year_valid() and self.get_month_valid() \ - and self.get_day_valid() + return ( + self.modifier == Date.MOD_NONE + and self.quality == Date.QUAL_NONE + and self.get_year_valid() + and self.get_month_valid() + and self.get_day_valid() + ) def is_full(self): """ Return True if the date is fully specified. """ - return (self.get_year_valid() and - self.get_month_valid() and - self.get_day_valid()) + return self.get_year_valid() and self.get_month_valid() and self.get_day_valid() def get_ymd(self): """ @@ -1816,8 +1936,7 @@ class Date: Return (day, month, year, [slash]). """ if get_slash: - return (self.get_day(), self.get_month(), self.get_year(), - self.get_slash()) + return (self.get_day(), self.get_month(), self.get_year(), self.get_slash()) else: return (self.get_day(), self.get_month(), self.get_year()) @@ -1826,8 +1945,7 @@ class Date: Return (year, month, day) of the stop date, or all-zeros if it's not defined. """ - return (self.get_stop_year(), self.get_stop_month(), - self.get_stop_day()) + return (self.get_stop_year(), self.get_stop_month(), self.get_stop_day()) def offset(self, value): """ @@ -1839,8 +1957,7 @@ class Date: """ Return (year, month, day) of this date +- value. """ - return Date(Date._calendar_change[Date.CAL_GREGORIAN](self.sortval + - value)) + return Date(Date._calendar_change[Date.CAL_GREGORIAN](self.sortval + value)) def lookup_calendar(self, calendar): """ @@ -1853,8 +1970,7 @@ class Date: Lookup date quality keyword, even if translated. """ qualities = ["none", "estimated", "calculated"] - ui_qualities = [_("none", "date-quality"), - _("estimated"), _("calculated")] + ui_qualities = [_("none", "date-quality"), _("estimated"), _("calculated")] if quality.lower() in qualities: return qualities.index(quality.lower()) elif quality.lower() in ui_qualities: @@ -1866,11 +1982,28 @@ class Date: """ Lookup date modifier keyword, even if translated. """ - mods = ["none", "before", "after", "about", - "range", "span", "textonly"] - ui_mods = [_("none", "date-modifier"), - _("before"), _("after"), _("about"), - _("range"), _("span"), _("textonly")] + mods = [ + "none", + "before", + "after", + "about", + "range", + "from", + "to", + "span", + "textonly", + ] + ui_mods = [ + _("none", "date-modifier"), + _("before"), + _("after"), + _("about"), + _("range"), + _("from"), + _("to"), + _("span"), + _("textonly"), + ] if modifier.lower() in mods: return mods.index(modifier.lower()) elif modifier.lower() in ui_mods: @@ -1933,26 +2066,30 @@ class Date: year = property(get_year, set_year) + def Today(): """ Returns a Date object set to the current date. """ import time + current_date = Date() current_date.set_yr_mon_day(*time.localtime(time.time())[0:3]) return current_date + def NextYear(): """ Returns a Date object set to next year """ return Today() + 1 -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # Date Functions # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- def lookup_calendar(calendar): @@ -1962,8 +2099,10 @@ def lookup_calendar(calendar): >>> lookup_calendar("hebrew") 2 """ - if calendar is None: return Date.CAL_GREGORIAN - if isinstance(calendar, int): return calendar + if calendar is None: + return Date.CAL_GREGORIAN + if isinstance(calendar, int): + return calendar for pos, calendar_name in enumerate(Date.calendar_names): if calendar.lower() == calendar_name.lower(): return pos @@ -1972,6 +2111,7 @@ def lookup_calendar(calendar): return pos raise AttributeError("invalid calendar: '%s'" % calendar) + def gregorian(date): """Convert given date to gregorian. Doesn't modify the original object.""" if date.get_calendar() != Date.CAL_GREGORIAN: @@ -1979,6 +2119,7 @@ def gregorian(date): date.convert_calendar(Date.CAL_GREGORIAN) return date + def calendar_has_fixed_newyear(cal): """Does the given calendar have a fixed new year, or may it be reset?""" return cal not in (Date.CAL_GREGORIAN, Date.CAL_JULIAN, Date.CAL_SWEDISH) diff --git a/gramps/gen/lib/test/date_test.py b/gramps/gen/lib/test/date_test.py index 8b21454db..03a6f3359 100644 --- a/gramps/gen/lib/test/date_test.py +++ b/gramps/gen/lib/test/date_test.py @@ -21,18 +21,18 @@ """ Unittest for testing dates """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Standard python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import unittest -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from ...config import config from ...datehandler import get_date_formats, set_format from ...datehandler import parser as _dp @@ -47,21 +47,34 @@ testset = "basic test" dates = [] calendar = Date.CAL_GREGORIAN for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, Date.QUAL_CALCULATED): - for modifier in (Date.MOD_NONE, Date.MOD_BEFORE, Date.MOD_AFTER, Date.MOD_ABOUT): - for month in range(1,13): + for modifier in ( + Date.MOD_NONE, + Date.MOD_BEFORE, + Date.MOD_AFTER, + Date.MOD_ABOUT, + Date.MOD_FROM, + Date.MOD_TO, + ): + for month in range(1, 13): d = Date() - d.set(quality,modifier,calendar,(4,month,1789,False),"Text comment") - dates.append( d) + d.set(quality, modifier, calendar, (4, month, 1789, False), "Text comment") + dates.append(d) for modifier in (Date.MOD_RANGE, Date.MOD_SPAN): - for month1 in range(1,13): - for month2 in range(1,13): + for month1 in range(1, 13): + for month2 in range(1, 13): d = Date() - d.set(quality,modifier,calendar,(4,month1,1789,False,5,month2,1876,False),"Text comment") - dates.append( d) + d.set( + quality, + modifier, + calendar, + (4, month1, 1789, False, 5, month2, 1876, False), + "Text comment", + ) + dates.append(d) modifier = Date.MOD_TEXTONLY d = Date() - d.set(quality,modifier,calendar,Date.EMPTY,"This is a textual date") - dates.append( d) + d.set(quality, modifier, calendar, Date.EMPTY, "This is a textual date") + dates.append(d) date_tests[testset] = dates # incomplete dates (day or month missing) @@ -69,38 +82,93 @@ testset = "partial date" dates = [] calendar = Date.CAL_GREGORIAN for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, Date.QUAL_CALCULATED): - for modifier in (Date.MOD_NONE, Date.MOD_BEFORE, Date.MOD_AFTER, Date.MOD_ABOUT): + for modifier in ( + Date.MOD_NONE, + Date.MOD_BEFORE, + Date.MOD_AFTER, + Date.MOD_ABOUT, + Date.MOD_FROM, + Date.MOD_TO, + ): d = Date() - d.set(quality,modifier,calendar,(0,11,1789,False),"Text comment") - dates.append( d) + d.set(quality, modifier, calendar, (0, 11, 1789, False), "Text comment") + dates.append(d) d = Date() - d.set(quality,modifier,calendar,(0,0,1789,False),"Text comment") - dates.append( d) + d.set(quality, modifier, calendar, (0, 0, 1789, False), "Text comment") + dates.append(d) for modifier in (Date.MOD_RANGE, Date.MOD_SPAN): d = Date() - d.set(quality,modifier,calendar,(4,10,1789,False,0,11,1876,False),"Text comment") - dates.append( d) + d.set( + quality, + modifier, + calendar, + (4, 10, 1789, False, 0, 11, 1876, False), + "Text comment", + ) + dates.append(d) d = Date() - d.set(quality,modifier,calendar,(4,10,1789,False,0,0,1876,False),"Text comment") - dates.append( d) + d.set( + quality, + modifier, + calendar, + (4, 10, 1789, False, 0, 0, 1876, False), + "Text comment", + ) + dates.append(d) d = Date() - d.set(quality,modifier,calendar,(0,10,1789,False,5,11,1876,False),"Text comment") - dates.append( d) + d.set( + quality, + modifier, + calendar, + (0, 10, 1789, False, 5, 11, 1876, False), + "Text comment", + ) + dates.append(d) d = Date() - d.set(quality,modifier,calendar,(0,10,1789,False,0,11,1876,False),"Text comment") - dates.append( d) + d.set( + quality, + modifier, + calendar, + (0, 10, 1789, False, 0, 11, 1876, False), + "Text comment", + ) + dates.append(d) d = Date() - d.set(quality,modifier,calendar,(0,10,1789,False,0,0,1876,False),"Text comment") - dates.append( d) + d.set( + quality, + modifier, + calendar, + (0, 10, 1789, False, 0, 0, 1876, False), + "Text comment", + ) + dates.append(d) d = Date() - d.set(quality,modifier,calendar,(0,0,1789,False,5,11,1876,False),"Text comment") - dates.append( d) + d.set( + quality, + modifier, + calendar, + (0, 0, 1789, False, 5, 11, 1876, False), + "Text comment", + ) + dates.append(d) d = Date() - d.set(quality,modifier,calendar,(0,0,1789,False,0,11,1876,False),"Text comment") - dates.append( d) + d.set( + quality, + modifier, + calendar, + (0, 0, 1789, False, 0, 11, 1876, False), + "Text comment", + ) + dates.append(d) d = Date() - d.set(quality,modifier,calendar,(0,0,1789,False,0,0,1876,False),"Text comment") - dates.append( d) + d.set( + quality, + modifier, + calendar, + (0, 0, 1789, False, 0, 0, 1876, False), + "Text comment", + ) + dates.append(d) date_tests[testset] = dates # slash-dates @@ -108,21 +176,46 @@ testset = "slash-dates" dates = [] calendar = Date.CAL_GREGORIAN for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, Date.QUAL_CALCULATED): - for modifier in (Date.MOD_NONE, Date.MOD_BEFORE, Date.MOD_AFTER, Date.MOD_ABOUT): + for modifier in ( + Date.MOD_NONE, + Date.MOD_BEFORE, + Date.MOD_AFTER, + Date.MOD_ABOUT, + Date.MOD_FROM, + Date.MOD_TO, + ): # normal date d = Date() - d.set(quality,modifier,calendar,(4,11,1789,True),"Text comment") - dates.append( d) + d.set(quality, modifier, calendar, (4, 11, 1789, True), "Text comment") + dates.append(d) for modifier in (Date.MOD_RANGE, Date.MOD_SPAN): d = Date() - d.set(quality,modifier,calendar,(4,11,1789,True,5,10,1876,False),"Text comment") - dates.append( d) + d.set( + quality, + modifier, + calendar, + (4, 11, 1789, True, 5, 10, 1876, False), + "Text comment", + ) + dates.append(d) d = Date() - d.set(quality,modifier,calendar,(4,11,1789,False,5,10,1876,True),"Text comment") - dates.append( d) + d.set( + quality, + modifier, + calendar, + (4, 11, 1789, False, 5, 10, 1876, True), + "Text comment", + ) + dates.append(d) d = Date() - d.set(quality,modifier,calendar,(4,11,1789,True,5,10,1876,True),"Text comment") - dates.append( d) + d.set( + quality, + modifier, + calendar, + (4, 11, 1789, True, 5, 10, 1876, True), + "Text comment", + ) + dates.append(d) date_tests[testset] = dates # BCE @@ -130,74 +223,116 @@ testset = "B. C. E." dates = [] calendar = Date.CAL_GREGORIAN for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, Date.QUAL_CALCULATED): - for modifier in (Date.MOD_NONE, Date.MOD_BEFORE, Date.MOD_AFTER, Date.MOD_ABOUT): + for modifier in ( + Date.MOD_NONE, + Date.MOD_BEFORE, + Date.MOD_AFTER, + Date.MOD_ABOUT, + Date.MOD_FROM, + Date.MOD_TO, + ): # normal date d = Date() - d.set(quality,modifier,calendar,(4,11,-90,False),"Text comment") - dates.append( d) + d.set(quality, modifier, calendar, (4, 11, -90, False), "Text comment") + dates.append(d) for modifier in (Date.MOD_RANGE, Date.MOD_SPAN): d = Date() - d.set(quality,modifier,calendar,(5,10,-90,False,4,11,-90,False),"Text comment") - dates.append( d) - d = Date() + d.set( + quality, + modifier, + calendar, + (5, 10, -90, False, 4, 11, -90, False), + "Text comment", + ) + dates.append(d) date_tests[testset] = dates # test for all other different calendars testset = "Non-gregorian" dates = [] -for calendar in (Date.CAL_JULIAN, - Date.CAL_HEBREW, - Date.CAL_ISLAMIC, - Date.CAL_FRENCH, - Date.CAL_PERSIAN, - ): +for calendar in ( + Date.CAL_JULIAN, + Date.CAL_HEBREW, + Date.CAL_ISLAMIC, + Date.CAL_FRENCH, + Date.CAL_PERSIAN, +): for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, Date.QUAL_CALCULATED): - for modifier in (Date.MOD_NONE, Date.MOD_BEFORE, Date.MOD_AFTER, Date.MOD_ABOUT): + for modifier in ( + Date.MOD_NONE, + Date.MOD_BEFORE, + Date.MOD_AFTER, + Date.MOD_ABOUT, + Date.MOD_FROM, + Date.MOD_TO, + ): d = Date() - d.set(quality,modifier,calendar,(4,11,1789,False),"Text comment") - dates.append( d) + d.set(quality, modifier, calendar, (4, 11, 1789, False), "Text comment") + dates.append(d) for modifier in (Date.MOD_RANGE, Date.MOD_SPAN): d = Date() - d.set(quality,modifier,calendar,(4,10,1789,False,5,11,1876,False),"Text comment") - dates.append( d) + d.set( + quality, + modifier, + calendar, + (4, 10, 1789, False, 5, 11, 1876, False), + "Text comment", + ) + dates.append(d) # CAL_SWEDISH - Swedish calendar 1700-03-01 -> 1712-02-30! class Context: def __init__(self, retval): self.retval = retval + def __enter__(self): return self.retval + def __exit__(self, *args, **kwargs): pass + with Context(Date.CAL_SWEDISH) as calendar: for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, Date.QUAL_CALCULATED): - for modifier in (Date.MOD_NONE, Date.MOD_BEFORE, Date.MOD_AFTER, Date.MOD_ABOUT): + for modifier in ( + Date.MOD_NONE, + Date.MOD_BEFORE, + Date.MOD_AFTER, + Date.MOD_ABOUT, + Date.MOD_FROM, + Date.MOD_TO, + ): d = Date() - d.set(quality,modifier,calendar,(4,11,1700,False),"Text comment") - dates.append( d) + d.set(quality, modifier, calendar, (4, 11, 1700, False), "Text comment") + dates.append(d) for modifier in (Date.MOD_RANGE, Date.MOD_SPAN): d = Date() - d.set(quality,modifier,calendar,(4,10,1701,False, - 5,11,1702,False),"Text comment") - dates.append( d) + d.set( + quality, + modifier, + calendar, + (4, 10, 1701, False, 5, 11, 1702, False), + "Text comment", + ) + dates.append(d) quality = Date.QUAL_NONE modifier = Date.MOD_NONE -for calendar in (Date.CAL_JULIAN, - Date.CAL_ISLAMIC, - Date.CAL_PERSIAN, - ): - for month in range(1,13): +for calendar in ( + Date.CAL_JULIAN, + Date.CAL_ISLAMIC, + Date.CAL_PERSIAN, +): + for month in range(1, 13): d = Date() - d.set(quality,modifier,calendar,(4,month,1789,False),"Text comment") - dates.append( d) + d.set(quality, modifier, calendar, (4, month, 1789, False), "Text comment") + dates.append(d) for calendar in (Date.CAL_HEBREW, Date.CAL_FRENCH): - for month in range(1,14): + for month in range(1, 14): d = Date() - d.set(quality,modifier,calendar,(4,month,1789,False),"Text comment") - dates.append( d) + d.set(quality, modifier, calendar, (4, month, 1789, False), "Text comment") + dates.append(d) date_tests[testset] = dates @@ -205,35 +340,37 @@ swedish_dates = [] # CAL_SWEDISH - Swedish calendar 1700-03-01 -> 1712-02-30! with Context(Date.CAL_SWEDISH) as calendar: for year in range(1701, 1712): - for month in range(1,13): + for month in range(1, 13): d = Date() - d.set(quality,modifier,calendar,(4,month,year,False),"Text comment") - swedish_dates.append( d) + d.set(quality, modifier, calendar, (4, month, year, False), "Text comment") + swedish_dates.append(d) -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # BaseDateTest # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class BaseDateTest(unittest.TestCase): """ Base class for all date tests. """ + def setUp(self): - config.set('behavior.date-before-range', 9999) - config.set('behavior.date-after-range', 9999) - config.set('behavior.date-about-range', 10) + config.set("behavior.date-before-range", 9999) + config.set("behavior.date-after-range", 9999) + config.set("behavior.date-about-range", 10) -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # ParserDateTest # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class ParserDateTest(BaseDateTest): """ Date displayer and parser tests. """ + def do_case(self, testset): for index, date_format in enumerate(get_date_formats()): set_format(index) @@ -241,12 +378,13 @@ class ParserDateTest(BaseDateTest): for dateval in date_tests[testset]: datestr = _dd.display(dateval) ndate = _dp.parse(datestr) - self.assertTrue(dateval.is_equal(ndate), - "dateval fails is_equal in format %d:\n" - " '%s' != '%s'\n" - " '%s' != '%s'\n" % - (index, dateval, ndate, - dateval.__dict__, ndate.__dict__)) + self.assertTrue( + dateval.is_equal(ndate), + "dateval fails is_equal in format %d:\n" + " '%s' != '%s'\n" + " '%s' != '%s'\n" + % (index, dateval, ndate, dateval.__dict__, ndate.__dict__), + ) def test_basic(self): self.do_case("basic test") @@ -264,103 +402,117 @@ class ParserDateTest(BaseDateTest): self.do_case("Non-gregorian") -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # MatchDateTest # -#------------------------------------------------------------------------- -ENGLISH_DATE_HANDLER = (_dd.__class__ == DateDisplayEn) -@unittest.skipUnless(ENGLISH_DATE_HANDLER, - "This test of Date() matching logic can only run in English locale.") +# ------------------------------------------------------------------------- +ENGLISH_DATE_HANDLER = _dd.__class__ == DateDisplayEn + + +@unittest.skipUnless( + ENGLISH_DATE_HANDLER, + "This test of Date() matching logic can only run in English locale.", +) class MatchDateTest(BaseDateTest): """ Date match tests. """ - tests = [("before 1960", "before 1961", True), - ("before 1960", "before 1960", True), - ("before 1961", "before 1961", True), - ("jan 1, 1960", "jan 1, 1960", True), - ("dec 31, 1959", "dec 31, 1959", True), - ("before 1960", "jan 1, 1960", False), - ("before 1960", "dec 31, 1959", True), - ("abt 1960", "1960", True), - ("abt 1960", "before 1960", True), - ("1960", "1960", True), - ("1960", "after 1960", False), - ("1960", "before 1960", False), - ("abt 1960", "abt 1960", True), - ("before 1960", "after 1960", False), - ("after jan 1, 1900", "jan 2, 1900", True), - ("abt jan 1, 1900", "jan 1, 1900", True), - ("from 1950 to 1955", "1950", True), - ("from 1950 to 1955", "1951", True), - ("from 1950 to 1955", "1952", True), - ("from 1950 to 1955", "1953", True), - ("from 1950 to 1955", "1954", True), - ("from 1950 to 1955", "1955", True), - ("from 1950 to 1955", "1956", False), - ("from 1950 to 1955", "dec 31, 1955", True), - ("from 1950 to 1955", "jan 1, 1955", True), - ("from 1950 to 1955", "dec 31, 1949", False), - ("from 1950 to 1955", "jan 1, 1956", False), - ("after jul 4, 1980", "jul 4, 1980", False), - ("after jul 4, 1980", "before jul 4, 1980", False), - ("after jul 4, 1980", "about jul 4, 1980", True), - ("after jul 4, 1980", "after jul 4, 1980", True), - ("between 1750 and 1752", "1750", True), - ("between 1750 and 1752", "about 1750", True), - ("between 1750 and 1752", "between 1749 and 1750", True), - ("between 1750 and 1752", "1749", False), - ("invalid date", "invalid date", True), - ("invalid date", "invalid", False, True), - ("invalid date 1", "invalid date 2", False), - ("abt jan 1, 2000", "dec 31, 1999", True), - ("jan 1, 2000", "dec 31, 1999", False), - ("aft jan 1, 2000", "dec 31, 1999", False), - ("after jan 1, 2000", "after dec 31, 1999", True), - ("after dec 31, 1999", "after jan 1, 2000", True), - ("1 31, 2000", "jan 1, 2000", False), - ("dec 31, 1999", "jan 1, 2000", False), - ("jan 1, 2000", "before dec 31, 1999", False), - ("aft jan 1, 2000", "before dec 31, 1999", False), - ("before jan 1, 2000", "after dec 31, 1999", False), - ("jan 1, 2000/1", "jan 1, 2000", False), - ("jan 1, 2000/1", "jan 1, 2001", False), - ("jan 1, 2000/1", "jan 1, 2000/1", True), - ("jan 1, 2000/1", "jan 14, 2001", True), - ("jan 1, 2000/1", "jan 1, 2001 (julian)", True), - ("about 1984", "about 2005", False), - ("about 1990", "about 2005", True), - ("about 2007", "about 2006", True), - ("about 1995", "after 2000", True), - ("about 1995", "after 2005", False), - ("about 2007", "about 2003", True), - ("before 2007", "2000", True), - # offsets - # different calendar, same date - ("1800-8-3", "15 Thermidor 8 (French Republican)", True), - ("after 1800-8-3", "before 15 Thermidor 8 (French Republican)", False), - ("ab cd", "54 ab cd 2000", True, False), - ("1700-02-29 (Julian)", "1700-03-01 (Swedish)", True), - ("1706-12-31 (Julian)", "1707-01-01 (Swedish)", True), - ("1712-02-28 (Julian)", "1712-02-29 (Swedish)", True), - ("1712-02-29 (Julian)", "1712-02-30 (Swedish)", True), - # See bug# 7100 - ("1233-12-01", "1234-12-01 (Mar25)", True), - ("1234-01-04", "1234-01-04 (Mar25)", True), - # See bug# 7158 -# Some issues passing Travis close to midnight; not sure why: -# ("today", Today(), True), -# ("today (Hebrew)", Today(), True), - ("today", "today", True), - (Today(), Today(), True), - # See bug# 7197 - ("1788-03-27", "1789-03-27 (Mar25)", True), - ("1788-03-27 (Julian)", "1789-03-27 (Julian, Mar25)", True), - ] + + tests = [ + ("before 1960", "before 1961", True), + ("before 1960", "before 1960", True), + ("before 1961", "before 1961", True), + ("jan 1, 1960", "jan 1, 1960", True), + ("dec 31, 1959", "dec 31, 1959", True), + ("before 1960", "jan 1, 1960", False), + ("before 1960", "dec 31, 1959", True), + ("abt 1960", "1960", True), + ("abt 1960", "before 1960", True), + ("1960", "1960", True), + ("1960", "after 1960", False), + ("1960", "before 1960", False), + ("abt 1960", "abt 1960", True), + ("before 1960", "after 1960", False), + ("after jan 1, 1900", "jan 2, 1900", True), + ("abt jan 1, 1900", "jan 1, 1900", True), + ("from 1950 to 1955", "1950", True), + ("from 1950 to 1955", "1951", True), + ("from 1950 to 1955", "1952", True), + ("from 1950 to 1955", "1953", True), + ("from 1950 to 1955", "1954", True), + ("from 1950 to 1955", "1955", True), + ("from 1950 to 1955", "1956", False), + ("from 1950 to 1955", "dec 31, 1955", True), + ("from 1950 to 1955", "jan 1, 1955", True), + ("from 1950 to 1955", "dec 31, 1949", False), + ("from 1950 to 1955", "jan 1, 1956", False), + ("from 1950", "1940", False), + ("from 1950", "2000", True), + ("from 1950", "jan 1, 1950", True), + ("from 1950", "dec 31, 1949", False), + ("to 1950", "1940", True), + ("to 1950", "2000", False), + ("to 1950", "dec 31, 1950", True), + ("to 1950", "jan 1, 1951", False), + ("after jul 4, 1980", "jul 4, 1980", False), + ("after jul 4, 1980", "before jul 4, 1980", False), + ("after jul 4, 1980", "about jul 4, 1980", True), + ("after jul 4, 1980", "after jul 4, 1980", True), + ("between 1750 and 1752", "1750", True), + ("between 1750 and 1752", "about 1750", True), + ("between 1750 and 1752", "between 1749 and 1750", True), + ("between 1750 and 1752", "1749", False), + ("invalid date", "invalid date", True), + ("invalid date", "invalid", False, True), + ("invalid date 1", "invalid date 2", False), + ("abt jan 1, 2000", "dec 31, 1999", True), + ("jan 1, 2000", "dec 31, 1999", False), + ("aft jan 1, 2000", "dec 31, 1999", False), + ("after jan 1, 2000", "after dec 31, 1999", True), + ("after dec 31, 1999", "after jan 1, 2000", True), + ("1 31, 2000", "jan 1, 2000", False), + ("dec 31, 1999", "jan 1, 2000", False), + ("jan 1, 2000", "before dec 31, 1999", False), + ("aft jan 1, 2000", "before dec 31, 1999", False), + ("before jan 1, 2000", "after dec 31, 1999", False), + ("jan 1, 2000/1", "jan 1, 2000", False), + ("jan 1, 2000/1", "jan 1, 2001", False), + ("jan 1, 2000/1", "jan 1, 2000/1", True), + ("jan 1, 2000/1", "jan 14, 2001", True), + ("jan 1, 2000/1", "jan 1, 2001 (julian)", True), + ("about 1984", "about 2005", False), + ("about 1990", "about 2005", True), + ("about 2007", "about 2006", True), + ("about 1995", "after 2000", True), + ("about 1995", "after 2005", False), + ("about 2007", "about 2003", True), + ("before 2007", "2000", True), + # offsets + # different calendar, same date + ("1800-8-3", "15 Thermidor 8 (French Republican)", True), + ("after 1800-8-3", "before 15 Thermidor 8 (French Republican)", False), + ("ab cd", "54 ab cd 2000", True, False), + ("1700-02-29 (Julian)", "1700-03-01 (Swedish)", True), + ("1706-12-31 (Julian)", "1707-01-01 (Swedish)", True), + ("1712-02-28 (Julian)", "1712-02-29 (Swedish)", True), + ("1712-02-29 (Julian)", "1712-02-30 (Swedish)", True), + # See bug# 7100 + ("1233-12-01", "1234-12-01 (Mar25)", True), + ("1234-01-04", "1234-01-04 (Mar25)", True), + # See bug# 7158 + # Some issues passing Travis close to midnight; not sure why: + # ("today", Today(), True), + # ("today (Hebrew)", Today(), True), + ("today", "today", True), + (Today(), Today(), True), + # See bug# 7197 + ("1788-03-27", "1789-03-27 (Mar25)", True), + ("1788-03-27 (Julian)", "1789-03-27 (Julian, Mar25)", True), + ] def convert_to_date(self, d): - return d if isinstance(d,Date) else _dp.parse(d) + return d if isinstance(d, Date) else _dp.parse(d) def do_case(self, d1, d2, expected1, expected2=None): """ @@ -376,27 +528,33 @@ class MatchDateTest(BaseDateTest): date1 = self.convert_to_date(d1) date2 = self.convert_to_date(d2) result = date2.match(date1) - self.assertEqual(result, expected, - "'{}' {} '{}'\n({} vs {})".format( - d1, - ("did not match" if expected else "matched"), - d2, - date1.__dict__, date2.__dict__)) + self.assertEqual( + result, + expected, + "'{}' {} '{}'\n({} vs {})".format( + d1, + ("did not match" if expected else "matched"), + d2, + date1.__dict__, + date2.__dict__, + ), + ) def test_match(self): for testdata in self.tests: self.do_case(*testdata) -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # ArithmeticDateTest # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class ArithmeticDateTest(BaseDateTest): """ Date arithmetic tests. """ + tests = [ # Date +/- int/tuple -> Date ("Date(2008, 1, 1) - 1", "Date(2007, 1, 1)"), @@ -411,7 +569,7 @@ class ArithmeticDateTest(BaseDateTest): ("Date(2008, 1, 1) + (0, 0, 32)", "Date(2008, 2, 2)"), ("Date(2008, 2, 1) + (0, 0, 32)", "Date(2008, 3, 4)"), ("Date(2000) - (0, 1, 0)", "Date(1999, 12, 1)"), - ("Date(2000) + (0, 1, 0)", "Date(2000, 1, 0)"), # Ok? + ("Date(2000) + (0, 1, 0)", "Date(2000, 1, 0)"), # Ok? ("Date(2000, 1, 1) - (0, 1, 0)", "Date(1999, 12, 1)"), ("Date(2000, 1, 1) - 1", "Date(1999, 1, 1)"), ("Date(2000) - 1", "Date(1999)"), @@ -423,28 +581,33 @@ class ArithmeticDateTest(BaseDateTest): ("(Date(2000,1,1) - Date(1999,12,1)).tuple()", "(0, 1, 0)"), ("(Date(2007, 12, 23) - Date(1963, 12, 4)).tuple()", "(44, 0, 19)"), ("(Date(1963, 12, 4) - Date(2007, 12, 23)).tuple()", "(-44, 0, -19)"), - ] + ] def test_evaluate(self): for exp1, exp2 in self.tests: val1 = eval(exp1) val2 = eval(exp2) - self.assertEqual(val1, val2, - "'%s' should be '%s' but was '%s'" % (exp1, val2, val1)) + self.assertEqual( + val1, val2, "'%s' should be '%s' but was '%s'" % (exp1, val2, val1) + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # SpanTest # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class SpanTest(BaseDateTest): """ Test spans. """ - tests = [((2000, 1, 31), (2000, 1, 1), 30), - ((1799, 11, 19), (8, 2, 18, Date.CAL_FRENCH), 10), - ((8, 2, 18, Date.CAL_FRENCH), (1799, 11, 4), 5), - ((8, 2, 18, Date.CAL_FRENCH), (3, 2, 9, Date.CAL_FRENCH), 1836)] + + tests = [ + ((2000, 1, 31), (2000, 1, 1), 30), + ((1799, 11, 19), (8, 2, 18, Date.CAL_FRENCH), 10), + ((8, 2, 18, Date.CAL_FRENCH), (1799, 11, 4), 5), + ((8, 2, 18, Date.CAL_FRENCH), (3, 2, 9, Date.CAL_FRENCH), 1836), + ] def test_evaluate(self): for value1, value2, duration in self.tests: @@ -462,146 +625,613 @@ class SpanTest(BaseDateTest): date.set_yr_mon_day(value[0], value[1], value[2]) return date -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- +# +# DateComparisonTest +# +# ------------------------------------------------------------------------- +@unittest.skipUnless( + ENGLISH_DATE_HANDLER, + "This test of Date() matching logic can only run in English locale.", +) +class DateComparisonTest(BaseDateTest): + """ + Date comparison tests. + """ + + tests = [ + ("1960", "=", "1960", True), + ("1960", "=", "1961", False), + ("1960", "!=", "1960", False), + ("1960", "!=", "1961", True), + ("1960", "==", "1960", True), + ("1960", "==", "1961", False), + ("1960", "<", "1959", False), + ("1960", "<", "1960", True), + ("1960", "<", "1961", True), + ("1960", ">", "1959", True), + ("1960", ">", "1960", True), + ("1960", ">", "1961", False), + ("1960", "<<", "1959", False), + ("1960", "<<", "1960", False), + ("1960", "<<", "1961", True), + ("1960", ">>", "1959", True), + ("1960", ">>", "1960", False), + ("1960", ">>", "1961", False), + ("1960", "<=", "1959", False), + ("1960", "<=", "1960", True), + ("1960", "<=", "1961", True), + ("1960", ">=", "1959", True), + ("1960", ">=", "1960", True), + ("1960", ">=", "1961", False), + ("1960-01-01", "=", "1960-01-01", True), + ("1960-01-01", "=", "1960-01-02", False), + ("1960-01-01", "!=", "1960-01-01", False), + ("1960-01-01", "!=", "1960-01-02", True), + ("1960-01-01", "==", "1960-01-01", True), + ("1960-01-01", "==", "1960-01-02", False), + ("1960-01-01", "<", "1959-12-31", False), + ("1960-01-01", "<", "1960-01-01", False), + ("1960-01-01", "<", "1960-01-02", True), + ("1960-01-01", ">", "1959-12-31", True), + ("1960-01-01", ">", "1960-01-01", False), + ("1960-01-01", ">", "1960-01-02", False), + ("1960-01-01", "<<", "1959-12-31", False), + ("1960-01-01", "<<", "1960-01-01", False), + ("1960-01-01", "<<", "1960-01-02", True), + ("1960-01-01", ">>", "1959-12-31", True), + ("1960-01-01", ">>", "1960-01-01", False), + ("1960-01-01", ">>", "1960-01-02", False), + ("before 1960-01-01", "=", "1959-12-31", True), + ("before 1960-01-01", "=", "1960-01-01", False), + ("about 1960-01-01", "=", "1959-12-31", True), + ("about 1960-01-01", "=", "1960-01-01", True), + ("about 1960-01-01", "=", "1960-01-02", True), + ("after 1960-01-01", "=", "1960-01-01", False), + ("after 1960-01-01", "=", "1960-01-02", True), + ("between 1960-01-01 and 1960-01-03", "=", "1959-12-31", False), + ("between 1960-01-01 and 1960-01-03", "=", "1960-01-01", True), + ("between 1960-01-01 and 1960-01-03", "=", "1960-01-02", True), + ("between 1960-01-01 and 1960-01-03", "=", "1960-01-02", True), + ("between 1960-01-01 and 1960-01-03", "=", "1960-01-04", False), + ("before 1960-01-01", "==", "1959-12-31", False), # ! + ("before 1960-01-01", "==", "1960-01-01", True), # ! + ("before 1960-01-01", "==", "1960-01-02", False), # ! + ("about 1960-01-01", "==", "1959-12-31", False), # ! + ("about 1960-01-01", "==", "1960-01-01", True), + ("about 1960-01-01", "==", "1960-01-02", False), # ! + ("after 1960-01-01", "==", "1960-01-01", True), # ! + ("after 1960-01-01", "==", "1960-01-02", False), # ! + ("between 1960-01-01 and 1960-01-03", "==", "1959-12-31", False), + ("between 1960-01-01 and 1960-01-03", "==", "1960-01-01", True), + ("between 1960-01-01 and 1960-01-03", "==", "1960-01-02", False), + ("between 1960-01-01 and 1960-01-03", "==", "1960-01-02", False), + ("between 1960-01-01 and 1960-01-03", "==", "1960-01-04", False), + ( + "4713-01-01 B.C. (Julian)", + "=", + "to 1960", + False, + ), # Corner case, logically True. + ("4713-01-02 B.C. (Julian)", "=", "to 1960", True), + ("4713-01-02 B.C. (Julian)", "<", "to 1960", True), + ("4713-01-02 B.C. (Julian)", "<=", "to 1960", True), + ("4713-01-02 B.C. (Julian)", "<<", "to 1960", False), + ("from 1960", "=", "from 1960", True), + ("from 1960", "=", "from 1961", True), + ("from 1960", "!=", "from 1960", False), + ("from 1960", "!=", "from 1961", True), + ("from 1960", "==", "from 1960", True), + ("from 1960", "==", "from 1961", False), + ("from 1960", "<", "from 1959", True), + ("from 1960", "<", "from 1960", True), + ("from 1960", "<", "from 1961", True), + ("from 1960", ">", "from 1959", True), + ("from 1960", ">", "from 1960", True), + ("from 1960", ">", "from 1961", True), + ("from 1960", "<<", "from 1959", False), + ("from 1960", "<<", "from 1960", False), + ("from 1960", "<<", "from 1961", False), + ("from 1960", ">>", "from 1959", False), + ("from 1960", ">>", "from 1960", False), + ("from 1960", ">>", "from 1961", False), + ("from 1960", "<=", "from 1959", False), + ("from 1960", "<=", "from 1960", True), + ("from 1960", "<=", "from 1961", True), + ("from 1960", ">=", "from 1959", True), + ("from 1960", ">=", "from 1960", True), + ("from 1960", ">=", "from 1961", False), + ("from 1960", "=", "to 1959", False), + ("from 1960", "=", "to 1960", True), + ("from 1960", "=", "to 1961", True), + ("from 1960", "!=", "to 1959", True), + ("from 1960", "!=", "to 1960", False), + ("from 1960", "!=", "to 1961", True), + ("from 1960", "==", "to 1959", False), + ("from 1960", "==", "to 1960", True), + ("from 1960", "==", "to 1961", False), + ("from 1960", "<", "to 1959", False), + ("from 1960", "<", "to 1960", True), + ("from 1960", "<", "to 1961", True), + ("from 1960", ">", "to 1959", True), + ("from 1960", ">", "to 1960", True), + ("from 1960", ">", "to 1961", True), + ("from 1960", "<<", "to 1959", False), + ("from 1960", "<<", "to 1960", False), + ("from 1960", "<<", "to 1961", False), + ("from 1960", ">>", "to 1959", True), + ("from 1960", ">>", "to 1960", False), + ("from 1960", ">>", "to 1961", False), + ("from 1960", "<=", "to 1959", False), + ("from 1960", "<=", "to 1960", True), + ("from 1960", "<=", "to 1961", True), + ("from 1960", ">=", "to 1959", True), + ("from 1960", ">=", "to 1960", True), + ("from 1960", ">=", "to 1961", False), + ("to 1960", "=", "from 1959", True), + ("to 1960", "=", "from 1960", True), + ("to 1960", "=", "from 1961", False), + ("to 1960", "!=", "from 1959", True), + ("to 1960", "!=", "from 1960", False), + ("to 1960", "!=", "from 1961", True), + ("to 1960", "==", "from 1959", False), + ("to 1960", "==", "from 1960", True), + ("to 1960", "==", "from 1961", False), + ("to 1960", "<", "from 1959", True), + ("to 1960", "<", "from 1960", True), + ("to 1960", "<", "from 1961", True), + ("to 1960", ">", "from 1959", True), + ("to 1960", ">", "from 1960", True), + ("to 1960", ">", "from 1961", False), + ("to 1960", "<<", "from 1959", False), + ("to 1960", "<<", "from 1960", False), + ("to 1960", "<<", "from 1961", True), + ("to 1960", ">>", "from 1959", False), + ("to 1960", ">>", "from 1960", False), + ("to 1960", ">>", "from 1961", False), + ("to 1960", "<=", "from 1959", False), + ("to 1960", "<=", "from 1960", True), + ("to 1960", "<=", "from 1961", True), + ("to 1960", ">=", "from 1959", True), + ("to 1960", ">=", "from 1960", True), + ("to 1960", ">=", "from 1961", False), + ("to 1960", "=", "to 1959", True), + ("to 1960", "=", "to 1960", True), + ("to 1960", "=", "to 1961", True), + ("to 1960", "!=", "to 1959", True), + ("to 1960", "!=", "to 1960", False), + ("to 1960", "!=", "to 1961", True), + ("to 1960", "==", "to 1959", False), + ("to 1960", "==", "to 1960", True), + ("to 1960", "==", "to 1961", False), + ("to 1960", "<", "to 1959", True), + ("to 1960", "<", "to 1960", True), + ("to 1960", "<", "to 1961", True), + ("to 1960", ">", "to 1959", True), + ("to 1960", ">", "to 1960", True), + ("to 1960", ">", "to 1961", True), + ("to 1960", "<<", "to 1959", False), + ("to 1960", "<<", "to 1960", False), + ("to 1960", "<<", "to 1961", False), + ("to 1960", ">>", "to 1959", False), + ("to 1960", ">>", "to 1960", False), + ("to 1960", ">>", "to 1961", False), + ("to 1960", "<=", "to 1959", False), + ("to 1960", "<=", "to 1960", True), + ("to 1960", "<=", "to 1961", True), + ("to 1960", ">=", "to 1959", True), + ("to 1960", ">=", "to 1960", True), + ("to 1960", ">=", "to 1961", False), + ("from 1960 to 1961", "=", "from 1958 to 1959", False), + ("from 1960 to 1961", "=", "from 1959 to 1960", True), + ("from 1960 to 1961", "=", "from 1960 to 1961", True), + ("from 1960 to 1961", "=", "from 1961 to 1962", True), + ("from 1960 to 1961", "=", "from 1962 to 1963", False), + ("from 1960 to 1961", "!=", "from 1958 to 1959", True), + ("from 1960 to 1961", "!=", "from 1959 to 1960", True), + ("from 1960 to 1961", "!=", "from 1960 to 1961", False), + ("from 1960 to 1961", "!=", "from 1961 to 1962", True), + ("from 1960 to 1961", "!=", "from 1962 to 1963", True), + ("from 1960 to 1961", "==", "from 1959 to 1960", False), + ("from 1960 to 1961", "==", "from 1960 to 1961", True), + ("from 1960 to 1961", "==", "from 1961 to 1962", False), + ("from 1960 to 1961", "<", "from 1958 to 1959", False), + ("from 1960 to 1961", "<", "from 1959 to 1960", True), + ("from 1960 to 1961", "<", "from 1960 to 1961", True), + ("from 1960 to 1961", "<", "from 1961 to 1962", True), + ("from 1960 to 1961", "<", "from 1962 to 1963", True), + ("from 1960 to 1961", ">", "from 1958 to 1959", True), + ("from 1960 to 1961", ">", "from 1959 to 1960", True), + ("from 1960 to 1961", ">", "from 1960 to 1961", True), + ("from 1960 to 1961", ">", "from 1961 to 1962", True), + ("from 1960 to 1961", ">", "from 1962 to 1963", False), + ("from 1960 to 1961", "<<", "from 1958 to 1959", False), + ("from 1960 to 1961", "<<", "from 1959 to 1960", False), + ("from 1960 to 1961", "<<", "from 1960 to 1961", False), + ("from 1960 to 1961", "<<", "from 1961 to 1962", False), + ("from 1960 to 1961", "<<", "from 1962 to 1963", True), + ("from 1960 to 1961", ">>", "from 1958 to 1959", True), + ("from 1960 to 1961", ">>", "from 1959 to 1960", False), + ("from 1960 to 1961", ">>", "from 1960 to 1961", False), + ("from 1960 to 1961", ">>", "from 1961 to 1962", False), + ("from 1960 to 1961", ">>", "from 1962 to 1963", False), + ("from 1960 to 1961", "<=", "from 1958 to 1959", False), + ("from 1960 to 1961", "<=", "from 1959 to 1960", False), + ("from 1960 to 1961", "<=", "from 1960 to 1961", True), + ("from 1960 to 1961", "<=", "from 1961 to 1962", True), + ("from 1960 to 1961", "<=", "from 1962 to 1963", True), + ("from 1960 to 1961", ">=", "from 1958 to 1959", True), + ("from 1960 to 1961", ">=", "from 1959 to 1960", True), + ("from 1960 to 1961", ">=", "from 1960 to 1961", True), + ("from 1960 to 1961", ">=", "from 1961 to 1962", False), + ("from 1960 to 1961", ">=", "from 1962 to 1963", False), + ("from 1960-01-01 to 1961-01-01", "=", "from 1958-01-01 to 1959-12-31", False), + ("from 1960-01-01 to 1961-01-01", "=", "from 1958-01-01 to 1960-01-01", True), + ("from 1960-01-01 to 1961-01-01", "=", "from 1958-01-01 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", "=", "from 1958-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "=", "from 1960-01-01 to 1960-12-31", True), + ("from 1960-01-01 to 1961-01-01", "=", "from 1960-01-01 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", "=", "from 1960-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "=", "from 1960-12-31 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", "=", "from 1960-12-31 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "=", "from 1961-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "=", "from 1961-01-02 to 1961-01-03", False), + ("from 1960-01-01 to 1961-01-01", "!=", "from 1958-01-01 to 1959-12-31", True), + ("from 1960-01-01 to 1961-01-01", "!=", "from 1958-01-01 to 1960-01-01", True), + ("from 1960-01-01 to 1961-01-01", "!=", "from 1958-01-01 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", "!=", "from 1958-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "!=", "from 1960-01-01 to 1960-12-31", False), + ("from 1960-01-01 to 1961-01-01", "!=", "from 1960-01-01 to 1961-01-01", False), + ("from 1960-01-01 to 1961-01-01", "!=", "from 1960-01-01 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", "!=", "from 1960-12-31 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", "!=", "from 1960-12-31 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "!=", "from 1961-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "!=", "from 1961-01-02 to 1961-01-03", True), + ("from 1960-01-01 to 1961-01-01", "==", "from 1958-01-01 to 1959-12-31", False), + ("from 1960-01-01 to 1961-01-01", "==", "from 1958-01-01 to 1960-01-01", False), + ("from 1960-01-01 to 1961-01-01", "==", "from 1958-01-01 to 1961-01-01", False), + ("from 1960-01-01 to 1961-01-01", "==", "from 1958-01-01 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", "==", "from 1960-01-01 to 1960-12-31", True), + ("from 1960-01-01 to 1961-01-01", "==", "from 1960-01-01 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", "==", "from 1960-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "==", "from 1960-12-31 to 1961-01-01", False), + ("from 1960-01-01 to 1961-01-01", "==", "from 1960-12-31 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", "==", "from 1961-01-01 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", "==", "from 1961-01-02 to 1961-01-03", False), + ("from 1960-01-01 to 1961-01-01", "<", "from 1958-01-01 to 1959-12-31", False), + ("from 1960-01-01 to 1961-01-01", "<", "from 1958-01-01 to 1960-01-01", False), + ("from 1960-01-01 to 1961-01-01", "<", "from 1958-01-01 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", "<", "from 1958-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "<", "from 1960-01-01 to 1960-12-31", True), + ("from 1960-01-01 to 1961-01-01", "<", "from 1960-01-01 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", "<", "from 1960-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "<", "from 1960-12-31 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", "<", "from 1960-12-31 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "<", "from 1961-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "<", "from 1961-01-02 to 1961-01-03", True), + ("from 1960-01-01 to 1961-01-01", ">", "from 1958-01-01 to 1959-12-31", True), + ("from 1960-01-01 to 1961-01-01", ">", "from 1958-01-01 to 1960-01-01", True), + ("from 1960-01-01 to 1961-01-01", ">", "from 1958-01-01 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", ">", "from 1958-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", ">", "from 1960-01-01 to 1960-12-31", True), + ("from 1960-01-01 to 1961-01-01", ">", "from 1960-01-01 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", ">", "from 1960-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", ">", "from 1960-12-31 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", ">", "from 1960-12-31 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", ">", "from 1961-01-01 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", ">", "from 1961-01-02 to 1961-01-03", False), + ("from 1960-01-01 to 1961-01-01", "<<", "from 1958-01-01 to 1959-12-31", False), + ("from 1960-01-01 to 1961-01-01", "<<", "from 1958-01-01 to 1960-01-01", False), + ("from 1960-01-01 to 1961-01-01", "<<", "from 1958-01-01 to 1961-01-01", False), + ("from 1960-01-01 to 1961-01-01", "<<", "from 1958-01-01 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", "<<", "from 1960-01-01 to 1960-12-31", False), + ("from 1960-01-01 to 1961-01-01", "<<", "from 1960-01-01 to 1961-01-01", False), + ("from 1960-01-01 to 1961-01-01", "<<", "from 1960-01-01 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", "<<", "from 1960-12-31 to 1961-01-01", False), + ("from 1960-01-01 to 1961-01-01", "<<", "from 1960-12-31 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", "<<", "from 1961-01-01 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", "<<", "from 1961-01-02 to 1961-01-03", True), + ("from 1960-01-01 to 1961-01-01", ">>", "from 1958-01-01 to 1959-12-31", True), + ("from 1960-01-01 to 1961-01-01", ">>", "from 1958-01-01 to 1960-01-01", False), + ("from 1960-01-01 to 1961-01-01", ">>", "from 1958-01-01 to 1961-01-01", False), + ("from 1960-01-01 to 1961-01-01", ">>", "from 1958-01-01 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", ">>", "from 1960-01-01 to 1960-12-31", False), + ("from 1960-01-01 to 1961-01-01", ">>", "from 1960-01-01 to 1961-01-01", False), + ("from 1960-01-01 to 1961-01-01", ">>", "from 1960-01-01 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", ">>", "from 1960-12-31 to 1961-01-01", False), + ("from 1960-01-01 to 1961-01-01", ">>", "from 1960-12-31 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", ">>", "from 1961-01-01 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", ">>", "from 1961-01-02 to 1961-01-03", False), + ("from 1960-01-01 to 1961-01-01", "<=", "from 1958-01-01 to 1959-12-31", False), + ("from 1960-01-01 to 1961-01-01", "<=", "from 1958-01-01 to 1960-01-01", False), + ("from 1960-01-01 to 1961-01-01", "<=", "from 1958-01-01 to 1961-01-01", False), + ("from 1960-01-01 to 1961-01-01", "<=", "from 1958-01-01 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", "<=", "from 1960-01-01 to 1960-12-31", True), + ("from 1960-01-01 to 1961-01-01", "<=", "from 1960-01-01 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", "<=", "from 1960-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "<=", "from 1960-12-31 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", "<=", "from 1960-12-31 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "<=", "from 1961-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", "<=", "from 1961-01-02 to 1961-01-03", True), + ("from 1960-01-01 to 1961-01-01", ">=", "from 1958-01-01 to 1959-12-31", True), + ("from 1960-01-01 to 1961-01-01", ">=", "from 1958-01-01 to 1960-01-01", True), + ("from 1960-01-01 to 1961-01-01", ">=", "from 1958-01-01 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", ">=", "from 1958-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", ">=", "from 1960-01-01 to 1960-12-31", True), + ("from 1960-01-01 to 1961-01-01", ">=", "from 1960-01-01 to 1961-01-01", True), + ("from 1960-01-01 to 1961-01-01", ">=", "from 1960-01-01 to 1961-01-02", True), + ("from 1960-01-01 to 1961-01-01", ">=", "from 1960-12-31 to 1961-01-01", False), + ("from 1960-01-01 to 1961-01-01", ">=", "from 1960-12-31 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", ">=", "from 1961-01-01 to 1961-01-02", False), + ("from 1960-01-01 to 1961-01-01", ">=", "from 1961-01-02 to 1961-01-03", False), + ] + + def convert_to_date(self, d): + return d if isinstance(d, Date) else _dp.parse(d) + + def do_case(self, d1, op, d2, expected): + """ + Compare two Gramps dates. + """ + failstr = d1 + " " + op + " " + d2 + " should be {}".format(expected) + date1 = self.convert_to_date(d1) + date2 = self.convert_to_date(d2) + if op == "=": + self.assertEqual(date1.match(date2), expected, failstr) + elif op == "!=": + self.assertEqual(date1 != date2, expected, failstr) + elif op == "==": + self.assertEqual(date1 == date2, expected, failstr) + elif op == "<": + self.assertEqual(date1 < date2, expected, failstr) + elif op == "<<": + self.assertEqual(date1 << date2, expected, failstr) + elif op == ">": + self.assertEqual(date1 > date2, expected, failstr) + elif op == ">>": + self.assertEqual(date1 >> date2, expected, failstr) + elif op == "<=": + self.assertEqual(date1 <= date2, expected, failstr) + elif op == ">=": + self.assertEqual(date1 >= date2, expected, failstr) + + def test_comparison(self): + for testdata in self.tests: + self.do_case(*testdata) + + +# ------------------------------------------------------------------------- +# +# AgeTest +# +# ------------------------------------------------------------------------- +@unittest.skipUnless( + ENGLISH_DATE_HANDLER, + "This test of Date() matching logic can only run in English locale.", +) +class AgeTest(BaseDateTest): + """ + Age tests. + """ + + tests = [ + ("1960", "1960", "0 days"), # Logically (less than 1 year) + ( + "1960-01", + "1960-01", + "0 days", + ), # Logically (less than 1 month) + ( + "1960-01", + "1960-02", + "1 month", + ), # Logically (between 1 month and 1 month, 27|28) days) + ("1960-01-01", "1960-01-02", "1 day"), + ("1960-01-01", "1960-01-31", "30 days"), + ("after 1960-01-01", "1960-01-31", "less than 29 days"), + ("1960-01-01", "1960-02-02", "1 month, 1 day"), + ("1960-01-01", "1961-02-02", "1 year, 1 month"), + ("1960-01-01", "1965-01-01", "5 years"), + ( + "1960-01-01", + "1965-02-02", + "5 years, 1 month", + ), + ( + "about 1960-01-01", + "before 1965-02-02", + "less than about 5 years, 1 month", + ), + ( + "about 1960-01-01", + "after 1965-02-02", + "more than about 5 years, 1 month", + ), + ( + "1960", + "2000", + "40 years", + ), + ("", "1760", "greater than 110 years"), + ("", "1960", "greater than 110 years"), + ("", "2020", "greater than 110 years"), + ("", "3020", "greater than 110 years"), + ("2000", "", "(1999 years)"), + ] + + def convert_to_date(self, d): + return d if isinstance(d, Date) else _dp.parse(d) + + def do_case(self, d1, d2, exp_age): + span = Span(self.convert_to_date(d2), self.convert_to_date(d1)) + age = span.as_age() + failstr = ( + "Birth at " + + d1 + + ", death at " + + d2 + + " gives age " + + age + + ". Should be {}".format(exp_age) + ) + self.assertEqual(age, exp_age, failstr) + + def test_age(self): + for testdata in self.tests: + self.do_case(*testdata) + + +# ------------------------------------------------------------------------- # # SwedishDateTest # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class SwedishDateTest(BaseDateTest): """ Swedish calendar tests. """ + def test_swedish(self): for date in swedish_dates: - self.assertEqual(date.sortval, - date.to_calendar('gregorian').sortval) + self.assertEqual(date.sortval, date.to_calendar("gregorian").sortval) + class Test_set2(BaseDateTest): """ Test the Date.set2_... setters -- the ones to manipulate the 2nd date of a compound date """ + def setUp(self): self.date = d = Date() - d.set(modifier=Date.MOD_RANGE, - #d m y sl--d m y sl - value=(1, 1, 2000, 0, 1, 1, 2010, 0)) + d.set( + modifier=Date.MOD_RANGE, + # d m y sl--d m y sl + value=(1, 1, 2000, 0, 1, 1, 2010, 0), + ) def testStartStopSanity(self): - start,stop = self.date.get_start_stop_range() + start, stop = self.date.get_start_stop_range() self.assertEqual(start, (2000, 1, 1)) self.assertEqual(stop, (2010, 1, 1)) def test_set2_ymd_overrides_stop_date(self): self.date.set2_yr_mon_day(2013, 2, 2) - start,stop = self.date.get_start_stop_range() + start, stop = self.date.get_start_stop_range() self.assertEqual(start, (2000, 1, 1)) self.assertEqual(stop, (2013, 2, 2)) def test_set_ymd_overrides_both_dates(self): - self.date.set_yr_mon_day(2013, 2, 2, remove_stop_date = True) - start,stop = self.date.get_start_stop_range() + self.date.set_yr_mon_day(2013, 2, 2, remove_stop_date=True) + start, stop = self.date.get_start_stop_range() self.assertEqual(start, stop) self.assertEqual(stop, (2013, 2, 2)) def test_set_ymd_offset_updates_both_ends(self): self.date.set_yr_mon_day_offset(+2, +2, +2) - start,stop = self.date.get_start_stop_range() + start, stop = self.date.get_start_stop_range() self.assertEqual(start, (2002, 3, 3)) self.assertEqual(stop, (2012, 3, 3)) def test_set2_ymd_offset_updates_stop_date(self): self.date.set2_yr_mon_day_offset(+7, +5, +5) - start,stop = self.date.get_start_stop_range() + start, stop = self.date.get_start_stop_range() self.assertEqual(start, (2000, 1, 1)) self.assertEqual(stop, (2017, 6, 6)) def test_copy_offset_ymd_preserves_orig(self): copied = self.date.copy_offset_ymd(year=-1) self.testStartStopSanity() - start,stop = copied.get_start_stop_range() + start, stop = copied.get_start_stop_range() self.assertEqual(start, (1999, 1, 1)) self.assertEqual(stop, (2009, 1, 1)) def test_copy_ymd_preserves_orig(self): - copied = self.date.copy_ymd(year=1000, month=10, day=10, - remove_stop_date=True) + copied = self.date.copy_ymd(year=1000, month=10, day=10, remove_stop_date=True) self.testStartStopSanity() - start,stop = copied.get_start_stop_range() + start, stop = copied.get_start_stop_range() self.assertEqual(start, (1000, 10, 10)) self.assertEqual(stop, (1000, 10, 10)) def _test_set2_function_raises_error_unless_compound(self, function): - for mod in (Date.MOD_NONE, Date.MOD_BEFORE, Date.MOD_AFTER, - Date.MOD_ABOUT, - Date.MOD_TEXTONLY): + for mod in ( + Date.MOD_NONE, + Date.MOD_BEFORE, + Date.MOD_AFTER, + Date.MOD_ABOUT, + Date.MOD_TEXTONLY, + ): self.date.set_modifier(mod) try: function(self.date) - self.assertTrue(False, - "Modifier: {}, dateval: {} - exception expected!".format( - mod, self.date.dateval)) + self.assertTrue( + False, + "Modifier: {}, dateval: {} - exception expected!".format( + mod, self.date.dateval + ), + ) except DateError: pass def test_set2_ymd_raises_error_unless_compound(self): self._test_set2_function_raises_error_unless_compound( - lambda date: date.set2_yr_mon_day(2013, 2, 2)) + lambda date: date.set2_yr_mon_day(2013, 2, 2) + ) def test_set2_ymd_offset_raises_error_unless_compound(self): self._test_set2_function_raises_error_unless_compound( - lambda date: date.set2_yr_mon_day_offset(year=-1)) + lambda date: date.set2_yr_mon_day_offset(year=-1) + ) + class Test_set_newyear(BaseDateTest): def test_raises_error_iff_calendar_has_fixed_newyear(self): for cal in Date.CALENDARS: - d = Date(1111,2,3) + d = Date(1111, 2, 3) should_raise = calendar_has_fixed_newyear(cal) - message = "{name} {cal}".format( - name = Date.calendar_names[cal], - cal = cal) + message = "{name} {cal}".format(name=Date.calendar_names[cal], cal=cal) try: d.set(calendar=cal, newyear=2) self.assertFalse(should_raise, message) except DateError: self.assertTrue(should_raise, message) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # EmptyDateTest # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class EmptyDateTest(BaseDateTest): """ Tests for empty dates. """ + def test_empty(self): d = Date() self.assertTrue(d.is_empty()) def test_text_only_empty(self): d = Date() - d.set(text='First of Jan', - modifier=Date.MOD_TEXTONLY) + d.set(text="First of Jan", modifier=Date.MOD_TEXTONLY) self.assertFalse(d.is_empty()) def test_single_empty(self): d = Date() - d.set(value=(1, 1, 1900, False), - modifier=Date.MOD_NONE) + d.set(value=(1, 1, 1900, False), modifier=Date.MOD_NONE) self.assertFalse(d.is_empty()) def test_range_empty(self): d = Date() - d.set(value=(1, 1, 1900, False, 1, 1, 1910, False), - modifier=Date.MOD_RANGE) + d.set(value=(1, 1, 1900, False, 1, 1, 1910, False), modifier=Date.MOD_RANGE) self.assertFalse(d.is_empty()) def test_span_empty(self): d = Date() - d.set(value=(1, 1, 1900, False, 1, 1, 1910, False), - modifier=Date.MOD_SPAN) + d.set(value=(1, 1, 1900, False, 1, 1, 1910, False), modifier=Date.MOD_SPAN) self.assertFalse(d.is_empty()) + if __name__ == "__main__": unittest.main() diff --git a/gramps/gui/editors/editdate.py b/gramps/gui/editors/editdate.py index eaf26c753..d74a64022 100644 --- a/gramps/gui/editors/editdate.py +++ b/gramps/gui/editors/editdate.py @@ -31,32 +31,32 @@ The DateEditor provides a dialog in which the date can be unambiguously built using UI controls such as menus and spin buttons. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # set up logging # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import logging -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # GNOME modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from gi.repository import Gtk -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from gramps.gen.const import GRAMPS_LOCALE as glocale from gramps.gen.config import config from gramps.gen.lib.date import Date, DateError, calendar_has_fixed_newyear @@ -68,42 +68,47 @@ from ..glade import Glade LOG = logging.getLogger(".EditDate") _ = glocale.translation.sgettext -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Constants # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- MOD_TEXT = ( - (Date.MOD_NONE, _('Regular')), - (Date.MOD_BEFORE, _('Before')), - (Date.MOD_AFTER, _('After')), - (Date.MOD_ABOUT, _('About')), - (Date.MOD_RANGE, _('Range')), - (Date.MOD_SPAN, _('Span')), - (Date.MOD_TEXTONLY, _('Text only'))) + (Date.MOD_NONE, _("Regular")), + (Date.MOD_BEFORE, _("Before")), + (Date.MOD_AFTER, _("After")), + (Date.MOD_ABOUT, _("About")), + (Date.MOD_RANGE, _("Range")), + (Date.MOD_FROM, _("From")), + (Date.MOD_TO, _("To")), + (Date.MOD_SPAN, _("Span")), + (Date.MOD_TEXTONLY, _("Text only")), +) QUAL_TEXT = ( - (Date.QUAL_NONE, _('Regular')), - (Date.QUAL_ESTIMATED, _('Estimated')), - (Date.QUAL_CALCULATED, _('Calculated'))) + (Date.QUAL_NONE, _("Regular")), + (Date.QUAL_ESTIMATED, _("Estimated")), + (Date.QUAL_CALCULATED, _("Calculated")), +) CAL_TO_MONTHS_NAMES = { - Date.CAL_GREGORIAN : displayer.short_months, - Date.CAL_JULIAN : displayer.short_months, - Date.CAL_HEBREW : displayer.hebrew, - Date.CAL_FRENCH : displayer.french, - Date.CAL_PERSIAN : displayer.persian, - Date.CAL_ISLAMIC : displayer.islamic, - Date.CAL_SWEDISH : displayer.swedish} + Date.CAL_GREGORIAN: displayer.short_months, + Date.CAL_JULIAN: displayer.short_months, + Date.CAL_HEBREW: displayer.hebrew, + Date.CAL_FRENCH: displayer.french, + Date.CAL_PERSIAN: displayer.persian, + Date.CAL_ISLAMIC: displayer.islamic, + Date.CAL_SWEDISH: displayer.swedish, +} WIKI_HELP_PAGE = URL_MANUAL_SECT1 -WIKI_HELP_SEC = _('Editing_dates', 'manual') +WIKI_HELP_SEC = _("Editing_dates", "manual") -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # EditDate # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class EditDate(ManagedWindow): """ Dialog allowing to build the date precisely, to correct possible @@ -122,40 +127,39 @@ class EditDate(ManagedWindow): self.top = Glade() self.set_window( - self.top.toplevel, - self.top.get_object('title'), - _('Date selection')) - self.setup_configs('interface.editdate', 620, 320) + self.top.toplevel, self.top.get_object("title"), _("Date selection") + ) + self.setup_configs("interface.editdate", 620, 320) - self.statusbar = self.top.get_object('statusbar') - self.ok_button = self.top.get_object('ok_button') - self.calendar_box = self.top.get_object('calendar_box') + self.statusbar = self.top.get_object("statusbar") + self.ok_button = self.top.get_object("ok_button") + self.calendar_box = self.top.get_object("calendar_box") for name in Date.ui_calendar_names: self.calendar_box.get_model().append([name]) - self.new_year = self.top.get_object('newyear') + self.new_year = self.top.get_object("newyear") self.new_year.set_text(self.date.newyear_to_str()) cal = self.date.get_calendar() self.calendar_box.set_active(cal) self.align_newyear_ui_with_calendar(cal) - self.calendar_box.connect('changed', self.switch_calendar) + self.calendar_box.connect("changed", self.switch_calendar) - self.quality_box = self.top.get_object('quality_box') + self.quality_box = self.top.get_object("quality_box") for item_number, item in enumerate(QUAL_TEXT): self.quality_box.append_text(item[1]) if self.date.get_quality() == item[0]: self.quality_box.set_active(item_number) - self.type_box = self.top.get_object('type_box') + self.type_box = self.top.get_object("type_box") for item_number, item in enumerate(MOD_TEXT): self.type_box.append_text(item[1]) if self.date.get_modifier() == item[0]: self.type_box.set_active(item_number) - self.type_box.connect('changed', self.switch_type) + self.type_box.connect("changed", self.switch_type) - self.start_month_box = self.top.get_object('start_month_box') - self.stop_month_box = self.top.get_object('stop_month_box') + self.start_month_box = self.top.get_object("start_month_box") + self.stop_month_box = self.top.get_object("stop_month_box") month_names = CAL_TO_MONTHS_NAMES[self.date.get_calendar()] for name in month_names: self.start_month_box.append_text(name) @@ -163,17 +167,17 @@ class EditDate(ManagedWindow): self.start_month_box.set_active(self.date.get_month()) self.stop_month_box.set_active(self.date.get_stop_month()) - self.start_day = self.top.get_object('start_day') + self.start_day = self.top.get_object("start_day") self.start_day.set_value(self.date.get_day()) - self.start_year = self.top.get_object('start_year') + self.start_year = self.top.get_object("start_year") self.start_year.set_value(self.date.get_year()) - self.stop_day = self.top.get_object('stop_day') + self.stop_day = self.top.get_object("stop_day") self.stop_day.set_value(self.date.get_stop_day()) - self.stop_year = self.top.get_object('stop_year') + self.stop_year = self.top.get_object("stop_year") self.stop_year.set_value(self.date.get_stop_year()) - self.dual_dated = self.top.get_object('dualdated') + self.dual_dated = self.top.get_object("dualdated") # Disable second date controls if not compound date if not self.date.is_compound(): @@ -191,16 +195,16 @@ class EditDate(ManagedWindow): self.dual_dated.set_sensitive(0) self.new_year.set_sensitive(0) - self.text_entry = self.top.get_object('date_text_entry') + self.text_entry = self.top.get_object("date_text_entry") self.text_entry.set_text(self.date.get_text()) if self.date.get_slash(): self.dual_dated.set_active(1) self.calendar_box.set_sensitive(0) self.calendar_box.set_active(Date.CAL_JULIAN) - self.dual_dated.connect('toggled', self.switch_dual_dated) + self.dual_dated.connect("toggled", self.switch_dual_dated) - cal = config.get('preferences.calendar-format-input') + cal = config.get("preferences.calendar-format-input") self.calendar_box.set_active(cal) # The dialog is modal -- since dates don't have names, we don't @@ -211,7 +215,7 @@ class EditDate(ManagedWindow): for obj in self.top.get_objects(): if obj != self.ok_button: - for signal in ['changed', 'value-changed']: + for signal in ["changed", "value-changed"]: try: obj.connect_after(signal, self.revalidate) except TypeError: @@ -245,20 +249,27 @@ class EditDate(ManagedWindow): If anything changed, revalidate the date and enable/disable the "OK" button based on the result. """ - (the_quality, the_modifier, the_calendar, the_value, - the_text, the_newyear) = self.build_date_from_ui() - LOG.debug("revalidate: {0} changed, value: {1}".format( - obj, the_value)) + ( + the_quality, + the_modifier, + the_calendar, + the_value, + the_text, + the_newyear, + ) = self.build_date_from_ui() + LOG.debug("revalidate: {0} changed, value: {1}".format(obj, the_value)) dat = Date(self.date) if not self.ok_button.get_sensitive(): self.statusbar.pop(1) try: - dat.set(quality=the_quality, - modifier=the_modifier, - calendar=the_calendar, - value=the_value, - text=the_text, - newyear=the_newyear) + dat.set( + quality=the_quality, + modifier=the_modifier, + calendar=the_calendar, + value=the_value, + text=the_text, + newyear=the_newyear, + ) # didn't throw yet? self.validated_date = dat LOG.debug("validated_date set to: {0}".format(dat.__dict__)) @@ -270,10 +281,12 @@ class EditDate(ManagedWindow): self.calendar_box.set_sensitive(0) curmode = MOD_TEXT[self.type_box.get_active()][1] txtmode = MOD_TEXT[-1][1] - self.statusbar.push(1, - _("Correct the date or switch from `{cur_mode}'" - " to `{text_mode}'").format( - cur_mode=curmode, text_mode=txtmode)) + self.statusbar.push( + 1, + _( + "Correct the date or switch from `{cur_mode}'" " to `{text_mode}'" + ).format(cur_mode=curmode, text_mode=txtmode), + ) return False def build_menu_names(self, obj): @@ -297,8 +310,14 @@ class EditDate(ManagedWindow): text = self.text_entry.get_text() if modifier == Date.MOD_TEXTONLY: - return (Date.QUAL_NONE, Date.MOD_TEXTONLY, Date.CAL_GREGORIAN, - Date.EMPTY, text, Date.NEWYEAR_JAN1) + return ( + Date.QUAL_NONE, + Date.MOD_TEXTONLY, + Date.CAL_GREGORIAN, + Date.EMPTY, + text, + Date.NEWYEAR_JAN1, + ) quality = QUAL_TEXT[self.quality_box.get_active()][0] @@ -311,13 +330,15 @@ class EditDate(ManagedWindow): self.stop_day.get_value_as_int(), self.stop_month_box.get_active(), self.stop_year.get_value_as_int(), - self.dual_dated.get_active()) + self.dual_dated.get_active(), + ) else: value = ( self.start_day.get_value_as_int(), self.start_month_box.get_active(), self.start_year.get_value_as_int(), - self.dual_dated.get_active()) + self.dual_dated.get_active(), + ) calendar = self.calendar_box.get_active() newyear = Date.newyear_to_code(self.new_year.get_text()) return (quality, modifier, calendar, value, text, newyear) @@ -366,7 +387,7 @@ class EditDate(ManagedWindow): if calendar_has_fixed_newyear(cal): LOG.debug("new year disabled for cal {0}".format(cal)) self.new_year.set_sensitive(0) - self.new_year.set_text('') + self.new_year.set_text("") else: LOG.debug("new year enabled for cal {0}".format(cal)) self.new_year.set_sensitive(1) @@ -379,20 +400,29 @@ class EditDate(ManagedWindow): old_cal = self.date.get_calendar() new_cal = self.calendar_box.get_active() - LOG.debug(">>>switch_calendar: {0} changed, {1} -> {2}".format( - obj, old_cal, new_cal)) + LOG.debug( + ">>>switch_calendar: {0} changed, {1} -> {2}".format(obj, old_cal, new_cal) + ) self.align_newyear_ui_with_calendar(new_cal) - (the_quality, the_modifier, dummy_the_calendar, - the_value, the_text, the_newyear) = self.build_date_from_ui() + ( + the_quality, + the_modifier, + dummy_the_calendar, + the_value, + the_text, + the_newyear, + ) = self.build_date_from_ui() try: - self.date.set(quality=the_quality, - modifier=the_modifier, - calendar=old_cal, - value=the_value, - text=the_text, - newyear=the_newyear) + self.date.set( + quality=the_quality, + modifier=the_modifier, + calendar=old_cal, + value=the_value, + text=the_text, + newyear=the_newyear, + ) except DateError: pass else: @@ -412,5 +442,6 @@ class EditDate(ManagedWindow): self.stop_day.set_value(self.date.get_stop_day()) self.stop_month_box.set_active(self.date.get_stop_month()) self.stop_year.set_value(self.date.get_stop_year()) - LOG.debug("<< {2}".format( - obj, old_cal, new_cal)) + LOG.debug( + "<< {2}".format(obj, old_cal, new_cal) + ) diff --git a/gramps/plugins/export/exportgeneweb.py b/gramps/plugins/export/exportgeneweb.py index ee54686b6..8d57123ed 100644 --- a/gramps/plugins/export/exportgeneweb.py +++ b/gramps/plugins/export/exportgeneweb.py @@ -24,28 +24,30 @@ "Export to GeneWeb." -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Standard Python Modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import os -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ # # Set up logging # -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ import logging from collections import abc + log = logging.getLogger(".WriteGeneWeb") -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from gramps.gen.const import GRAMPS_LOCALE as glocale + _ = glocale.translation.gettext from gramps.gen.lib import Date, Event, EventType, FamilyRelType, Person from gramps.gui.plug.export import WriterOptionBox @@ -54,6 +56,7 @@ from gramps.gui.glade import Glade from gramps.gen.config import config from gramps.gen.display.place import displayer as _pd + class GeneWebWriter: def __init__(self, database, filename, user, option_box=None): self.db = database @@ -78,17 +81,17 @@ class GeneWebWriter: def update_real(self): self.count += 1 - newval = int(100*self.count/self.total) + newval = int(100 * self.count / self.total) if newval != self.oldval: self.user.callback(newval) self.oldval = newval def writeln(self, text): - self.g.write(self.iso8859('%s\n' % (text))) + self.g.write(self.iso8859("%s\n" % (text))) def export_data(self): - self.dirname = os.path.dirname (self.filename) + self.dirname = os.path.dirname(self.filename) try: with open(self.filename, "wb") as self.g: self.flist = self.db.get_family_handles() @@ -123,29 +126,31 @@ class GeneWebWriter: mother_handle = family.get_mother_handle() if mother_handle: mother = self.db.get_person_from_handle(mother_handle) - self.writeln("fam %s %s+%s %s %s" % - (self.get_ref_name(father), + self.writeln( + "fam %s %s+%s %s %s" + % ( + self.get_ref_name(father), self.get_full_person_info_fam(father), self.get_wedding_data(family), self.get_ref_name(mother), - self.get_full_person_info_fam(mother) - ) - ) - self.write_witness( family) - self.write_sources( family.get_citation_list()) - self.write_children( family, father) - self.write_notes( family, father, mother) - if True: # FIXME: not (self.restrict and self.exclnotes): + self.get_full_person_info_fam(mother), + ) + ) + self.write_witness(family) + self.write_sources(family.get_citation_list()) + self.write_children(family, father) + self.write_notes(family, father, mother) + if True: # FIXME: not (self.restrict and self.exclnotes): notelist = family.get_note_list() note = "" for notehandle in notelist: noteobj = self.db.get_note_from_handle(notehandle) note += noteobj.get() + " " if note and note != "": - note = note.replace('\n\r',' ') - note = note.replace('\r\n',' ') - note = note.replace('\n',' ') - note = note.replace('\r',' ') + note = note.replace("\n\r", " ") + note = note.replace("\r\n", " ") + note = note.replace("\n", " ") + note = note.replace("\r", " ") self.writeln("comm %s" % note) def write_witness(self, family): @@ -162,24 +167,25 @@ class GeneWebWriter: if w_list: for witness in w_list: if witness and witness.type == Event.ID: - person = self.db.get_person_from_handle( - witness.get_value()) + person = self.db.get_person_from_handle(witness.get_value()) if person: gender = "" if person.get_gender() == Person.MALE: gender = "h" elif person.get_gender() == Person.FEMALE: gender = "f" - self.writeln("wit %s %s %s" % - (gender, + self.writeln( + "wit %s %s %s" + % ( + gender, self.get_ref_name(person), - self.get_full_person_info_fam(person) - ) + self.get_full_person_info_fam(person), ) + ) - def write_sources(self,reflist): + def write_sources(self, reflist): # FIXME - #if self.restrict and self.exclnotes: + # if self.restrict and self.exclnotes: # return if reflist: @@ -188,11 +194,9 @@ class GeneWebWriter: src_handle = citation.get_reference_handle() source = self.db.get_source_from_handle(src_handle) if source: - self.writeln( "src %s" % - (self.rem_spaces(source.get_title())) - ) + self.writeln("src %s" % (self.rem_spaces(source.get_title()))) - def write_children(self,family, father): + def write_children(self, family, father): father_lastname = father.get_primary_name().get_surname() child_ref_list = family.get_child_ref_list() if child_ref_list: @@ -205,17 +209,19 @@ class GeneWebWriter: gender = "h" elif child.get_gender() == Person.FEMALE: gender = "f" - self.writeln("- %s %s %s" % - (gender, + self.writeln( + "- %s %s %s" + % ( + gender, self.get_child_ref_name(child, father_lastname), - self.get_full_person_info_child(child) - ) - ) + self.get_full_person_info_child(child), + ) + ) self.writeln("end") - def write_notes(self,family, father, mother): + def write_notes(self, family, father, mother): # FIXME: - #if self.restrict and self.exclnotes: + # if self.restrict and self.exclnotes: # return self.write_note_of_person(father) @@ -227,19 +233,20 @@ class GeneWebWriter: if child: self.write_note_of_person(child) # FIXME: witnesses do not exist in events anymore -## event_ref_list = family.get_event_ref_list() -## for event_ref in event_ref_list: -## event = self.db.get_event_from_handle(event_ref.ref) -## if int(event.get_type()) == EventType.MARRIAGE: -## w_list = event.get_witness_list() -## if w_list: -## for witness in w_list: -## if witness and witness.type == Event.ID: -## person = self.db.get_person_from_handle(witness.get_value()) -## if person: -## self.write_note_of_person(person) - def write_note_of_person(self,person): + ## event_ref_list = family.get_event_ref_list() + ## for event_ref in event_ref_list: + ## event = self.db.get_event_from_handle(event_ref.ref) + ## if int(event.get_type()) == EventType.MARRIAGE: + ## w_list = event.get_witness_list() + ## if w_list: + ## for witness in w_list: + ## if witness and witness.type == Event.ID: + ## person = self.db.get_person_from_handle(witness.get_value()) + ## if person: + ## self.write_note_of_person(person) + + def write_note_of_person(self, person): if self.persons_notes_done.count(person.get_handle()) == 0: self.persons_notes_done.append(person.get_handle()) @@ -259,7 +266,7 @@ class GeneWebWriter: def get_full_person_info(self, person): # FIXME: - #if self.restrict: + # if self.restrict: # return "0 " retval = "" @@ -270,12 +277,12 @@ class GeneWebWriter: if birth_ref: birth = self.db.get_event_from_handle(birth_ref.ref) if birth: - b_date = self.format_date( birth.get_date_object()) + b_date = self.format_date(birth.get_date_object()) place_handle = birth.get_place_handle() if place_handle: b_place = _pd.display_event(self.db, birth) - if probably_alive(person,self.db): + if probably_alive(person, self.db): d_date = "" else: d_date = "0" @@ -284,7 +291,7 @@ class GeneWebWriter: if death_ref: death = self.db.get_event_from_handle(death_ref.ref) if death: - d_date = self.format_date( death.get_date_object()) + d_date = self.format_date(death.get_date_object()) place_handle = death.get_place_handle() if place_handle: d_place = _pd.display_event(self.db, death) @@ -316,7 +323,6 @@ class GeneWebWriter: retval = self.get_full_person_info(person) return retval - def get_full_person_info_child(self, person): """Output full person data for a child, if not printed somewhere else.""" retval = "" @@ -325,36 +331,36 @@ class GeneWebWriter: retval = self.get_full_person_info(person) return retval - def rem_spaces(self,str): - return str.replace(' ','_') + def rem_spaces(self, str): + return str.replace(" ", "_") - def get_ref_name(self,person): - #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 (probably_alive(person,self.db) and \ + def get_ref_name(self, person): + # 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 (probably_alive(person,self.db) and \ # self.restrict and self.living): - firstname = self.rem_spaces( person.get_primary_name().get_first_name()) + firstname = self.rem_spaces(person.get_primary_name().get_first_name()) if person.get_handle() not in self.person_ids: self.person_ids[person.get_handle()] = len(self.person_ids) - return "%s %s.%d" % (surname, firstname, - self.person_ids[person.get_handle()]) + return "%s %s.%d" % (surname, firstname, self.person_ids[person.get_handle()]) - def get_child_ref_name(self,person,father_lastname): - #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 (probably_alive(person,self.db) and \ + def get_child_ref_name(self, person, father_lastname): + # 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 (probably_alive(person,self.db) and \ # self.restrict and self.living): - firstname = self.rem_spaces( person.get_primary_name().get_first_name()) + firstname = self.rem_spaces(person.get_primary_name().get_first_name()) if person.get_handle() not in self.person_ids: self.person_ids[person.get_handle()] = len(self.person_ids) ret = "%s.%d" % (firstname, self.person_ids[person.get_handle()]) - if surname != father_lastname: ret += " " + surname + if surname != father_lastname: + ret += " " + surname return ret - def get_wedding_data(self,family): - ret = ""; + def get_wedding_data(self, family): + ret = "" event_ref_list = family.get_event_ref_list() m_date = "" m_place = "" @@ -370,40 +376,46 @@ class GeneWebWriter: event = self.db.get_event_from_handle(event_ref.ref) if event.get_type() == EventType.MARRIAGE: married = 1 - m_date = self.format_date( event.get_date_object()) + m_date = self.format_date(event.get_date_object()) place_handle = event.get_place_handle() if place_handle: m_place = _pd.display_event(self.db, event) - m_source = self.get_primary_source( event.get_citation_list()) + m_source = self.get_primary_source(event.get_citation_list()) if event.get_type() == EventType.ENGAGEMENT: engaged = 1 - eng_date = self.format_date( event.get_date_object()) + eng_date = self.format_date(event.get_date_object()) place_handle = event.get_place_handle() if place_handle: eng_place = _pd.display_event(self.db, event) - eng_source = self.get_primary_source( event.get_citation_list()) + eng_source = self.get_primary_source(event.get_citation_list()) if event.get_type() == EventType.DIVORCE: divorced = 1 - div_date = self.format_date( event.get_date_object()) + div_date = self.format_date(event.get_date_object()) if married == 1: if m_date != "": ret = ret + m_date if m_place != "" and m_source != "": - ret = ret + " #mp %s #ms %s" % (self.rem_spaces( m_place), self.rem_spaces( m_source)) + ret = ret + " #mp %s #ms %s" % ( + self.rem_spaces(m_place), + self.rem_spaces(m_source), + ) if m_place != "" and m_source == "": - ret = ret + " #mp %s" % self.rem_spaces( m_place) + ret = ret + " #mp %s" % self.rem_spaces(m_place) if m_source != "" and m_place == "": - ret = ret + " #ms %s" % self.rem_spaces( m_source) + ret = ret + " #ms %s" % self.rem_spaces(m_source) elif engaged == 1: """Geneweb only supports either Marriage or engagement""" if eng_date != "": ret = ret + eng_date if m_place != "" and m_source != "": - ret = ret + " #mp %s #ms %s" % (self.rem_spaces( m_place), self.rem_spaces( m_source)) + ret = ret + " #mp %s #ms %s" % ( + self.rem_spaces(m_place), + self.rem_spaces(m_source), + ) if eng_place != "" and m_source == "": - ret = ret + " #mp %s" % self.rem_spaces( m_place) + ret = ret + " #mp %s" % self.rem_spaces(m_place) if eng_source != "" and m_place == "": - ret = ret + " #ms %s" % self.rem_spaces( m_source) + ret = ret + " #ms %s" % self.rem_spaces(m_source) else: if family.get_relationship() != FamilyRelType.MARRIED: """Not married or engaged""" @@ -411,13 +423,13 @@ class GeneWebWriter: if divorced == 1: if div_date != "": - ret = ret + " -%s" %div_date + ret = ret + " -%s" % div_date else: ret = ret + " -0" return ret - def get_primary_source(self,reflist): + def get_primary_source(self, reflist): ret = "" if reflist: for handle in reflist: @@ -453,15 +465,14 @@ class GeneWebWriter: if year > 0: if month > 0: if day > 0: - retval = "%s%s/%s/%s%s" % (mode_prefix,day,month,year,cal_type) + retval = "%s%s/%s/%s%s" % (mode_prefix, day, month, year, cal_type) else: - retval = "%s%s/%s%s" % (mode_prefix,month,year,cal_type) + retval = "%s%s/%s%s" % (mode_prefix, month, year, cal_type) else: - retval = "%s%s%s" % (mode_prefix,year,cal_type) + retval = "%s%s%s" % (mode_prefix, year, cal_type) return retval - - def format_date(self,date): + def format_date(self, date): retval = "" if date.get_modifier() == Date.MOD_TEXTONLY: retval = "0(%s)" % self.rem_spaces(date.get_text()) @@ -470,20 +481,30 @@ class GeneWebWriter: cal = cal = date.get_calendar() if mod == Date.MOD_SPAN or mod == Date.MOD_RANGE: retval = "%s..%s" % ( - self.format_single_date(date.get_start_date(), cal,mod), - self.format_single_date(date.get_stop_date(),cal,mod)) + self.format_single_date(date.get_start_date(), cal, mod), + self.format_single_date(date.get_stop_date(), cal, mod), + ) + elif mod == Date.MOD_FROM: + retval = "%s..0" % ( + self.format_single_date(date.get_start_date(), cal, mod) + ) + elif mod == Date.MOD_TO: + retval = "0..%s" % ( + self.format_single_date(date.get_start_date(), cal, mod) + ) else: - retval = self.format_single_date(date.get_start_date(),cal,mod) + retval = self.format_single_date(date.get_start_date(), cal, mod) return retval - def iso8859(self,s): - return s.encode('iso-8859-1','xmlcharrefreplace') + def iso8859(self, s): + return s.encode("iso-8859-1", "xmlcharrefreplace") -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- def exportData(database, filename, user, option_box=None): gw = GeneWebWriter(database, filename, user, option_box) return gw.export_data() diff --git a/gramps/plugins/export/exportvcalendar.py b/gramps/plugins/export/exportvcalendar.py index 6dd577f2f..ec87f0858 100644 --- a/gramps/plugins/export/exportvcalendar.py +++ b/gramps/plugins/export/exportvcalendar.py @@ -23,30 +23,32 @@ "Export Events to vCalendar." -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Standard Python Modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import os import sys import time -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ # # Set up logging # -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ import logging from collections import abc + log = logging.getLogger(".ExportVCal") -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from gramps.gen.const import GRAMPS_LOCALE as glocale + _ = glocale.translation.gettext from gramps.gui.plug.export import WriterOptionBox from gramps.gen.utils.db import family_name @@ -91,14 +93,13 @@ class CalendarWriter: self.oldval = newval def writeln(self, text): - self.g.write('%s\n' % text) + self.g.write("%s\n" % text) def export_data(self, filename): self.dirname = os.path.dirname(filename) try: - with open(filename, "w", encoding='utf8', - newline='\r\n') as self.g: + with open(filename, "w", encoding="utf8", newline="\r\n") as self.g: self.writeln("BEGIN:VCALENDAR") self.writeln("PRODID:-//GNU//Gramps//EN") self.writeln("VERSION:2.0") @@ -134,8 +135,7 @@ class CalendarWriter: event = self.db.get_event_from_handle(event_ref.ref) if event and event.get_type() == EventType.MARRIAGE: # feature requests 2356, 1657: avoid genitive form - text = "%s - %s" % (family_name(family, self.db), - _("Marriage")) + text = "%s - %s" % (family_name(family, self.db), _("Marriage")) self.write_vevent(text, event) def write_person(self, person_handle): @@ -146,18 +146,18 @@ class CalendarWriter: birth = self.db.get_event_from_handle(birth_ref.ref) if birth: # feature requests 2356, 1657: avoid genitive form - self.write_vevent("%s - %s" % - (name_displayer.display(person), - _("Birth")), birth) + self.write_vevent( + "%s - %s" % (name_displayer.display(person), _("Birth")), birth + ) death_ref = person.get_death_ref() if death_ref: death = self.db.get_event_from_handle(death_ref.ref) if death: # feature requests 2356, 1657: avoid genitive form - self.write_vevent("%s - %s" % - (name_displayer.display(person), - _("Death")), death) + self.write_vevent( + "%s - %s" % (name_displayer.display(person), _("Death")), death + ) def format_single_date(self, subdate, thisyear, cal): retval = "" @@ -183,19 +183,24 @@ class CalendarWriter: mod = date.get_modifier() cal = cal = date.get_calendar() if mod == Date.MOD_SPAN or mod == Date.MOD_RANGE: - start = self.format_single_date(date.get_start_date(), - thisyear, cal) - end = self.format_single_date(date.get_stop_date(), - thisyear, cal) + start = self.format_single_date(date.get_start_date(), thisyear, cal) + end = self.format_single_date(date.get_stop_date(), thisyear, cal) if start and end: - retval = "DTSTART:%sT000001\nDTEND:%sT235959" % (start, - end) - elif mod == Date.MOD_NONE: - start = self.format_single_date(date.get_start_date(), - thisyear, cal) + retval = "DTSTART:%sT000001\nDTEND:%sT235959" % (start, end) + elif mod == Date.MOD_FROM: + start = self.format_single_date(date.get_start_date(), thisyear, cal) if start: - retval = "DTSTART:%sT000001\nDTEND:%sT235959" % (start, - start) + retval = "DTSTART:%sT000001" % (start) + + elif mod == Date.MOD_TO: + end = self.format_single_date(date.get_start_date(), thisyear, cal) + if end: + retval = "DTEND:%sT235959" % (end) + + elif mod == Date.MOD_NONE: + start = self.format_single_date(date.get_start_date(), thisyear, cal) + if start: + retval = "DTSTART:%sT000001\nDTEND:%sT235959" % (start, start) return retval def write_vevent(self, event_text, event): @@ -217,18 +222,19 @@ class CalendarWriter: self.writeln(date_string) self.writeln("END:VEVENT") + # ------------------------------------------------------------------------- def fold(txt): - """ Limit line length to 75 octets (per RFC 5545) """ + """Limit line length to 75 octets (per RFC 5545)""" l_len = 0 - text = '' + text = "" for char in txt: - c_len = len(char.encode('utf8')) + c_len = len(char.encode("utf8")) if c_len + l_len > 75: l_len = 1 - text += '\n ' + char + text += "\n " + char else: l_len += c_len text += char diff --git a/gramps/plugins/export/exportvcard.py b/gramps/plugins/export/exportvcard.py index cda6236a5..e1580683d 100644 --- a/gramps/plugins/export/exportvcard.py +++ b/gramps/plugins/export/exportvcard.py @@ -24,29 +24,31 @@ "Export Persons to vCard (RFC 2426)." -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Standard Python Modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import sys from textwrap import TextWrapper -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ # # Set up logging # -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ import logging from collections import abc + log = logging.getLogger(".ExportVCard") -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from gramps.gen.const import GRAMPS_LOCALE as glocale + _ = glocale.translation.gettext from gramps.gen.const import PROGRAM_NAME from gramps.version import VERSION @@ -57,11 +59,11 @@ from gramps.gen.lib.eventtype import EventType from gramps.gen.display.name import displayer as _nd from gramps.gen.plug.utils import OpenFileOrStdout -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Support Functions # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- def exportData(database, filename, user, option_box=None): """Function called by Gramps to export data on persons in VCard format.""" cardw = VCardWriter(database, filename, option_box, user) @@ -76,17 +78,19 @@ def exportData(database, filename, user, option_box=None): return False return True -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # VCardWriter class # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class VCardWriter: """Class to create a file with data in VCard format.""" - LINELENGTH = 73 # unclear if the 75 chars of spec includes \r\n. - ESCAPE_CHAR = '\\' - TOBE_ESCAPED = ['\\', ',', ';'] # order is important - LINE_CONTINUATION = [' ', '\t'] + + LINELENGTH = 73 # unclear if the 75 chars of spec includes \r\n. + ESCAPE_CHAR = "\\" + TOBE_ESCAPED = ["\\", ",", ";"] # order is important + LINE_CONTINUATION = [" ", "\t"] @staticmethod def esc(data): @@ -100,8 +104,10 @@ class VCardWriter: elif type(data) == type(()): return tuple(map(VCardWriter.esc, data)) else: - raise TypeError("VCard escaping is not implemented for " - "data type %s." % str(type(data))) + raise TypeError( + "VCard escaping is not implemented for " + "data type %s." % str(type(data)) + ) def __init__(self, database, filename, option_box=None, user=None): self.db = database @@ -118,11 +124,13 @@ class VCardWriter: self.option_box.parse_options() self.db = option_box.get_filtered_database(self.db) - self.txtwrp = TextWrapper(width=self.LINELENGTH, - expand_tabs=False, - replace_whitespace=False, - drop_whitespace=False, - subsequent_indent=self.LINE_CONTINUATION[0]) + self.txtwrp = TextWrapper( + width=self.LINELENGTH, + expand_tabs=False, + replace_whitespace=False, + drop_whitespace=False, + subsequent_indent=self.LINE_CONTINUATION[0], + ) self.count = 0 self.total = 0 @@ -133,7 +141,7 @@ class VCardWriter: def update_real(self): """Report progress.""" self.count += 1 - newval = int(100*self.count/self.total) + newval = int(100 * self.count / self.total) if newval != self.oldval: self.user.callback(newval) self.oldval = newval @@ -144,13 +152,15 @@ class VCardWriter: Can't cope with nested VCards, section 2.4.2 of RFC 2426. """ - self.filehandle.write('%s\r\n' % '\r\n'.join( - [line for line in self.txtwrp.wrap(text)])) + self.filehandle.write( + "%s\r\n" % "\r\n".join([line for line in self.txtwrp.wrap(text)]) + ) def export_data(self): """Open the file and loop over everyone too write their VCards.""" - with OpenFileOrStdout(self.filename, encoding='utf-8', - errors='strict', newline='') as self.filehandle: + with OpenFileOrStdout( + self.filename, encoding="utf-8", errors="strict", newline="" + ) as self.filehandle: if self.filehandle: self.count = 0 self.oldval = 0 @@ -181,8 +191,7 @@ class VCardWriter: """Write the opening lines of a VCard.""" self.writeln("BEGIN:VCARD") self.writeln("VERSION:3.0") - self.writeln("PRODID:-//Gramps//NONSGML %s %s//EN" % - (PROGRAM_NAME, VERSION)) + self.writeln("PRODID:-//Gramps//NONSGML %s %s//EN" % (PROGRAM_NAME, VERSION)) def write_footer(self): """Write the closing lines of a VCard.""" @@ -199,20 +208,32 @@ class VCardWriter: def write_name(self, prname): """Write the compulsory N property of a VCard.""" - family_name = '' - given_name = '' - additional_names = '' - hon_prefix = '' - suffix = '' + family_name = "" + given_name = "" + additional_names = "" + hon_prefix = "" + suffix = "" primary_surname = prname.get_primary_surname() surname_list = prname.get_surname_list() if not surname_list[0].get_primary(): surname_list.remove(primary_surname) surname_list.insert(0, primary_surname) - family_name = ','.join(self.esc([("%s %s %s" % (surname.get_prefix(), - surname.get_surname(), surname.get_connector())).strip() - for surname in surname_list])) + family_name = ",".join( + self.esc( + [ + ( + "%s %s %s" + % ( + surname.get_prefix(), + surname.get_surname(), + surname.get_connector(), + ) + ).strip() + for surname in surname_list + ] + ) + ) call_name = prname.get_call_name() if call_name: @@ -220,23 +241,25 @@ class VCardWriter: additional_name_list = prname.get_first_name().split() if call_name in additional_name_list: additional_name_list.remove(call_name) - additional_names = ','.join(self.esc(additional_name_list)) + additional_names = ",".join(self.esc(additional_name_list)) else: name_list = prname.get_first_name().split() if len(name_list) > 0: given_name = self.esc(name_list[0]) if len(name_list) > 1: - additional_names = ','.join(self.esc(name_list[1:])) + additional_names = ",".join(self.esc(name_list[1:])) # Alternate names are ignored because names just don't add up: # if one name is Jean and an alternate is Paul then you can't # conclude the Jean Paul is also an alternate name of that person. # Assume all titles/suffixes that apply are present in primary name. - hon_prefix = ','.join(self.esc(prname.get_title().split())) - suffix = ','.join(self.esc(prname.get_suffix().split())) + hon_prefix = ",".join(self.esc(prname.get_title().split())) + suffix = ",".join(self.esc(prname.get_suffix().split())) - self.writeln("N:%s;%s;%s;%s;%s" % (family_name, given_name, - additional_names, hon_prefix, suffix)) + self.writeln( + "N:%s;%s;%s;%s;%s" + % (family_name, given_name, additional_names, hon_prefix, suffix) + ) def write_sortstring(self, prname): """Write the SORT-STRING property of a VCard.""" @@ -245,19 +268,20 @@ class VCardWriter: def write_nicknames(self, person, prname): """Write the NICKNAME property of a VCard.""" - nicknames = [x.get_nick_name() for x in person.get_alternate_names() - if x.get_nick_name()] + nicknames = [ + x.get_nick_name() for x in person.get_alternate_names() if x.get_nick_name() + ] if prname.get_nick_name(): nicknames.insert(0, prname.get_nick_name()) if len(nicknames) > 0: - self.writeln("NICKNAME:%s" % (','.join(self.esc(nicknames)))) + self.writeln("NICKNAME:%s" % (",".join(self.esc(nicknames)))) def write_gender(self, person): """Write the X-GENDER property of a VCard (X- dropped in 4.0, we're at 3.0).""" gender = person.get_gender() - gender_value = '' + gender_value = "" if gender == Person.MALE: - gender_value = 'Male' + gender_value = "Male" elif gender == Person.FEMALE: gender_value = 'Female' elif gender == Person.OTHER: @@ -274,10 +298,14 @@ class VCardWriter: if birth: b_date = birth.get_date_object() mod = b_date.get_modifier() - if (mod != Date.MOD_TEXTONLY and - not b_date.is_empty() and - not mod == Date.MOD_SPAN and - not mod == Date.MOD_RANGE): + if ( + mod != Date.MOD_TEXTONLY + and not b_date.is_empty() + and not mod == Date.MOD_SPAN + and not mod == Date.MOD_FROM + and not mod == Date.MOD_TO + and not mod == Date.MOD_RANGE + ): (day, month, year, slash) = b_date.get_start_date() if day > 0 and month > 0 and year > 0: self.writeln("BDAY:%s-%02d-%02d" % (year, month, day)) @@ -294,8 +322,10 @@ class VCardWriter: zipcode = address.get_postal_code() country = address.get_country() if street or city or state or zipcode or country: - self.writeln("ADR:%s;%s;%s;%s;%s;%s;%s" % self.esc( - (postbox, ext, street, city, state, zipcode, country))) + self.writeln( + "ADR:%s;%s;%s;%s;%s;%s;%s" + % self.esc((postbox, ext, street, city, state, zipcode, country)) + ) phone = address.get_phone() if phone: @@ -308,8 +338,8 @@ class VCardWriter: href = url.get_path() if href: if url.get_type() == UrlType(UrlType.EMAIL): - if href.startswith('mailto:'): - href = href[len('mailto:'):] + if href.startswith("mailto:"): + href = href[len("mailto:") :] self.writeln("EMAIL:%s" % self.esc(href)) else: self.writeln("URL:%s" % self.esc(href)) @@ -321,12 +351,13 @@ class VCardWriter: Use the most recent occupation event. """ event_refs = person.get_primary_event_ref_list() - events = [event for event in - [self.db.get_event_from_handle(ref.ref) for ref in event_refs] - if event.get_type() == EventType(EventType.OCCUPATION)] + events = [ + event + for event in [self.db.get_event_from_handle(ref.ref) for ref in event_refs] + if event.get_type() == EventType(EventType.OCCUPATION) + ] if len(events) > 0: events.sort(key=lambda x: x.get_date_object()) occupation = events[-1].get_description() if occupation: self.writeln("ROLE:%s" % occupation) - diff --git a/gramps/plugins/export/exportxml.py b/gramps/plugins/export/exportxml.py index 08830e5ea..60835ad31 100644 --- a/gramps/plugins/export/exportxml.py +++ b/gramps/plugins/export/exportxml.py @@ -30,31 +30,33 @@ Contains the interface to allow a database to get written using Gramps' XML file format. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Standard python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import time import shutil import os import codecs from xml.sax.saxutils import escape -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ # # Set up logging # -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ import logging + LOG = logging.getLogger(".WriteXML") -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from gramps.gen.const import GRAMPS_LOCALE as glocale + _ = glocale.translation.gettext from gramps.gen.const import URL_HOMEPAGE from gramps.gen.lib import Date, Person @@ -65,40 +67,49 @@ from gramps.gen.constfunc import win from gramps.gui.plug.export import WriterOptionBox, WriterOptionBoxWithCompression import gramps.plugins.lib.libgrampsxml as libgrampsxml -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Attempt to load the GZIP library. Some version of python do not seem # to be compiled with this available. # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- try: import gzip + _gzip_ok = 1 except: _gzip_ok = 0 # table for skipping control chars from XML except 09, 0A, 0D -strip_dict = dict.fromkeys(list(range(9))+list(range(11,13))+list(range(14, 32))) +strip_dict = dict.fromkeys(list(range(9)) + list(range(11, 13)) + list(range(14, 32))) + def escxml(d): - return escape(d, - {'"' : '"', - '<' : '<', - '>' : '>', - }) if d else "" + return ( + escape( + d, + { + '"': """, + "<": "<", + ">": ">", + }, + ) + if d + else "" + ) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class GrampsXmlWriter(UpdateCallback): """ Writes a database to the XML file. """ - def __init__(self, db, strip_photos=0, compress=1, version="unknown", - user=None): + def __init__(self, db, strip_photos=0, compress=1, version="unknown", user=None): """ Initialize, but does not write, an XML file. @@ -124,8 +135,9 @@ class GrampsXmlWriter(UpdateCallback): """ Write the database to the specified file. """ - if filename == '-': + if filename == "-": import sys + try: g = sys.stdout.buffer except: @@ -136,48 +148,58 @@ class GrampsXmlWriter(UpdateCallback): if os.path.isdir(base): if not os.access(base, os.W_OK) or not os.access(base, os.R_OK): raise DbWriteFailure( - _('Failure writing %s') % filename, - _("The database cannot be saved because you do " + _("Failure writing %s") % filename, + _( + "The database cannot be saved because you do " "not have permission to write to the directory. " "Please make sure you have write access to the " - "directory and try again.")) + "directory and try again." + ), + ) return 0 else: - raise DbWriteFailure(_('No directory'), - _('There is no directory %s.\n\n' - 'Please select another directory ' - 'or create it.') % base ) + raise DbWriteFailure( + _("No directory"), + _( + "There is no directory %s.\n\n" + "Please select another directory " + "or create it." + ) + % base, + ) return 0 if os.path.exists(filename): if not os.access(filename, os.W_OK): raise DbWriteFailure( - _('Failure writing %s') % filename, - _("The database cannot be saved because you do " + _("Failure writing %s") % filename, + _( + "The database cannot be saved because you do " "not have permission to write to the file. " "Please make sure you have write access to the " - "file and try again.")) + "file and try again." + ), + ) return 0 self.fileroot = os.path.dirname(filename) try: if self.compress and _gzip_ok: try: - g = gzip.open(filename,"wb") + g = gzip.open(filename, "wb") except: - g = open(filename,"wb") + g = open(filename, "wb") else: - g = open(filename,"wb") + g = open(filename, "wb") except IOError as msg: LOG.warning(str(msg)) - raise DbWriteFailure(_('Failure writing %s') % filename, - str(msg)) + raise DbWriteFailure(_("Failure writing %s") % filename, str(msg)) return 0 self.g = codecs.getwriter("utf8")(g) self.write_xml_data() - if filename != '-': + if filename != "-": g.close() return 1 @@ -216,35 +238,50 @@ class GrampsXmlWriter(UpdateCallback): note_len = self.db.get_number_of_notes() tag_len = self.db.get_number_of_tags() - total_steps = (person_len + family_len + event_len + citation_len + - source_len + place_len + repo_len + obj_len + note_len + - tag_len - ) + total_steps = ( + person_len + + family_len + + event_len + + citation_len + + source_len + + place_len + + repo_len + + obj_len + + note_len + + tag_len + ) self.set_total(total_steps) self.g.write('\n') - self.g.write('\n' - % (libgrampsxml.GRAMPS_XML_VERSION, URL_HOMEPAGE, - libgrampsxml.GRAMPS_XML_VERSION)) - self.g.write('\n' - % (URL_HOMEPAGE, libgrampsxml.GRAMPS_XML_VERSION)) + self.g.write( + "\n' + % ( + libgrampsxml.GRAMPS_XML_VERSION, + URL_HOMEPAGE, + libgrampsxml.GRAMPS_XML_VERSION, + ) + ) + self.g.write( + '\n' + % (URL_HOMEPAGE, libgrampsxml.GRAMPS_XML_VERSION) + ) self.g.write("
\n") - self.g.write(' \n") self.g.write(" \n") - self.write_line("resname", owner.get_name(),3) - self.write_line("resaddr", owner.get_address(),3) - self.write_line("reslocality", owner.get_locality(),3) - self.write_line("rescity", owner.get_city(),3) - self.write_line("resstate", owner.get_state(),3) - self.write_line("rescountry", owner.get_country(),3) - self.write_line("respostal", owner.get_postal_code(),3) - self.write_line("resphone", owner.get_phone(),3) - self.write_line("resemail", owner.get_email(),3) + self.write_line("resname", owner.get_name(), 3) + self.write_line("resaddr", owner.get_address(), 3) + self.write_line("reslocality", owner.get_locality(), 3) + self.write_line("rescity", owner.get_city(), 3) + self.write_line("resstate", owner.get_state(), 3) + self.write_line("rescountry", owner.get_country(), 3) + self.write_line("respostal", owner.get_postal_code(), 3) + self.write_line("resphone", owner.get_phone(), 3) + self.write_line("resemail", owner.get_email(), 3) self.g.write(" \n") self.write_metadata() self.g.write("
\n") @@ -269,7 +306,7 @@ class GrampsXmlWriter(UpdateCallback): for handle in sorted(self.db.get_event_handles()): event = self.db.get_event_from_handle(handle) if event: - self.write_event(event,2) + self.write_event(event, 2) self.update() self.g.write(" \n") @@ -278,7 +315,7 @@ class GrampsXmlWriter(UpdateCallback): person = self.db.get_default_person() if person: self.g.write(' home="_%s"' % person.handle) - self.g.write('>\n') + self.g.write(">\n") for handle in sorted(self.db.get_person_handles()): person = self.db.get_person_from_handle(handle) @@ -292,7 +329,7 @@ class GrampsXmlWriter(UpdateCallback): for handle in sorted(self.db.iter_family_handles()): family = self.db.get_family_from_handle(handle) if family: - self.write_family(family,2) + self.write_family(family, 2) self.update() self.g.write(" \n") @@ -301,7 +338,7 @@ class GrampsXmlWriter(UpdateCallback): for handle in sorted(self.db.get_citation_handles()): citation = self.db.get_citation_from_handle(handle) if citation: - self.write_citation(citation,2) + self.write_citation(citation, 2) self.update() self.g.write(" \n") @@ -310,7 +347,7 @@ class GrampsXmlWriter(UpdateCallback): for handle in sorted(self.db.get_source_handles()): source = self.db.get_source_from_handle(handle) if source: - self.write_source(source,2) + self.write_source(source, 2) self.update() self.g.write(" \n") @@ -320,7 +357,7 @@ class GrampsXmlWriter(UpdateCallback): # try: place = self.db.get_place_from_handle(key) if place: - self.write_place_obj(place,2) + self.write_place_obj(place, 2) self.update() self.g.write(" \n") @@ -329,7 +366,7 @@ class GrampsXmlWriter(UpdateCallback): for handle in sorted(self.db.get_media_handles()): obj = self.db.get_media_from_handle(handle) if obj: - self.write_object(obj,2) + self.write_object(obj, 2) self.update() self.g.write(" \n") @@ -338,7 +375,7 @@ class GrampsXmlWriter(UpdateCallback): for key in sorted(self.db.get_repository_handles()): repo = self.db.get_repository_from_handle(key) if repo: - self.write_repository(repo,2) + self.write_repository(repo, 2) self.update() self.g.write(" \n") @@ -357,13 +394,12 @@ class GrampsXmlWriter(UpdateCallback): self.g.write("
\n") -# self.status.end() -# self.status = None + # self.status.end() + # self.status = None def write_metadata(self): - """ Method to write out metadata of the database - """ - mediapath= self.db.get_mediapath() + """Method to write out metadata of the database""" + mediapath = self.db.get_mediapath() if mediapath is not None: self.write_line("mediapath", mediapath, 2) @@ -375,8 +411,10 @@ class GrampsXmlWriter(UpdateCallback): self.g.write(" \n") for key in group_map: value = self.db.get_name_group_mapping(key) - self.g.write(' \n' - % (self.fix(key), self.fix(value))) + self.g.write( + ' \n' + % (self.fix(key), self.fix(value)) + ) self.g.write(" \n") def write_bookmarks(self): @@ -390,52 +428,53 @@ class GrampsXmlWriter(UpdateCallback): bm_obj_len = len(self.db.media_bookmarks.get()) bm_note_len = len(self.db.note_bookmarks.get()) - bm_len = (bm_person_len + bm_family_len + bm_event_len + - bm_source_len + bm_place_len + bm_repo_len + - bm_citation_len + bm_obj_len + bm_note_len - ) + bm_len = ( + bm_person_len + + bm_family_len + + bm_event_len + + bm_source_len + + bm_place_len + + bm_repo_len + + bm_citation_len + + bm_obj_len + + bm_note_len + ) if bm_len > 0: self.g.write(" \n") for handle in self.db.get_bookmarks().get(): - self.g.write(' \n' - % handle ) + self.g.write(' \n' % handle) for handle in self.db.get_family_bookmarks().get(): - self.g.write(' \n' - % handle ) + self.g.write(' \n' % handle) for handle in self.db.get_event_bookmarks().get(): - self.g.write(' \n' - % handle ) + self.g.write(' \n' % handle) for handle in self.db.get_source_bookmarks().get(): - self.g.write(' \n' - % handle ) + self.g.write(' \n' % handle) for handle in self.db.get_citation_bookmarks().get(): - self.g.write(' \n' - % handle ) + self.g.write(' \n' % handle) for handle in self.db.get_place_bookmarks().get(): - self.g.write(' \n' - % handle ) + self.g.write(' \n' % handle) for handle in self.db.get_media_bookmarks().get(): - self.g.write(' \n' - % handle ) + self.g.write(' \n' % handle) for handle in self.db.get_repo_bookmarks().get(): - self.g.write(' \n' - % handle ) + self.g.write( + ' \n' % handle + ) for handle in self.db.get_note_bookmarks().get(): - self.g.write(' \n' - % handle ) + self.g.write(' \n' % handle) self.g.write(" \n") def write_name_formats(self): if len(self.db.name_formats) > 0: self.g.write(" \n") - for number, name,fmt_str,active in self.db.name_formats: - self.g.write('%s\n' - % (' ', number, - escxml(name), escxml(fmt_str), int(active)) ) + for number, name, fmt_str, active in self.db.name_formats: + self.g.write( + '%s\n' + % (" ", number, escxml(name), escxml(fmt_str), int(active)) + ) self.g.write(" \n") def write_tag(self, tag, index=2): @@ -445,26 +484,26 @@ class GrampsXmlWriter(UpdateCallback): if not tag: return - self.write_table_tag('tag', tag, index, close=False) + self.write_table_tag("tag", tag, index, close=False) self.g.write(' name="%s"' % escxml(tag.get_name())) self.g.write(' color="%s"' % tag.get_color()) self.g.write(' priority="%d"' % tag.get_priority()) - self.g.write('/>\n') + self.g.write("/>\n") def fix(self, line): l = str(line) l = l.strip().translate(strip_dict) return escxml(l) - def write_note_list(self, note_list,indent=0): + def write_note_list(self, note_list, indent=0): for handle in note_list: - self.write_ref("noteref", handle,indent) + self.write_ref("noteref", handle, indent) def write_note(self, note, index=2): if not note: return - self.write_primary_tag('note', note, index, close=False) + self.write_primary_tag("note", note, index, close=False) ntype = escxml(note.get_type().xml_str()) format = note.get_format() @@ -475,273 +514,304 @@ class GrampsXmlWriter(UpdateCallback): self.g.write(' type="%s"' % ntype) if format != note.FLOWED: self.g.write(' format="%d"' % format) - self.g.write('>\n') + self.g.write(">\n") - self.write_text('text', text, index + 1) + self.write_text("text", text, index + 1) if styles: self.write_styles(styles, index + 1) for tag_handle in note.get_tag_list(): - self.write_ref("tagref", tag_handle, index+1) + self.write_ref("tagref", tag_handle, index + 1) - self.g.write(' ' * index + '\n') + self.g.write(" " * index + "\n") def write_styles(self, styles, index=3): for style in styles: name = style.name.xml_str() value = style.value - self.g.write(' ' * index + '\n') + self.g.write(" " * index + "\n") def write_text(self, val, text, indent=0): if not text: return if indent: - self.g.write(' ' * indent) + self.g.write(" " * indent) - self.g.write('<%s>' % val) + self.g.write("<%s>" % val) self.g.write(escxml(str(text).translate(strip_dict))) self.g.write("\n" % val) - def write_person(self,person,index=1): - sp = " "*index - self.write_primary_tag("person",person,index) + def write_person(self, person, index=1): + sp = " " * index + self.write_primary_tag("person", person, index) if person.get_gender() == Person.MALE: - self.write_line("gender","M",index+1) + self.write_line("gender", "M", index + 1) elif person.get_gender() == Person.FEMALE: self.write_line("gender","F",index+1) elif person.get_gender() == Person.OTHER: self.write_line("gender","X",index+1) else: - self.write_line("gender","U",index+1) - self.dump_name(person.get_primary_name(),False,index+1) + self.write_line("gender", "U", index + 1) + self.dump_name(person.get_primary_name(), False, index + 1) for name in person.get_alternate_names(): - self.dump_name(name,True,index+1) + self.dump_name(name, True, index + 1) - #self.dump_event_ref(person.get_birth_ref(),index+1) - #self.dump_event_ref(person.get_death_ref(),index+1) + # self.dump_event_ref(person.get_birth_ref(),index+1) + # self.dump_event_ref(person.get_death_ref(),index+1) for event_ref in person.get_event_ref_list(): - self.dump_event_ref(event_ref,index+1) + self.dump_event_ref(event_ref, index + 1) for lds_ord in person.lds_ord_list: - self.dump_ordinance(lds_ord,index+1) + self.dump_ordinance(lds_ord, index + 1) - self.write_media_list(person.get_media_list(),index+1) + self.write_media_list(person.get_media_list(), index + 1) - self.write_address_list(person,index+1) + self.write_address_list(person, index + 1) self.write_attribute_list(person.get_attribute_list()) - self.write_url_list(person.get_url_list(),index+1) + self.write_url_list(person.get_url_list(), index + 1) for family_handle in person.get_parent_family_handle_list(): - self.write_ref("childof",family_handle,index+1) + self.write_ref("childof", family_handle, index + 1) for family_handle in person.get_family_handle_list(): - self.write_ref("parentin",family_handle,index+1) + self.write_ref("parentin", family_handle, index + 1) for person_ref in person.get_person_ref_list(): - self.dump_person_ref(person_ref,index+1) + self.dump_person_ref(person_ref, index + 1) - self.write_note_list(person.get_note_list(),index+1) + self.write_note_list(person.get_note_list(), index + 1) for citation_handle in person.get_citation_list(): - self.write_ref("citationref", citation_handle, index+1) + self.write_ref("citationref", citation_handle, index + 1) for tag_handle in person.get_tag_list(): - self.write_ref("tagref", tag_handle, index+1) + self.write_ref("tagref", tag_handle, index + 1) self.g.write("%s\n" % sp) - def write_family(self,family,index=1): - sp = " "*index - self.write_family_handle(family,index) + def write_family(self, family, index=1): + sp = " " * index + self.write_family_handle(family, index) fhandle = family.get_father_handle() mhandle = family.get_mother_handle() if fhandle: - self.write_ref("father",fhandle,index+1) + self.write_ref("father", fhandle, index + 1) if mhandle: - self.write_ref("mother",mhandle,index+1) + self.write_ref("mother", mhandle, index + 1) for event_ref in family.get_event_ref_list(): - self.dump_event_ref(event_ref,3) + self.dump_event_ref(event_ref, 3) for lds_ord in family.lds_ord_list: - self.dump_ordinance(lds_ord,index+1) + self.dump_ordinance(lds_ord, index + 1) - self.write_media_list(family.get_media_list(),index+1) + self.write_media_list(family.get_media_list(), index + 1) for child_ref in family.get_child_ref_list(): - self.dump_child_ref(child_ref,index+1) + self.dump_child_ref(child_ref, index + 1) self.write_attribute_list(family.get_attribute_list()) - self.write_note_list(family.get_note_list(),index+1) + self.write_note_list(family.get_note_list(), index + 1) for citation_handle in family.get_citation_list(): - self.write_ref("citationref", citation_handle, index+1) + self.write_ref("citationref", citation_handle, index + 1) for tag_handle in family.get_tag_list(): - self.write_ref("tagref", tag_handle, index+1) + self.write_ref("tagref", tag_handle, index + 1) self.g.write("%s\n" % sp) def write_citation(self, citation, index=1): sp = " " * index self.write_primary_tag("citation", citation, index) - self.write_date(citation.get_date_object(), index+1) - self.write_line("page", citation.get_page(), index+1) - self.write_line_always("confidence", - citation.get_confidence_level(), index+1) - self.write_note_list(citation.get_note_list(), index+1) - self.write_media_list(citation.get_media_list(), index+1) - self.write_srcattribute_list(citation.get_attribute_list(), index+1) - self.write_ref("sourceref", citation.get_reference_handle(), index+1) + self.write_date(citation.get_date_object(), index + 1) + self.write_line("page", citation.get_page(), index + 1) + self.write_line_always("confidence", citation.get_confidence_level(), index + 1) + self.write_note_list(citation.get_note_list(), index + 1) + self.write_media_list(citation.get_media_list(), index + 1) + self.write_srcattribute_list(citation.get_attribute_list(), index + 1) + self.write_ref("sourceref", citation.get_reference_handle(), index + 1) for tag_handle in citation.get_tag_list(): - self.write_ref("tagref", tag_handle, index+1) + self.write_ref("tagref", tag_handle, index + 1) self.g.write("%s\n" % sp) def write_source(self, source, index=1): - sp = " "*index + sp = " " * index self.write_primary_tag("source", source, index) - self.write_force_line("stitle", source.get_title(), index+1) - self.write_line("sauthor", source.get_author(), index+1) - self.write_line("spubinfo", source.get_publication_info(), index+1) - self.write_line("sabbrev", source.get_abbreviation(), index+1) - self.write_note_list(source.get_note_list(), index+1) - self.write_media_list(source.get_media_list(), index+1) - self.write_srcattribute_list(source.get_attribute_list(), index+1) - self.write_reporef_list(source.get_reporef_list(), index+1) + self.write_force_line("stitle", source.get_title(), index + 1) + self.write_line("sauthor", source.get_author(), index + 1) + self.write_line("spubinfo", source.get_publication_info(), index + 1) + self.write_line("sabbrev", source.get_abbreviation(), index + 1) + self.write_note_list(source.get_note_list(), index + 1) + self.write_media_list(source.get_media_list(), index + 1) + self.write_srcattribute_list(source.get_attribute_list(), index + 1) + self.write_reporef_list(source.get_reporef_list(), index + 1) for tag_handle in source.get_tag_list(): - self.write_ref("tagref", tag_handle, index+1) + self.write_ref("tagref", tag_handle, index + 1) self.g.write("%s\n" % sp) - def write_repository(self,repo,index=1): - sp = " "*index - self.write_primary_tag("repository",repo,index) - #name - self.write_line('rname',repo.name,index+1) + def write_repository(self, repo, index=1): + sp = " " * index + self.write_primary_tag("repository", repo, index) + # name + self.write_line("rname", repo.name, index + 1) rtype = repo.type.xml_str() if rtype: - self.write_line('type',rtype,index+1) - #address list - self.write_address_list(repo,index+1) + self.write_line("type", rtype, index + 1) + # address list + self.write_address_list(repo, index + 1) # url list - self.write_url_list(repo.get_url_list(),index+1) - self.write_note_list(repo.get_note_list(),index+1) + self.write_url_list(repo.get_url_list(), index + 1) + self.write_note_list(repo.get_note_list(), index + 1) for tag_handle in repo.get_tag_list(): - self.write_ref("tagref", tag_handle, index+1) + self.write_ref("tagref", tag_handle, index + 1) self.g.write("%s\n" % sp) - def write_address_list(self, obj,index=1): + def write_address_list(self, obj, index=1): if len(obj.get_address_list()) == 0: return - sp = " "*index + sp = " " * index for address in obj.get_address_list(): - self.g.write('%s\n' % (sp,conf_priv(address))) - self.write_date(address.get_date_object(),index+1) - self.write_line("street",address.get_street(),index+1) - self.write_line("locality",address.get_locality(),index+1) - self.write_line("city",address.get_city(),index+1) - self.write_line("county",address.get_county(),index+1) - self.write_line("state",address.get_state(),index+1) - self.write_line("country",address.get_country(),index+1) - self.write_line("postal",address.get_postal_code(),index+1) - self.write_line("phone",address.get_phone(),index+1) - self.write_note_list(address.get_note_list(),index+1) + self.g.write("%s\n" % (sp, conf_priv(address))) + self.write_date(address.get_date_object(), index + 1) + self.write_line("street", address.get_street(), index + 1) + self.write_line("locality", address.get_locality(), index + 1) + self.write_line("city", address.get_city(), index + 1) + self.write_line("county", address.get_county(), index + 1) + self.write_line("state", address.get_state(), index + 1) + self.write_line("country", address.get_country(), index + 1) + self.write_line("postal", address.get_postal_code(), index + 1) + self.write_line("phone", address.get_phone(), index + 1) + self.write_note_list(address.get_note_list(), index + 1) for citation_handle in address.get_citation_list(): - self.write_ref("citationref", citation_handle, index+1) - self.g.write('%s\n' % sp) + self.write_ref("citationref", citation_handle, index + 1) + self.g.write("%s\n" % sp) - def dump_person_ref(self,personref,index=1): + def dump_person_ref(self, personref, index=1): if not personref or not personref.ref: return - sp = " "*index + sp = " " * index priv_text = conf_priv(personref) rel_text = ' rel="%s"' % escxml(personref.get_relation()) citation_list = personref.get_citation_list() nreflist = personref.get_note_list() - if (len(citation_list) + len(nreflist) == 0): - self.write_ref('personref',personref.ref,index,close=True, - extra_text=priv_text+rel_text) + if len(citation_list) + len(nreflist) == 0: + self.write_ref( + "personref", + personref.ref, + index, + close=True, + extra_text=priv_text + rel_text, + ) else: - self.write_ref('personref',personref.ref,index,close=False, - extra_text=priv_text+rel_text) + self.write_ref( + "personref", + personref.ref, + index, + close=False, + extra_text=priv_text + rel_text, + ) for citation_handle in citation_list: - self.write_ref("citationref", citation_handle, index+1) + self.write_ref("citationref", citation_handle, index + 1) - self.write_note_list(nreflist,index+1) - self.g.write('%s\n' % sp) + self.write_note_list(nreflist, index + 1) + self.g.write("%s\n" % sp) - def dump_child_ref(self,childref,index=1): + def dump_child_ref(self, childref, index=1): if not childref or not childref.ref: return - sp = " "*index + sp = " " * index priv_text = conf_priv(childref) if childref.frel.is_default(): - frel_text = '' + frel_text = "" else: frel_text = ' frel="%s"' % escxml(childref.frel.xml_str()) if childref.mrel.is_default(): - mrel_text = '' + mrel_text = "" else: mrel_text = ' mrel="%s"' % escxml(childref.mrel.xml_str()) citation_list = childref.get_citation_list() nreflist = childref.get_note_list() - if (len(citation_list)+len(nreflist) == 0): - self.write_ref('childref',childref.ref,index,close=True, - extra_text=priv_text+mrel_text+frel_text) + if len(citation_list) + len(nreflist) == 0: + self.write_ref( + "childref", + childref.ref, + index, + close=True, + extra_text=priv_text + mrel_text + frel_text, + ) else: - self.write_ref('childref',childref.ref,index,close=False, - extra_text=priv_text+mrel_text+frel_text) + self.write_ref( + "childref", + childref.ref, + index, + close=False, + extra_text=priv_text + mrel_text + frel_text, + ) for citation_handle in citation_list: - self.write_ref("citationref", citation_handle, index+1) - self.write_note_list(nreflist,index+1) - self.g.write('%s\n' % sp) + self.write_ref("citationref", citation_handle, index + 1) + self.write_note_list(nreflist, index + 1) + self.g.write("%s\n" % sp) - def dump_event_ref(self,eventref,index=1): + def dump_event_ref(self, eventref, index=1): if not eventref or not eventref.ref: return - sp = " "*index + sp = " " * index priv_text = conf_priv(eventref) role = escxml(eventref.role.xml_str()) if role: role_text = ' role="%s"' % role else: - role_text = '' + role_text = "" attribute_list = eventref.get_attribute_list() note_list = eventref.get_note_list() - if (len(attribute_list) + len(note_list) == 0): - self.write_ref('eventref',eventref.ref,index, - close=True,extra_text=priv_text+role_text) + if len(attribute_list) + len(note_list) == 0: + self.write_ref( + "eventref", + eventref.ref, + index, + close=True, + extra_text=priv_text + role_text, + ) else: - self.write_ref('eventref',eventref.ref,index, - close=False,extra_text=priv_text+role_text) - self.write_attribute_list(attribute_list,index+1) - self.write_note_list(note_list,index+1) - self.g.write('%s\n' % sp) + self.write_ref( + "eventref", + eventref.ref, + index, + close=False, + extra_text=priv_text + role_text, + ) + self.write_attribute_list(attribute_list, index + 1) + self.write_note_list(note_list, index + 1) + self.g.write("%s\n" % sp) def dump_place_ref(self, placeref, index=1): sp = " " * index date = placeref.get_date_object() if date.is_empty(): - self.write_ref('placeref', placeref.ref, index, close=True) + self.write_ref("placeref", placeref.ref, index, close=True) else: - self.write_ref('placeref', placeref.ref, index, close=False) - self.write_date(date, index+1) - self.g.write('%s\n' % sp) + self.write_ref("placeref", placeref.ref, index, close=False) + self.write_date(date, index + 1) + self.g.write("%s\n" % sp) def dump_place_name(self, place_name, index=1): sp = " " * index @@ -752,71 +822,73 @@ class GrampsXmlWriter(UpdateCallback): if lang: self.g.write(' lang="%s"' % self.fix(lang)) if date.is_empty(): - self.g.write('/>\n') + self.g.write("/>\n") else: - self.g.write('>\n') - self.write_date(date, index+1) - self.g.write('%s\n' % sp) + self.g.write(">\n") + self.write_date(date, index + 1) + self.g.write("%s\n" % sp) - def write_event(self,event,index=1): + def write_event(self, event, index=1): if not event: return - self.write_primary_tag("event",event,2) + self.write_primary_tag("event", event, 2) sp = " " * index etype = event.get_type().xml_str() - self.g.write(' %s%s\n' % (sp,self.fix(etype)) ) - self.write_date(event.get_date_object(),index+1) - self.write_ref("place",event.get_place_handle(),index+1) - self.write_line("description",event.get_description(),index+1) - self.write_attribute_list(event.get_attribute_list(),index+1) - self.write_note_list(event.get_note_list(),index+1) + self.g.write(" %s%s\n" % (sp, self.fix(etype))) + self.write_date(event.get_date_object(), index + 1) + self.write_ref("place", event.get_place_handle(), index + 1) + self.write_line("description", event.get_description(), index + 1) + self.write_attribute_list(event.get_attribute_list(), index + 1) + self.write_note_list(event.get_note_list(), index + 1) for citation_handle in event.get_citation_list(): - self.write_ref("citationref", citation_handle, index+1) - self.write_media_list(event.get_media_list(),index+1) + self.write_ref("citationref", citation_handle, index + 1) + self.write_media_list(event.get_media_list(), index + 1) for tag_handle in event.get_tag_list(): - self.write_ref("tagref", tag_handle, index+1) + self.write_ref("tagref", tag_handle, index + 1) self.g.write("%s\n" % sp) - def dump_ordinance(self, ord,index=1): + def dump_ordinance(self, ord, index=1): name = ord.type2xml() sp = " " * index - sp2 = " " * (index+1) + sp2 = " " * (index + 1) priv = conf_priv(ord) - self.g.write('%s\n' % (sp, name,priv)) + self.g.write('%s\n' % (sp, name, priv)) dateobj = ord.get_date_object() if dateobj and not dateobj.is_empty(): - self.write_date(dateobj,index+1) + self.write_date(dateobj, index + 1) if ord.get_temple(): - self.g.write('%s\n' - % (sp2,self.fix(ord.get_temple()))) - self.write_ref("place", ord.get_place_handle(),index+1) + self.g.write('%s\n' % (sp2, self.fix(ord.get_temple()))) + self.write_ref("place", ord.get_place_handle(), index + 1) if ord.get_status() != 0: self.g.write('%s\n' % (sp2, ord.status2xml())) if ord.get_family_handle(): - self.g.write('%s\n' % - (sp2,"_"+ord.get_family_handle())) - self.write_note_list(ord.get_note_list(),index+1) + self.g.write( + '%s\n' % (sp2, "_" + ord.get_family_handle()) + ) + self.write_note_list(ord.get_note_list(), index + 1) for citation_handle in ord.get_citation_list(): - self.write_ref("citationref", citation_handle, index+1) - self.g.write('%s\n' % sp) + self.write_ref("citationref", citation_handle, index + 1) + self.g.write("%s\n" % sp) - def write_ref(self,tagname, handle,index=1,close=True,extra_text=''): + def write_ref(self, tagname, handle, index=1, close=True, extra_text=""): if handle: if close: close_tag = "/" else: close_tag = "" - sp = " "*index - self.g.write('%s<%s hlink="_%s"%s%s>\n' - % (sp,tagname, handle,extra_text,close_tag)) + sp = " " * index + self.g.write( + '%s<%s hlink="_%s"%s%s>\n' + % (sp, tagname, handle, extra_text, close_tag) + ) def write_primary_tag(self, tagname, obj, index=1, close=True): """ @@ -830,7 +902,7 @@ class GrampsXmlWriter(UpdateCallback): self.write_table_tag(tagname, obj, index, False) self.g.write(id_text + priv_text) if close: - self.g.write('>\n') + self.g.write(">\n") def write_table_tag(self, tagname, obj, index=1, close=True): """ @@ -840,24 +912,24 @@ class GrampsXmlWriter(UpdateCallback): return sp = " " * index try: - change_text = ' change="%d"' % obj.get_change_time() + change_text = ' change="%d"' % obj.get_change_time() except: - change_text = ' change="%d"' % 0 + change_text = ' change="%d"' % 0 handle_text = ' handle="_%s"' % obj.get_handle() - obj_text = '%s<%s' % (sp, tagname) + obj_text = "%s<%s" % (sp, tagname) self.g.write(obj_text + handle_text + change_text) if close: - self.g.write('>\n') + self.g.write(">\n") - def write_family_handle(self,family,index=1): - sp = " "*index - self.write_primary_tag('family',family,index) + def write_family_handle(self, family, index=1): + sp = " " * index + self.write_primary_tag("family", family, index) if family: rel = escxml(family.get_relationship().xml_str()) if rel != "": - self.g.write(' %s\n' % (sp,rel) ) + self.g.write(' %s\n' % (sp, rel)) def write_surname(self, surname, indent=1): """ @@ -868,7 +940,7 @@ class GrampsXmlWriter(UpdateCallback): nam = surname.get_surname() der = surname.get_origintype().xml_str() pri = surname.get_primary() - self.g.write('%s%s\n' % self.fix(nam)) + self.g.write(">%s\n" % self.fix(nam)) - def write_line(self,tagname,value,indent=1): + def write_line(self, tagname, value, indent=1): if value: - self.g.write('%s<%s>%s\n' % - (' '*indent,tagname,self.fix(value),tagname)) + self.g.write( + "%s<%s>%s\n" % (" " * indent, tagname, self.fix(value), tagname) + ) - def write_line_nofix(self,tagname,value,indent=1): + def write_line_nofix(self, tagname, value, indent=1): """Writes a line, but does not escape characters. - Use this instead of write_line if the value is already fixed, - this avoids & becoming &amp; + Use this instead of write_line if the value is already fixed, + this avoids & becoming &amp; """ if value: - self.g.write('%s<%s>%s\n' % - (' '*indent, tagname, value, tagname)) + self.g.write("%s<%s>%s\n" % (" " * indent, tagname, value, tagname)) - def write_line_always(self,tagname,value,indent=1): + def write_line_always(self, tagname, value, indent=1): """Writes a line, always, even with a zero value.""" - self.g.write('%s<%s>%s\n' % - (' '*indent,tagname,self.fix(value),tagname)) + self.g.write( + "%s<%s>%s\n" % (" " * indent, tagname, self.fix(value), tagname) + ) - def get_iso_date(self,date): + def get_iso_date(self, date): if date[2] == 0: y = "????" else: @@ -913,24 +986,24 @@ class GrampsXmlWriter(UpdateCallback): else: m = "-%02d" % (date[1]) if date[0] == 0: - d = '' + d = "" else: d = "-%02d" % date[0] - ret = "%s%s%s" % (y,m,d) + ret = "%s%s%s" % (y, m, d) # If the result does not contain anything beyond dashes # and question marks then it's as good as empty - if ret.replace('-','').replace('?','') == '': - ret = '' + if ret.replace("-", "").replace("?", "") == "": + ret = "" return ret - def write_date(self,date,indent=1): - sp = ' '*indent + def write_date(self, date, indent=1): + sp = " " * indent - cal= date.get_calendar() + cal = date.get_calendar() if cal != Date.CAL_GREGORIAN: calstr = ' cformat="%s"' % Date.calendar_names[cal] else: - calstr = '' + calstr = "" qual = date.get_quality() if qual == Date.QUAL_ESTIMATED: @@ -944,28 +1017,38 @@ class GrampsXmlWriter(UpdateCallback): if dualdated: dualdated_str = ' dualdated="1"' else: - dualdated_str = '' + dualdated_str = "" newyear = date.newyear_to_str() if newyear: newyear_str = ' newyear="%s"' % newyear else: - newyear_str = '' + newyear_str = "" mode = date.get_modifier() if date.is_compound(): if mode == Date.MOD_RANGE: - tagname = 'daterange' + tagname = "daterange" else: - tagname = 'datespan' + tagname = "datespan" d1 = self.get_iso_date(date.get_start_date()) d2 = self.get_iso_date(date.get_stop_date()) if d1 != "" or d2 != "": - self.g.write('%s<%s start="%s" stop="%s"%s%s%s%s/>\n' - % (sp,tagname,d1,d2,qual_str,calstr, - dualdated_str, newyear_str)) + self.g.write( + '%s<%s start="%s" stop="%s"%s%s%s%s/>\n' + % ( + sp, + tagname, + d1, + d2, + qual_str, + calstr, + dualdated_str, + newyear_str, + ) + ) elif mode != Date.MOD_TEXTONLY: date_str = self.get_iso_date(date.get_start_date()) if date_str == "": @@ -977,29 +1060,35 @@ class GrampsXmlWriter(UpdateCallback): mode_str = ' type="after"' elif mode == Date.MOD_ABOUT: mode_str = ' type="about"' + elif mode == Date.MOD_FROM: + mode_str = ' type="from"' + elif mode == Date.MOD_TO: + mode_str = ' type="to"' else: mode_str = "" - self.g.write('%s\n' - % (sp, date_str, mode_str, qual_str, - calstr, dualdated_str, newyear_str)) + self.g.write( + '%s\n' + % (sp, date_str, mode_str, qual_str, calstr, dualdated_str, newyear_str) + ) else: - self.g.write('%s\n' - %(sp,self.fix(date.get_text()))) + self.g.write('%s\n' % (sp, self.fix(date.get_text()))) - def write_force_line(self,label,value,indent=1): + def write_force_line(self, label, value, indent=1): if value is not None: - self.g.write('%s<%s>%s\n' % (' '*indent,label,self.fix(value),label)) + self.g.write( + "%s<%s>%s\n" % (" " * indent, label, self.fix(value), label) + ) - def dump_name(self, name,alternative=False,index=1): - sp = " "*index + def dump_name(self, name, alternative=False, index=1): + sp = " " * index name_type = name.get_type().xml_str() # bug 9242 if len(name.get_first_name().splitlines()) != 1: firstname = "".join(name.get_first_name().splitlines()) else: firstname = name.get_first_name() - self.g.write('%s\n') - self.write_line("first", firstname, index+1) - self.write_line("call", name.get_call_name(), index+1) + self.g.write(">\n") + self.write_line("first", firstname, index + 1) + self.write_line("call", name.get_call_name(), index + 1) for surname in name.get_surname_list(): - self.write_surname(surname,index+1) - self.write_line("suffix", name.get_suffix(), index+1) - self.write_line("title", name.get_title(), index+1) - self.write_line("nick", name.get_nick_name(), index+1) - self.write_line("familynick", name.get_family_nick_name(), index+1) - self.write_line("group", name.get_group_as(), index+1) + self.write_surname(surname, index + 1) + self.write_line("suffix", name.get_suffix(), index + 1) + self.write_line("title", name.get_title(), index + 1) + self.write_line("nick", name.get_nick_name(), index + 1) + self.write_line("familynick", name.get_family_nick_name(), index + 1) + self.write_line("group", name.get_group_as(), index + 1) if name.date: - self.write_date(name.date,4) - self.write_note_list(name.get_note_list(),index+1) + self.write_date(name.date, 4) + self.write_note_list(name.get_note_list(), index + 1) for citation_handle in name.get_citation_list(): - self.write_ref("citationref", citation_handle, index+1) + self.write_ref("citationref", citation_handle, index + 1) - self.g.write('%s\n' % sp) + self.g.write("%s\n" % sp) - def append_value(self, orig,val): + def append_value(self, orig, val): if orig: - return "%s, %s" % (orig,val) + return "%s, %s" % (orig, val) else: return val - def build_place_title(self,loc): + def build_place_title(self, loc): "Builds a title from a location" street = self.fix(loc.get_street()) locality = self.fix(loc.get_locality()) @@ -1062,7 +1151,7 @@ class GrampsXmlWriter(UpdateCallback): value = self.append_value(value, country) return value - def dump_location(self,loc): + def dump_location(self, loc): "Writes the location information to the output file" if loc.is_empty(): return @@ -1076,7 +1165,7 @@ class GrampsXmlWriter(UpdateCallback): zip_code = self.fix(loc.get_postal_code()) phone = self.fix(loc.get_phone()) - self.g.write(' \n') + self.g.write("/>\n") def write_attribute_list(self, list, indent=3): - sp = ' ' * indent + sp = " " * indent for attr in list: - self.g.write('%s\n') + if (len(nlist) + len(citation_list)) == 0: + self.g.write("/>\n") else: - self.g.write('>\n') + self.g.write(">\n") for citation_handle in citation_list: - self.write_ref("citationref", citation_handle, indent+1) - self.write_note_list(attr.get_note_list(),indent+1) - self.g.write('%s\n' % sp) + self.write_ref("citationref", citation_handle, indent + 1) + self.write_note_list(attr.get_note_list(), indent + 1) + self.g.write("%s\n" % sp) def write_srcattribute_list(self, list, indent=3): - sp = ' ' * indent + sp = " " * indent for srcattr in list: - self.g.write('%s\n') + self.g.write( + '%s\n") - def write_media_list(self,list,indent=3): - sp = ' '*indent + def write_media_list(self, list, indent=3): + sp = " " * indent for photo in list: mobj_id = photo.get_reference_handle() - self.g.write('%s\n") else: self.g.write(">\n") - if rect is not None : - self.g.write(' %s\n' % ( - sp, - corner1_x, - corner1_y, - corner2_x, - corner2_y - ) - ) - self.write_attribute_list(proplist,indent+1) + if rect is not None: + self.g.write( + ' %s\n' + % (sp, corner1_x, corner1_y, corner2_x, corner2_y) + ) + self.write_attribute_list(proplist, indent + 1) for citation_handle in citation_list: - self.write_ref("citationref", citation_handle, indent+1) - self.write_note_list(nreflist, indent+1) - self.g.write('%s\n' % sp) + self.write_ref("citationref", citation_handle, indent + 1) + self.write_note_list(nreflist, indent + 1) + self.g.write("%s\n" % sp) def write_reporef_list(self, rrlist, index=1): for reporef in rrlist: @@ -1178,10 +1278,10 @@ class GrampsXmlWriter(UpdateCallback): if reporef.get_privacy(): priv_text = ' priv="1"' else: - priv_text = '' + priv_text = "" if reporef.call_number == "": - callno_text = '' + callno_text = "" else: callno_text = ' callno="%s"' % escxml(reporef.call_number) @@ -1189,76 +1289,81 @@ class GrampsXmlWriter(UpdateCallback): if mtype: type_text = ' medium="%s"' % escxml(mtype) else: - type_text = '' + type_text = "" note_list = reporef.get_note_list() - if len(note_list) == 0: - self.write_ref('reporef', reporef.ref, index, close=True, - extra_text=priv_text+callno_text+type_text) + if len(note_list) == 0: + self.write_ref( + "reporef", + reporef.ref, + index, + close=True, + extra_text=priv_text + callno_text + type_text, + ) else: - self.write_ref('reporef', reporef.ref, index, close=False, - extra_text=priv_text+callno_text+type_text) - self.write_note_list(note_list, index+1) - sp = " "*index - self.g.write('%s\n' % sp) + self.write_ref( + "reporef", + reporef.ref, + index, + close=False, + extra_text=priv_text + callno_text + type_text, + ) + self.write_note_list(note_list, index + 1) + sp = " " * index + self.g.write("%s\n" % sp) def write_url_list(self, list, index=1): - sp = " "*index + sp = " " * index for url in list: url_type = url.get_type().xml_str() if url_type: type_text = ' type="%s"' % escxml(url_type) else: - type_text = '' + type_text = "" priv_text = conf_priv(url) if url.get_description() != "": - desc_text = ' description="%s"' % self.fix( - url.get_description()) + desc_text = ' description="%s"' % self.fix(url.get_description()) else: - desc_text = '' + desc_text = "" path_text = ' href="%s"' % self.fix(url.get_path()) - self.g.write('%s\n' % ( - sp, - priv_text, - path_text, - type_text, - desc_text - ) - ) + self.g.write( + "%s\n" % (sp, priv_text, path_text, type_text, desc_text) + ) def write_place_obj(self, place, index=1): self.write_primary_tag("placeobj", place, index, close=False) ptype = self.fix(place.get_type().xml_str()) self.g.write(' type="%s"' % ptype) - self.g.write('>\n') + self.g.write(">\n") title = self.fix(place.get_title()) code = self.fix(place.get_code()) - self.write_line_nofix("ptitle", title, index+1) - self.write_line_nofix("code", code, index+1) + self.write_line_nofix("ptitle", title, index + 1) + self.write_line_nofix("code", code, index + 1) - self.dump_place_name(place.get_name(), index+1) + self.dump_place_name(place.get_name(), index + 1) for pname in place.get_alternative_names(): - self.dump_place_name(pname, index+1) + self.dump_place_name(pname, index + 1) longitude = self.fix(place.get_longitude()) lat = self.fix(place.get_latitude()) if longitude or lat: - self.g.write('%s\n' - % (" "*(index+1), longitude, lat)) + self.g.write( + '%s\n' % (" " * (index + 1), longitude, lat) + ) for placeref in place.get_placeref_list(): - self.dump_place_ref(placeref, index+1) + self.dump_place_ref(placeref, index + 1) list(map(self.dump_location, place.get_alternate_locations())) - self.write_media_list(place.get_media_list(), index+1) + self.write_media_list(place.get_media_list(), index + 1) self.write_url_list(place.get_url_list()) - self.write_note_list(place.get_note_list(), index+1) + self.write_note_list(place.get_note_list(), index + 1) for citation_handle in place.get_citation_list(): - self.write_ref("citationref", citation_handle, index+1) + self.write_ref("citationref", citation_handle, index + 1) for tag_handle in place.get_tag_list(): - self.write_ref("tagref", tag_handle, index+1) + self.write_ref("tagref", tag_handle, index + 1) - self.g.write("%s\n" % (" "*index)) + self.g.write("%s\n" % (" " * index)) def write_object(self, obj, index=1): self.write_primary_tag("object", obj, index) @@ -1269,43 +1374,51 @@ class GrampsXmlWriter(UpdateCallback): if desc: desc_text = ' description="%s"' % self.fix(desc) else: - desc_text = '' + desc_text = "" checksum = obj.get_checksum() if checksum: checksum_text = ' checksum="%s"' % checksum else: - checksum_text = '' + checksum_text = "" if self.strip_photos == 1: path = os.path.basename(path) - elif self.strip_photos == 2 and (len(path)>0 and os.path.isabs(path)): + elif self.strip_photos == 2 and (len(path) > 0 and os.path.isabs(path)): drive, path = os.path.splitdrive(path) path = path[1:] if win(): # Always export path with \ replaced with /. Otherwise import # from Windows to Linux of gpkg's path to images does not work. - path = path.replace('\\','/') - self.g.write('%s\n' - % (" "*(index+1), self.fix(path), self.fix(mime_type), - checksum_text, desc_text)) + path = path.replace("\\", "/") + self.g.write( + '%s\n' + % ( + " " * (index + 1), + self.fix(path), + self.fix(mime_type), + checksum_text, + desc_text, + ) + ) self.write_attribute_list(obj.get_attribute_list()) - self.write_note_list(obj.get_note_list(), index+1) + self.write_note_list(obj.get_note_list(), index + 1) dval = obj.get_date_object() if not dval.is_empty(): - self.write_date(dval, index+1) + self.write_date(dval, index + 1) for citation_handle in obj.get_citation_list(): - self.write_ref("citationref", citation_handle, index+1) + self.write_ref("citationref", citation_handle, index + 1) for tag_handle in obj.get_tag_list(): - self.write_ref("tagref", tag_handle, index+1) + self.write_ref("tagref", tag_handle, index + 1) - self.g.write("%s\n" % (" "*index)) + self.g.write("%s\n" % (" " * index)) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # # -#------------------------------------------------------------------------- -def sortById(first,second): +# ------------------------------------------------------------------------- +def sortById(first, second): fid = first.get_gramps_id() sid = second.get_gramps_id() @@ -1314,22 +1427,24 @@ def sortById(first,second): else: return fid != sid -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- def conf_priv(obj): if obj.get_privacy() != 0: return ' priv="%d"' % obj.get_privacy() else: - return '' + return "" -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # export_data # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- def export_data(database, filename, user, option_box=None): """ Call the XML writer with the syntax expected by the export plugin. @@ -1351,26 +1466,26 @@ def export_data(database, filename, user, option_box=None): g = XmlWriter(database, user, 0, compress) return g.write(filename) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # # XmlWriter # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class XmlWriter(GrampsXmlWriter): """ Writes a database to the XML file. """ def __init__(self, dbase, user, strip_photos, compress=1): - GrampsXmlWriter.__init__( - self, dbase, strip_photos, compress, VERSION, user) + GrampsXmlWriter.__init__(self, dbase, strip_photos, compress, VERSION, user) self.user = user def write(self, filename): """ Write the database to the specified file. """ - ret = 0 #False + ret = 0 # False try: ret = GrampsXmlWriter.write(self, filename) except DbWriteFailure as msg: diff --git a/gramps/plugins/importer/importgeneweb.py b/gramps/plugins/importer/importgeneweb.py index 784054cf7..39dcc42c7 100644 --- a/gramps/plugins/importer/importgeneweb.py +++ b/gramps/plugins/importer/importgeneweb.py @@ -22,31 +22,33 @@ "Import from GeneWeb" -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # standard python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import re import time -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ # # Set up logging # -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ import logging + LOG = logging.getLogger(".ImportGeneWeb") -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from gramps.gen.const import GRAMPS_LOCALE as glocale from gramps.gen.utils.libformatting import ImportInfo + _ = glocale.translation.gettext -ngettext = glocale.translation.ngettext # else "nearby" comments are ignored +ngettext = glocale.translation.ngettext # else "nearby" comments are ignored from gramps.gen.errors import GedcomError, GrampsImportError from gramps.gen.lib import (Attribute, AttributeType, ChildRef, Citation, Date, DateError, Event, EventRef, EventRoleType, EventType, @@ -56,123 +58,127 @@ from gramps.gen.db import DbTxn from html.entities import name2codepoint _date_parse = re.compile( - r'([kmes~?<>]+)?([0-9/]+)([J|H|F])?(\.\.)?([0-9/]+)?([J|H|F])?') -_text_parse = re.compile(r'0\((.*)\)') + r"([kmes~?<>]+)?([0-9/]+)([J|H|F])?(\.\.)?([0-9/]+)?([J|H|F])?" +) +_text_parse = re.compile(r"0\((.*)\)") _mod_map = { - '>' : Date.MOD_AFTER, - '<' : Date.MOD_BEFORE, - '~' : Date.MOD_ABOUT, - } + ">": Date.MOD_AFTER, + "<": Date.MOD_BEFORE, + "~": Date.MOD_ABOUT, +} _cal_map = { - 'J' : Date.CAL_JULIAN, - 'H' : Date.CAL_HEBREW, - 'F' : Date.CAL_FRENCH, - } + "J": Date.CAL_JULIAN, + "H": Date.CAL_HEBREW, + "F": Date.CAL_FRENCH, +} pevents_map = { - "#birt" : EventType.BIRTH, #Epers_Birth - "#bapt" : EventType.BAPTISM, #Epers_Baptism - "#deat" : EventType.DEATH, #Epers_Death - "#buri" : EventType.BURIAL, #Epers_Burial - "#crem" : EventType.CREMATION, - "#acco" : EventType((EventType.CUSTOM, _('Accomplishment'))) , - "#acqu" : EventType((EventType.CUSTOM, _('Acquisition'))), - "#adhe" : EventType((EventType.CUSTOM, _('Adhesion'))), - "#awar" : EventType((EventType.CUSTOM, _('Award'))), - "#bapl" : LdsOrd.BAPTISM, #Epers_BaptismLDS - "#barm" : EventType.BAR_MITZVAH, #Epers_BarMitzvah - "#basm" : EventType.BAS_MITZVAH, #Epers_BatMitzvah - "#bles" : EventType.BLESS, #Epers_Benediction - "#cens" : EventType.CENSUS, - "#chgn" : EventType((EventType.CUSTOM, _('Change Name'))), - "#circ" : EventType((EventType.CUSTOM, _('Circumcision'))), - "#conf" : EventType.CONFIRMATION, #Epers_Confirmation - "#conl" : LdsOrd.CONFIRMATION, #Epers_ConfirmationLDS - "#degr" : EventType.DEGREE, - "#demm" : EventType((EventType.CUSTOM, _('Military Demobilisation'))), - "#dist" : EventType((EventType.CUSTOM, _('Award'))), - "#dotl" : LdsOrd.ENDOWMENT, #Epers_DotationLDS - "#educ" : EventType.EDUCATION, #Epers_Education - "#elec" : EventType.ELECTED, #Epers_Election - "#emig" : EventType.EMIGRATION, - "#endl" : EventType((EventType.CUSTOM, _('Dotation'))), - "#exco" : EventType((EventType.CUSTOM, _('Excommunication'))), - "#fcom" : EventType.FIRST_COMMUN, - "#flkl" : EventType((EventType.CUSTOM, _('LDS Family Link'))), - "#fune" : EventType((EventType.CUSTOM, _('Funeral'))), - "#grad" : EventType.GRADUATION, - "#hosp" : EventType((EventType.CUSTOM, _('Hospitalisation'))), - "#illn" : EventType((EventType.CUSTOM, _('Illness'))), - "#immi" : EventType.IMMIGRATION, - "#lpas" : EventType((EventType.CUSTOM, _('List Passenger'))), - "#mdis" : EventType((EventType.CUSTOM, _('Military Distinction'))), - "#mobm" : EventType((EventType.CUSTOM, _('Militaty Mobilisation'))), - "#mpro" : EventType((EventType.CUSTOM, _('Military Promotion'))), - "#mser" : EventType.MILITARY_SERV, #Epers_MilitaryService - "#natu" : EventType.NATURALIZATION, #Epers_Naturalisation - "#occu" : EventType.OCCUPATION, #Epers_Occupation - "#ordn" : EventType.ORDINATION, #Epers_Ordination - "#prop" : EventType.PROPERTY, #Epers_Property - "#resi" : EventType.RESIDENCE, #Epers_Residence - "#reti" : EventType.RETIREMENT, - "#slgc" : EventType((EventType.CUSTOM, _('LDS Seal to child'))), #Epers_ScellentChildLDS - "#slgp" : LdsOrd.SEAL_TO_PARENTS, #Epers_ScellentParentLDS - "#slgs" : LdsOrd.SEAL_TO_SPOUSE, - "#vteb" : EventType((EventType.CUSTOM, _('Sold property'))), #Epers_VenteBien - "#will" : EventType.WILL, #Epers_Will - } + "#birt": EventType.BIRTH, # Epers_Birth + "#bapt": EventType.BAPTISM, # Epers_Baptism + "#deat": EventType.DEATH, # Epers_Death + "#buri": EventType.BURIAL, # Epers_Burial + "#crem": EventType.CREMATION, + "#acco": EventType((EventType.CUSTOM, _("Accomplishment"))), + "#acqu": EventType((EventType.CUSTOM, _("Acquisition"))), + "#adhe": EventType((EventType.CUSTOM, _("Adhesion"))), + "#awar": EventType((EventType.CUSTOM, _("Award"))), + "#bapl": LdsOrd.BAPTISM, # Epers_BaptismLDS + "#barm": EventType.BAR_MITZVAH, # Epers_BarMitzvah + "#basm": EventType.BAS_MITZVAH, # Epers_BatMitzvah + "#bles": EventType.BLESS, # Epers_Benediction + "#cens": EventType.CENSUS, + "#chgn": EventType((EventType.CUSTOM, _("Change Name"))), + "#circ": EventType((EventType.CUSTOM, _("Circumcision"))), + "#conf": EventType.CONFIRMATION, # Epers_Confirmation + "#conl": LdsOrd.CONFIRMATION, # Epers_ConfirmationLDS + "#degr": EventType.DEGREE, + "#demm": EventType((EventType.CUSTOM, _("Military Demobilisation"))), + "#dist": EventType((EventType.CUSTOM, _("Award"))), + "#dotl": LdsOrd.ENDOWMENT, # Epers_DotationLDS + "#educ": EventType.EDUCATION, # Epers_Education + "#elec": EventType.ELECTED, # Epers_Election + "#emig": EventType.EMIGRATION, + "#endl": EventType((EventType.CUSTOM, _("Dotation"))), + "#exco": EventType((EventType.CUSTOM, _("Excommunication"))), + "#fcom": EventType.FIRST_COMMUN, + "#flkl": EventType((EventType.CUSTOM, _("LDS Family Link"))), + "#fune": EventType((EventType.CUSTOM, _("Funeral"))), + "#grad": EventType.GRADUATION, + "#hosp": EventType((EventType.CUSTOM, _("Hospitalisation"))), + "#illn": EventType((EventType.CUSTOM, _("Illness"))), + "#immi": EventType.IMMIGRATION, + "#lpas": EventType((EventType.CUSTOM, _("List Passenger"))), + "#mdis": EventType((EventType.CUSTOM, _("Military Distinction"))), + "#mobm": EventType((EventType.CUSTOM, _("Militaty Mobilisation"))), + "#mpro": EventType((EventType.CUSTOM, _("Military Promotion"))), + "#mser": EventType.MILITARY_SERV, # Epers_MilitaryService + "#natu": EventType.NATURALIZATION, # Epers_Naturalisation + "#occu": EventType.OCCUPATION, # Epers_Occupation + "#ordn": EventType.ORDINATION, # Epers_Ordination + "#prop": EventType.PROPERTY, # Epers_Property + "#resi": EventType.RESIDENCE, # Epers_Residence + "#reti": EventType.RETIREMENT, + "#slgc": EventType( + (EventType.CUSTOM, _("LDS Seal to child")) + ), # Epers_ScellentChildLDS + "#slgp": LdsOrd.SEAL_TO_PARENTS, # Epers_ScellentParentLDS + "#slgs": LdsOrd.SEAL_TO_SPOUSE, + "#vteb": EventType((EventType.CUSTOM, _("Sold property"))), # Epers_VenteBien + "#will": EventType.WILL, # Epers_Will +} fevents_map = { - "#marr" : EventType.MARRIAGE, #Efam_Marriage - "#nmar" : EventType.NUM_MARRIAGES, - "#nmen" : EventType((EventType.CUSTOM, _('No mention'))), #Efam_NoMention - "#enga" : EventType.ENGAGEMENT, #Efam_Engage - "#div" : EventType.DIVORCE, - "#sep" : EventType((EventType.CUSTOM, _('Separated'))), #Efam_Separated - "#anul" : EventType.ANNULMENT, #Efam_Annulation - "#marb" : EventType.MARR_BANNS, #Efam_MarriageBann - "#marc" : EventType.MARR_CONTR, #Efam_MarriageContract) - "#marl" : EventType.MARR_LIC, #Efam_MarriageLicense) - "#resi" : EventType.RESIDENCE, #Efam_Residence) - } + "#marr": EventType.MARRIAGE, # Efam_Marriage + "#nmar": EventType.NUM_MARRIAGES, + "#nmen": EventType((EventType.CUSTOM, _("No mention"))), # Efam_NoMention + "#enga": EventType.ENGAGEMENT, # Efam_Engage + "#div": EventType.DIVORCE, + "#sep": EventType((EventType.CUSTOM, _("Separated"))), # Efam_Separated + "#anul": EventType.ANNULMENT, # Efam_Annulation + "#marb": EventType.MARR_BANNS, # Efam_MarriageBann + "#marc": EventType.MARR_CONTR, # Efam_MarriageContract) + "#marl": EventType.MARR_LIC, # Efam_MarriageLicense) + "#resi": EventType.RESIDENCE, # Efam_Residence) +} -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- def importData(database, filename, user): global callback try: - g = GeneWebParser(database,filename) + g = GeneWebParser(database, filename) except IOError as msg: - user.notify_error(_("%s could not be opened\n") % filename,str(msg)) + user.notify_error(_("%s could not be opened\n") % filename, str(msg)) return try: status = g.parse_geneweb_file() except IOError as msg: errmsg = _("%s could not be opened\n") % filename - user.notify_error(errmsg,str(msg)) + user.notify_error(errmsg, str(msg)) return return ImportInfo({_("Results"): _("done")}) -#------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- # For a description of the file format see # http://cristal.inria.fr/~ddr/GeneWeb/en/gwformat.htm # https://github.com/geneanet/geneweb/issues/315 -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class GeneWebParser: def __init__(self, dbase, file): self.db = dbase - if file: # Unit tests can create the parser w/o underlying file + if file: # Unit tests can create the parser w/o underlying file self.f = open(file, "rUb") self.filename = file - self.encoding = 'iso-8859-1' + self.encoding = "iso-8859-1" self.gwplus = False def get_next_line(self): @@ -180,7 +186,7 @@ class GeneWebParser: line = self.f.readline() try: - line = line.decode('utf-8') + line = line.decode("utf-8") except GrampsImportError as err: self.errmsg(str(err)) @@ -222,58 +228,62 @@ class GeneWebParser: fields = line.split(" ") - LOG.debug("LINE: %s" %line) + LOG.debug("LINE: %s" % line) if fields[0] == "gwplus": self.gwplus = True - self.encoding = 'utf-8' + self.encoding = "utf-8" elif fields[0] == "encoding:": self.encoding = fields[1] elif fields[0] == "fam": self.current_mode = "fam" - self.read_family_line(line,fields) + self.read_family_line(line, fields) elif fields[0] == "rel": self.current_mode = "rel" - self.read_relationship_person(line,fields) + self.read_relationship_person(line, fields) elif fields[0] == "src": - self.read_source_line(line,fields) + self.read_source_line(line, fields) elif fields[0] in ("wit", "wit:"): - self.read_witness_line(line,fields) + self.read_witness_line(line, fields) elif fields[0] == "cbp": - self.read_children_birthplace_line(line,fields) + self.read_children_birthplace_line(line, fields) elif fields[0] == "csrc": - self.read_children_source_line(line,fields) + self.read_children_source_line(line, fields) elif fields[0] == "beg" and self.current_mode == "fam": self.read_children_lines() elif fields[0] == "beg" and self.current_mode == "rel": self.read_relation_lines() elif fields[0] == "comm": - self.read_family_comment(line,fields) + self.read_family_comment(line, fields) elif fields[0] == "notes": - self.read_person_notes_lines(line,fields) + self.read_person_notes_lines(line, fields) elif fields[0] == "fevt" and self.current_mode == "fam": - #self.read_fevent_line(self.get_next_line()) + # self.read_fevent_line(self.get_next_line()) pass elif fields[0] == "pevt": - #self.read_pevent_line(self.get_next_line(), fields) + # self.read_pevent_line(self.get_next_line(), fields) pass elif fields[0] == "notes-db": - self.read_database_notes_lines(line,fields) + self.read_database_notes_lines(line, fields) elif fields[0] == "pages-ext" or "wizard-note": pass elif fields[0] == "end": self.current_mode = None else: - LOG.warning("parse_geneweb_file(): Token >%s< unknown. line %d skipped: %s" % - (fields[0],self.lineno,line)) + LOG.warning( + "parse_geneweb_file(): Token >%s< unknown. line %d skipped: %s" + % (fields[0], self.lineno, line) + ) except GedcomError as err: self.errmsg(str(err)) t = time.time() - t # Translators: leave all/any {...} untranslated - msg = ngettext('Import Complete: {number_of} second', - 'Import Complete: {number_of} seconds', t - ).format(number_of=t) + msg = ngettext( + "Import Complete: {number_of} second", + "Import Complete: {number_of} seconds", + t, + ).format(number_of=t) self.db.enable_signals() self.db.request_rebuild() @@ -283,38 +293,38 @@ class GeneWebParser: LOG.debug("Individuals: %d" % len(self.ikeys)) return None - def read_family_line(self,line,fields): + def read_family_line(self, line, fields): self.current_husband_handle = None self.current_child_birthplace_handle = None self.current_child_source_handle = None self.current_family = Family() - self.db.add_family(self.current_family,self.trans) - #self.db.commit_family(self.current_family,self.trans) + self.db.add_family(self.current_family, self.trans) + # self.db.commit_family(self.current_family,self.trans) self.fkeys.append(self.current_family.get_handle()) - idx = 1; + idx = 1 LOG.debug("\nHusband:") - (idx, husband) = self.parse_person(fields,idx,Person.MALE,None) + (idx, husband) = self.parse_person(fields, idx, Person.MALE, None) if husband: self.current_husband_handle = husband.get_handle() self.current_family.set_father_handle(husband.get_handle()) - self.db.commit_family(self.current_family,self.trans) + self.db.commit_family(self.current_family, self.trans) husband.add_family_handle(self.current_family.get_handle()) - self.db.commit_person(husband,self.trans) + self.db.commit_person(husband, self.trans) LOG.debug("Marriage:") - idx = self.parse_marriage(fields,idx) + idx = self.parse_marriage(fields, idx) LOG.debug("Wife:") - (idx,wife) = self.parse_person(fields,idx,Person.FEMALE,None) + (idx, wife) = self.parse_person(fields, idx, Person.FEMALE, None) if wife: self.current_family.set_mother_handle(wife.get_handle()) - self.db.commit_family(self.current_family,self.trans) + self.db.commit_family(self.current_family, self.trans) wife.add_family_handle(self.current_family.get_handle()) - self.db.commit_person(wife,self.trans) + self.db.commit_person(wife, self.trans) return None - def read_relationship_person(self,line,fields): + def read_relationship_person(self, line, fields): LOG.debug(r"\Relationships:") - (idx,person) = self.parse_person(fields,1,Person.UNKNOWN,None) + (idx, person) = self.parse_person(fields, 1, Person.UNKNOWN, None) if person: self.current_relationship_person_handle = person.get_handle() @@ -322,7 +332,9 @@ class GeneWebParser: if not self.current_relationship_person_handle: LOG.warning("Unknown person for relationship in line %d!" % self.lineno) return None - rel_person = self.db.get_person_from_handle(self.current_relationship_person_handle) + rel_person = self.db.get_person_from_handle( + self.current_relationship_person_handle + ) while 1: line = self.get_next_line() if line is None or line == "end": @@ -334,16 +346,16 @@ class GeneWebParser: line_re = re.compile("^- ([^:]+): (.*)$") matches = line_re.match(line) if matches: - #split related person into fields + # split related person into fields fields = matches.groups()[1].split(" ") if fields: - (idx,asso_p) = self.parse_person(fields,0,Person.UNKNOWN,None) + (idx, asso_p) = self.parse_person(fields, 0, Person.UNKNOWN, None) pref = PersonRef() pref.set_relation(matches.groups()[0]) LOG.warning("TODO: Handle association types properly") pref.set_reference_handle(asso_p.get_handle()) rel_person.add_person_ref(pref) - self.db.commit_person(rel_person,self.trans) + self.db.commit_person(rel_person, self.trans) else: LOG.warning("Invalid name of person in line %d" % self.lineno) else: @@ -352,31 +364,31 @@ class GeneWebParser: self.current_mode = None return None - def read_source_line(self,line,fields): + def read_source_line(self, line, fields): if not self.current_family: LOG.warning("Unknown family of child in line %d!" % self.lineno) return None source = self.get_or_create_source(self.decode(fields[1])) self.current_family.add_citation(source.get_handle()) - self.db.commit_family(self.current_family,self.trans) + self.db.commit_family(self.current_family, self.trans) return None - def read_witness_line(self,line,fields): + def read_witness_line(self, line, fields): LOG.debug("Witness:") if fields[1] == "m:": - (idx,wit_p) = self.parse_person(fields,2,Person.MALE,None) + (idx, wit_p) = self.parse_person(fields, 2, Person.MALE, None) elif fields[1] == "f:": - (idx,wit_p) = self.parse_person(fields,2,Person.FEMALE,None) + (idx, wit_p) = self.parse_person(fields, 2, Person.FEMALE, None) else: - (idx,wit_p) = self.parse_person(fields,1,None,None) + (idx, wit_p) = self.parse_person(fields, 1, None, None) if wit_p: mev = None # search marriage event for evr in self.current_family.get_event_ref_list(): ev = self.db.get_event_from_handle(evr.get_reference_handle()) if ev.get_type() == EventType.MARRIAGE: - mev = ev # found. - if not mev: # No marriage event found create a new one + mev = ev # found. + if not mev: # No marriage event found create a new one mev = self.create_event(EventType.MARRIAGE, None, None, None, None) mar_ref = EventRef() mar_ref.set_reference_handle(mev.get_handle()) @@ -385,7 +397,7 @@ class GeneWebParser: wit_ref.set_role(EventRoleType(EventRoleType.WITNESS)) wit_ref.set_reference_handle(mev.get_handle()) wit_p.add_event_ref(wit_ref) - self.db.commit_person(wit_p,self.trans) + self.db.commit_person(wit_p, self.trans) return None def read_children_lines(self): @@ -410,18 +422,24 @@ class GeneWebParser: LOG.debug("Child:") child = None if fields[1] == "h": - (idx,child) = self.parse_person(fields,2,Person.MALE,father_surname) + (idx, child) = self.parse_person( + fields, 2, Person.MALE, father_surname + ) elif fields[1] == "f": - (idx,child) = self.parse_person(fields,2,Person.FEMALE,father_surname) + (idx, child) = self.parse_person( + fields, 2, Person.FEMALE, father_surname + ) else: - (idx,child) = self.parse_person(fields,1,Person.UNKNOWN,father_surname) + (idx, child) = self.parse_person( + fields, 1, Person.UNKNOWN, father_surname + ) if child: childref = ChildRef() childref.set_reference_handle(child.get_handle()) - self.current_family.add_child_ref( childref) - self.db.commit_family(self.current_family,self.trans) - child.add_parent_family_handle( self.current_family.get_handle()) + self.current_family.add_child_ref(childref) + self.db.commit_family(self.current_family, self.trans) + child.add_parent_family_handle(self.current_family.get_handle()) if self.current_child_birthplace_handle: birth = None birth_ref = child.get_birth_ref() @@ -433,36 +451,35 @@ class GeneWebParser: birth_ref.set_reference_handle(birth.get_handle()) child.set_birth_ref(birth_ref) birth.set_place_handle(self.current_child_birthplace_handle) - self.db.commit_event(birth,self.trans) + self.db.commit_event(birth, self.trans) if self.current_child_source_handle: child.add_citation(self.current_child_source_handle) - self.db.commit_person(child,self.trans) + self.db.commit_person(child, self.trans) else: break self.current_mode = None return None - - def read_children_birthplace_line(self,line,fields): + def read_children_birthplace_line(self, line, fields): cbp = self.get_or_create_place(self.decode(fields[1])) if cbp: self.current_child_birthplace_handle = cbp.get_handle() return None - def read_children_source_line(self,line,fields): + def read_children_source_line(self, line, fields): csrc = self.get_or_create_source(self.decode(fields[1])) self.current_child_source_handle = csrc.handle return None - def read_family_comment(self,line,fields): + def read_family_comment(self, line, fields): if not self.current_family: LOG.warning("Unknown family of child in line %d!" % self.lineno) return None n = Note() n.set(line) - self.db.add_note(n,self.trans) + self.db.add_note(n, self.trans) self.current_family.add_note(n.handle) - self.db.commit_family(self.current_family,self.trans) + self.db.commit_family(self.current_family, self.trans) return None def _read_notes_lines(self, note_tag): @@ -485,21 +502,21 @@ class GeneWebParser: if note_txt: n = Note() n.set(note_txt) - self.db.add_note(n,self.trans) + self.db.add_note(n, self.trans) return n.handle return None - def read_person_notes_lines(self,line,fields): - (idx,person) = self.parse_person(fields,1,None,None) - note_handle = self._read_notes_lines( fields[0]) + def read_person_notes_lines(self, line, fields): + (idx, person) = self.parse_person(fields, 1, None, None) + note_handle = self._read_notes_lines(fields[0]) if note_handle: person.add_note(note_handle) - self.db.commit_person(person,self.trans) + self.db.commit_person(person, self.trans) - def read_database_notes_lines(self,line,fields): - note_handle = self._read_notes_lines( fields[0]) + def read_database_notes_lines(self, line, fields): + note_handle = self._read_notes_lines(fields[0]) - def parse_marriage(self,fields,idx): + def parse_marriage(self, fields, idx): mariageDataRe = re.compile("^[+#-0-9].*$") mar_date = None @@ -513,12 +530,14 @@ class GeneWebParser: engaged = 0 # skip to marriage date in case person contained unmatches tokens - #Alex: this failed when fields[idx] was an empty line. Fixed. - #while idx < len(fields) and not fields[idx][0] == "+": + # Alex: this failed when fields[idx] was an empty line. Fixed. + # while idx < len(fields) and not fields[idx][0] == "+": while idx < len(fields) and not (fields[idx] and fields[idx][0] == "+"): if fields[idx]: - LOG.warning(("parse_marriage(): Unknown field: " + - "'%s' in line %d!") % (fields[idx], self.lineno)) + LOG.warning( + ("parse_marriage(): Unknown field: " + "'%s' in line %d!") + % (fields[idx], self.lineno) + ) idx += 1 while idx < len(fields) and mariageDataRe.match(fields[idx]): @@ -553,48 +572,47 @@ class GeneWebParser: LOG.debug(" Are engaged.") engaged = 1 else: - LOG.warning(("parse_marriage(): Unknown field " + - "'%s'for mariage in line %d!") % (field, self.lineno)) + LOG.warning( + ("parse_marriage(): Unknown field " + "'%s'for mariage in line %d!") + % (field, self.lineno) + ) if mar_date or mar_place or mar_source: mar = self.create_event( - EventType.MARRIAGE, None, mar_date, mar_place, mar_source) + EventType.MARRIAGE, None, mar_date, mar_place, mar_source + ) mar_ref = EventRef() mar_ref.set_reference_handle(mar.get_handle()) mar_ref.set_role(EventRoleType.FAMILY) self.current_family.add_event_ref(mar_ref) - self.current_family.set_relationship( - FamilyRelType(FamilyRelType.MARRIED)) + self.current_family.set_relationship(FamilyRelType(FamilyRelType.MARRIED)) if div_date: - div = self.create_event( - EventType.DIVORCE, None, div_date, None, None) + div = self.create_event(EventType.DIVORCE, None, div_date, None, None) div_ref = EventRef() div_ref.set_reference_handle(div.get_handle()) div_ref.set_role(EventRoleType.FAMILY) self.current_family.add_event_ref(div_ref) if sep_date or engaged: - sep = self.create_event( - EventType.ENGAGEMENT, None, sep_date, None, None) + sep = self.create_event(EventType.ENGAGEMENT, None, sep_date, None, None) sep_ref = EventRef() sep_ref.set_reference_handle(sep.get_handle()) sep_ref.set_role(EventRoleType.FAMILY) self.current_family.add_event_ref(sep_ref) if not married: - self.current_family.set_relationship( - FamilyRelType(FamilyRelType.UNMARRIED)) + self.current_family.set_relationship(FamilyRelType(FamilyRelType.UNMARRIED)) - self.db.commit_family(self.current_family,self.trans) + self.db.commit_family(self.current_family, self.trans) return idx - def parse_person(self,fields,idx,gender,father_surname): + def parse_person(self, fields, idx, gender, father_surname): if not father_surname: if not idx < len(fields): LOG.warning("Missing surname of person in line %d!" % self.lineno) - surname ="" + surname = "" else: surname = self.decode(fields[idx]) idx += 1 @@ -614,16 +632,16 @@ class GeneWebParser: idx += 1 LOG.debug("Person: %s %s" % (firstname, surname)) - person = self.get_or_create_person(firstname,surname) + person = self.get_or_create_person(firstname, surname) name = Name() - name.set_type( NameType(NameType.BIRTH)) + name.set_type(NameType(NameType.BIRTH)) name.set_first_name(firstname) surname_obj = name.get_primary_surname() surname_obj.set_surname(surname) person.set_primary_name(name) if person.get_gender() == Person.UNKNOWN and gender is not None: person.set_gender(gender) - self.db.commit_person(person,self.trans) + self.db.commit_person(person, self.trans) personDataRe = re.compile(r"^[kmes0-9<>~#\[({!].*$") dateRe = re.compile("^[kmes0-9~<>?]+.*$") @@ -656,13 +674,13 @@ class GeneWebParser: while idx < len(fields) and personDataRe.match(fields[idx]): field = fields[idx] idx += 1 - if field.startswith('('): + if field.startswith("("): LOG.debug("Public Name: %s" % field) public_name = self.decode(field[1:-1]) - elif field.startswith('{'): + elif field.startswith("{"): LOG.debug("Firstsname Alias: %s" % field) firstname_aliases.append(self.decode(field[1:-1])) - elif field.startswith('['): + elif field.startswith("["): LOG.debug("Title: %s" % field) titleparts = self.decode(field[1:-1]).split(":") tname = ttitle = tplace = tstart = tend = tnth = None @@ -676,101 +694,99 @@ class GeneWebParser: tnth = titleparts[5] except IndexError: # not all parts are written all the time pass - if tnth: # Append title numer to title + if tnth: # Append title numer to title # TODO for Arabic, should the next comma be translated? ttitle += ", " + tnth - title = self.create_event( - EventType.NOB_TITLE, ttitle, tstart, tplace) + title = self.create_event(EventType.NOB_TITLE, ttitle, tstart, tplace) # TODO: Geneweb has a start date and an end date, and therefore # supports stuff like: FROM about 1955 TO between 1998 and 1999 # gramps only supports one single date or range. if tname and tname != "*": n = Note() n.set(tname) - self.db.add_note(n,self.trans) - title.add_note( n.handle) + self.db.add_note(n, self.trans) + title.add_note(n.handle) title_ref = EventRef() title_ref.set_reference_handle(title.get_handle()) person.add_event_ref(title_ref) - elif field == '#nick' and idx < len(fields): + elif field == "#nick" and idx < len(fields): LOG.debug("Nick Name: %s" % fields[idx]) nick_names.append(self.decode(fields[idx])) idx += 1 - elif field == '#occu' and idx < len(fields): + elif field == "#occu" and idx < len(fields): LOG.debug("Occupation: %s" % fields[idx]) - occu = self.create_event( - EventType.OCCUPATION, self.decode(fields[idx])) + occu = self.create_event(EventType.OCCUPATION, self.decode(fields[idx])) occu_ref = EventRef() occu_ref.set_reference_handle(occu.get_handle()) person.add_event_ref(occu_ref) idx += 1 - elif field == '#alias' and idx < len(fields): + elif field == "#alias" and idx < len(fields): LOG.debug("Name Alias: %s" % fields[idx]) name_aliases.append(self.decode(fields[idx])) idx += 1 - elif field == '#salias' and idx < len(fields): + elif field == "#salias" and idx < len(fields): LOG.debug("Surname Alias: %s" % fields[idx]) surname_aliases.append(self.decode(fields[idx])) idx += 1 - elif field == '#image' and idx < len(fields): + elif field == "#image" and idx < len(fields): LOG.debug("Image: %s" % fields[idx]) idx += 1 - elif field == '#src' and idx < len(fields): + elif field == "#src" and idx < len(fields): LOG.debug("Source: %s" % fields[idx]) source = self.get_or_create_source(self.decode(fields[idx])) idx += 1 - elif field == '#bs' and idx < len(fields): + elif field == "#bs" and idx < len(fields): LOG.debug("Birth Source: %s" % fields[idx]) birth_source = self.get_or_create_source(self.decode(fields[idx])) idx += 1 - elif field[0] == '!': + elif field[0] == "!": LOG.debug("Baptize at: %s" % field[1:]) bapt_date = self.parse_date(self.decode(field[1:])) - elif field == '#bp' and idx < len(fields): + elif field == "#bp" and idx < len(fields): LOG.debug("Birth Place: %s" % fields[idx]) birth_place = self.get_or_create_place(self.decode(fields[idx])) idx += 1 - elif field == '#pp' and idx < len(fields): + elif field == "#pp" and idx < len(fields): LOG.debug("Baptize Place: %s" % fields[idx]) bapt_place = self.get_or_create_place(self.decode(fields[idx])) idx += 1 - elif field == '#ps' and idx < len(fields): + elif field == "#ps" and idx < len(fields): LOG.debug("Baptize Source: %s" % fields[idx]) bapt_source = self.get_or_create_source(self.decode(fields[idx])) idx += 1 - elif field == '#dp' and idx < len(fields): + elif field == "#dp" and idx < len(fields): LOG.debug("Death Place: %s" % fields[idx]) death_place = self.get_or_create_place(self.decode(fields[idx])) idx += 1 - elif field == '#ds' and idx < len(fields): + elif field == "#ds" and idx < len(fields): LOG.debug("Death Source: %s" % fields[idx]) death_source = self.get_or_create_source(self.decode(fields[idx])) idx += 1 - elif field == '#buri' and idx < len(fields): - if fields[idx][0]!='#': # bug in GeneWeb: empty #buri fields + elif field == "#buri" and idx < len(fields): + if fields[idx][0] != "#": # bug in GeneWeb: empty #buri fields LOG.debug("Burial Date: %s" % fields[idx]) bur_date = self.parse_date(self.decode(fields[idx])) idx += 1 - elif field == '#crem' and idx < len(fields): + elif field == "#crem" and idx < len(fields): LOG.debug("Cremention Date: %s" % fields[idx]) crem_date = self.parse_date(self.decode(fields[idx])) idx += 1 - elif field == '#rp' and idx < len(fields): + elif field == "#rp" and idx < len(fields): LOG.debug("Burial Place: %s" % fields[idx]) bur_place = self.get_or_create_place(self.decode(fields[idx])) idx += 1 - elif field == '#rs' and idx < len(fields): + elif field == "#rs" and idx < len(fields): LOG.debug("Burial Source: %s" % fields[idx]) bur_source = self.get_or_create_source(self.decode(fields[idx])) idx += 1 - elif field == '#apubl': + elif field == "#apubl": LOG.debug("This is a public record") - elif field == '#apriv': + elif field == "#apriv": LOG.debug("This is a private record") person.set_privacy(True) - elif field == '#h': + elif field == "#h": LOG.debug("This is a restricted record") - #TODO: Gramps does currently not feature this level + # TODO: Gramps does currently not feature this level person.set_privacy(True) elif dateRe.match(field): if not birth_parsed: @@ -790,10 +806,12 @@ class GeneWebParser: death_cause = "Executed" elif field.startswith("d"): death_cause = "Disappeared" - #TODO: Set special death types more properly + # TODO: Set special death types more properly else: - LOG.warning(("parse_person(): Unknown field " + - "'%s' for person in line %d!") % (field, self.lineno)) + LOG.warning( + ("parse_person(): Unknown field " + "'%s' for person in line %d!") + % (field, self.lineno) + ) if public_name: name = person.get_primary_name() @@ -843,43 +861,53 @@ class GeneWebParser: person.add_citation(source.get_handle()) if birth_date or birth_place or birth_source: - birth = self.create_event(EventType.BIRTH, None, birth_date, birth_place, birth_source) + birth = self.create_event( + EventType.BIRTH, None, birth_date, birth_place, birth_source + ) birth_ref = EventRef() - birth_ref.set_reference_handle( birth.get_handle()) - person.set_birth_ref( birth_ref) + birth_ref.set_reference_handle(birth.get_handle()) + person.set_birth_ref(birth_ref) if bapt_date or bapt_place or bapt_source: - babt = self.create_event(EventType.BAPTISM, None, bapt_date, bapt_place, bapt_source) + babt = self.create_event( + EventType.BAPTISM, None, bapt_date, bapt_place, bapt_source + ) babt_ref = EventRef() - babt_ref.set_reference_handle( babt.get_handle()) - person.add_event_ref( babt_ref) + babt_ref.set_reference_handle(babt.get_handle()) + person.add_event_ref(babt_ref) if death_date or death_place or death_source or death_cause: - death = self.create_event(EventType.DEATH, None, death_date, death_place, death_source) + death = self.create_event( + EventType.DEATH, None, death_date, death_place, death_source + ) if death_cause: death.set_description(death_cause) - self.db.commit_event(death,self.trans) + self.db.commit_event(death, self.trans) death_ref = EventRef() - death_ref.set_reference_handle( death.get_handle()) - person.set_death_ref( death_ref) + death_ref.set_reference_handle(death.get_handle()) + person.set_death_ref(death_ref) if bur_date: - bur = self.create_event(EventType.BURIAL, None, bur_date, bur_place, bur_source) + bur = self.create_event( + EventType.BURIAL, None, bur_date, bur_place, bur_source + ) bur_ref = EventRef() - bur_ref.set_reference_handle( bur.get_handle()) - person.add_event_ref( bur_ref) + bur_ref.set_reference_handle(bur.get_handle()) + person.add_event_ref(bur_ref) if crem_date: - crem = self.create_event(EventType.CREMATION, None, crem_date, bur_place, bur_source) + crem = self.create_event( + EventType.CREMATION, None, crem_date, bur_place, bur_source + ) crem_ref = EventRef() - crem_ref.set_reference_handle( crem.get_handle()) + crem_ref.set_reference_handle(crem.get_handle()) person.add_event_ref(crem_ref) - self.db.commit_person(person,self.trans) + self.db.commit_person(person, self.trans) - return (idx,person) + return (idx, person) - def parse_date(self,field): + def parse_date(self, field): if field == "0": return None date = Date() @@ -893,40 +921,59 @@ class GeneWebParser: matches = _date_parse.match(field) if matches: groups = matches.groups() - mod = _mod_map.get(groups[0],Date.MOD_NONE) + mod = _mod_map.get(groups[0], Date.MOD_NONE) if groups[3] == "..": - mod = Date.MOD_SPAN - cal2 = _cal_map.get(groups[5],Date.CAL_GREGORIAN) - sub2 = self.sub_date(groups[4]) + if groups[4] == "0": + mod = Date.MOD_FROM + cal1 = _cal_map.get(groups[2], Date.CAL_GREGORIAN) + sub1 = self.sub_date(groups[1]) + sub2 = (0, 0, 0) + elif groups[1] == "0": + mod = Date.MOD_TO + cal1 = _cal_map.get(groups[5], Date.CAL_GREGORIAN) + sub1 = self.sub_date(groups[4]) + sub2 = (0, 0, 0) + else: + mod = Date.MOD_SPAN + cal1 = _cal_map.get(groups[2], Date.CAL_GREGORIAN) + cal2 = _cal_map.get(groups[5], Date.CAL_GREGORIAN) + sub1 = self.sub_date(groups[1]) + sub2 = self.sub_date(groups[4]) else: - sub2 = (0,0,0) - cal1 = _cal_map.get(groups[2],Date.CAL_GREGORIAN) - sub1 = self.sub_date(groups[1]) + cal1 = _cal_map.get(groups[2], Date.CAL_GREGORIAN) + sub1 = self.sub_date(groups[1]) + sub2 = (0, 0, 0) try: - date.set(Date.QUAL_NONE,mod, cal1, - (sub1[0],sub1[1],sub1[2],0,sub2[0],sub2[1],sub2[2],0)) + date.set( + Date.QUAL_NONE, + mod, + cal1, + (sub1[0], sub1[1], sub1[2], 0, sub2[0], sub2[1], sub2[2], 0), + ) except DateError as e: # Translators: leave the {date} and {gw_snippet} untranslated # in the format string, but you may re-order them if needed. - LOG.warning(_( - "Invalid date {date} in {gw_snippet}, " - "preserving date as text." - ).format(date=e.date.__dict__, gw_snippet=field)) + LOG.warning( + _( + "Invalid date {date} in {gw_snippet}, " + "preserving date as text." + ).format(date=e.date.__dict__, gw_snippet=field) + ) date.set(modifier=Date.MOD_TEXTONLY, text=field) return date else: return None - def sub_date(self,data): - vals = data.split('/') + def sub_date(self, data): + vals = data.split("/") if len(vals) == 1: - return (0,0,int(vals[0])) + return (0, 0, int(vals[0])) elif len(vals) == 2: - return (0,int(vals[0]),int(vals[1])) + return (0, int(vals[0]), int(vals[1])) else: - return (int(vals[0]),int(vals[1]),int(vals[2])) + return (int(vals[0]), int(vals[1]), int(vals[2])) - def create_event(self,type,desc=None,date=None,place=None,source=None): + def create_event(self, type, desc=None, date=None, place=None, source=None): event = Event() if type: event.set_type(EventType(type)) @@ -938,23 +985,23 @@ class GeneWebParser: event.set_place_handle(place.get_handle()) if source: event.add_citation(source.get_handle()) - self.db.add_event(event,self.trans) - self.db.commit_event(event,self.trans) + self.db.add_event(event, self.trans) + self.db.commit_event(event, self.trans) return event - def get_or_create_person(self,firstname,lastname): + def get_or_create_person(self, firstname, lastname): person = None - mykey = firstname+lastname + mykey = firstname + lastname if mykey in self.ikeys and firstname != "?" and lastname != "?": person = self.db.get_person_from_handle(self.ikeys[mykey]) else: person = Person() - self.db.add_person(person,self.trans) - self.db.commit_person(person,self.trans) + self.db.add_person(person, self.trans) + self.db.commit_person(person, self.trans) self.ikeys[mykey] = person.get_handle() return person - def get_or_create_place(self,place_name): + def get_or_create_place(self, place_name): place = None if place_name in self.pkeys: place = self.db.get_place_from_handle(self.pkeys[place_name]) @@ -962,20 +1009,20 @@ class GeneWebParser: place = Place() place.name = PlaceName(value=place_name) place.set_title(place_name) - self.db.add_place(place,self.trans) - self.db.commit_place(place,self.trans) + self.db.add_place(place, self.trans) + self.db.commit_place(place, self.trans) self.pkeys[place_name] = place.get_handle() return place - def get_or_create_source(self,source_name): + def get_or_create_source(self, source_name): source = None if source_name in self.skeys: source = self.db.get_source_from_handle(self.skeys[source_name]) else: source = Source() source.set_title(source_name) - self.db.add_source(source,self.trans) - self.db.commit_source(source,self.trans) + self.db.add_source(source, self.trans) + self.db.commit_source(source, self.trans) self.skeys[source_name] = source.get_handle() citation = Citation() citation.set_reference_handle(source.get_handle()) @@ -986,16 +1033,16 @@ class GeneWebParser: def read_fevent_line(self, event): if fevents_map.get(event[0:5]) == None: - return #need to fix custom event types not in the map + return # need to fix custom event types not in the map fev = None # get events for the current family for evr in self.current_family.get_event_ref_list(): ev = self.db.get_event_from_handle(evr.get_reference_handle()) if ev.get_type() == fevents_map.get(event[0:5]): - fev = ev # found. Need to also check EventRef role + fev = ev # found. Need to also check EventRef role return - if not fev: # No event found create a new one + if not fev: # No event found create a new one if evr.get_role() != EventRoleType(EventRoleType.FAMILY): continue else: @@ -1009,7 +1056,7 @@ class GeneWebParser: continue else: self.current_mode = None - #self.db.commit_family(self.current_family,self.trans) + # self.db.commit_family(self.current_family,self.trans) break def read_pevent_line(self, event, fields): @@ -1021,29 +1068,29 @@ class GeneWebParser: # check key on {ikey} except: self.person = "(TO_CHECK: %s)" % fields[1:] - #GrampsImportError() + # GrampsImportError() lastname = fields[1] firstname = fields[2] self.current_person = self.get_or_create_person(firstname, lastname) - #name = Name() - #name.set_type(NameType(NameType.BIRTH)) - #name.set_first_name(firstname) - #surname_obj = name.get_primary_surname() - #surname_obj.set_surname(surname) - #self.current_person.set_primary_name(name) + # name = Name() + # name.set_type(NameType(NameType.BIRTH)) + # name.set_first_name(firstname) + # surname_obj = name.get_primary_surname() + # surname_obj.set_surname(surname) + # self.current_person.set_primary_name(name) if pevents_map.get(event[0:5]) == None: - return #need to fix custom event types not in the map + return # need to fix custom event types not in the map self.current_event = None # get events for the current person for evr in self.current_person.get_event_ref_list(): ev = self.db.get_event_from_handle(evr.get_reference_handle()) if ev.get_type() == pevents_map.get(event[0:5]): - self.current_event = ev # found. Need to also check EventRef role - if not self.current_event: # No event found create a new one + self.current_event = ev # found. Need to also check EventRef role + if not self.current_event: # No event found create a new one self.current_event = self.new_gwplus_pevent(event) while True: line = self.get_next_line() @@ -1058,10 +1105,10 @@ class GeneWebParser: self.current_event.add_note(n.handle) self.db.commit_event(self.current_event, self.trans) else: - print('note', n.handle) + print("note", n.handle) else: self.current_mode = None - #self.db.commit_person(self.current_person,self.trans) + # self.db.commit_person(self.current_person,self.trans) break def new_gwplus_fevent(self, line): @@ -1081,15 +1128,15 @@ class GeneWebParser: if part == "#s": source = self.get_or_create_source(self.decode(data[idx])) self.current_event = self.create_event(type, None, None, None, None) - print('new event', self.current_event.handle) + print("new event", self.current_event.handle) if date: print(date) self.current_event.set_date_object(date) if place: - print('place', place.handle) + print("place", place.handle) self.current_event.set_place_handle(place.get_handle()) if source: - print('source', source.handle) + print("source", source.handle) self.current_event.add_citation(source.get_handle()) self.db.commit_event(self.current_event, self.trans) nev_ref = EventRef() @@ -1115,15 +1162,15 @@ class GeneWebParser: if part == "#s": source = self.get_or_create_source(self.decode(data[idx])) self.current_event = self.create_event(type, None, None, None, None) - print('new event', self.current_event.handle) + print("new event", self.current_event.handle) if date: print(date) self.current_event.set_date_object(date) if place: - print('place', place.handle) + print("place", place.handle) self.current_event.set_place_handle(place.get_handle()) if source: - print('source', source.handle) + print("source", source.handle) self.current_event.add_citation(source.get_handle()) self.db.commit_event(self.current_event, self.trans) nev_ref = EventRef() @@ -1132,21 +1179,21 @@ class GeneWebParser: self.db.commit_person(self.current_person, self.trans) return self.current_event - def decode(self,s): - s = s.replace('_',' ') - charref_re = re.compile('(&#)(x?)([0-9a-zA-Z]+)(;)') + def decode(self, s): + s = s.replace("_", " ") + charref_re = re.compile("(&#)(x?)([0-9a-zA-Z]+)(;)") for match in charref_re.finditer(s): try: if match.group(2): # HEX - nchar = chr(int(match.group(3),16)) - else: # Decimal + nchar = chr(int(match.group(3), 16)) + else: # Decimal nchar = chr(int(match.group(3))) s = s.replace(match.group(0), nchar) except UnicodeDecodeError: pass # replace named entities - entref_re = re.compile('(&)([a-zA-Z]+)(;)') + entref_re = re.compile("(&)([a-zA-Z]+)(;)") for match in entref_re.finditer(s): try: if match.group(2) in name2codepoint: @@ -1155,7 +1202,7 @@ class GeneWebParser: except UnicodeDecodeError: pass - return(s) + return s def debug(self, txt): LOG.debug(txt) diff --git a/gramps/plugins/importer/importxml.py b/gramps/plugins/importer/importxml.py index 0f5e5fe2d..4612b6c57 100644 --- a/gramps/plugins/importer/importxml.py +++ b/gramps/plugins/importer/importxml.py @@ -23,11 +23,11 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Standard Python Modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import os import sys import time @@ -35,29 +35,65 @@ from xml.parsers.expat import ExpatError, ParserCreate from xml.sax.saxutils import escape from gramps.gen.const import URL_WIKISTRING from gramps.gen.const import GRAMPS_LOCALE as glocale + _ = glocale.translation.gettext import re import logging from collections import abc + LOG = logging.getLogger(".ImportXML") -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps Modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from gramps.gen.mime import get_type -from gramps.gen.lib import (Address, Attribute, AttributeType, ChildRef, - ChildRefType, Citation, Date, DateError, Event, - EventRef, EventRoleType, EventType, Family, LdsOrd, - Location, Media, MediaRef, Name, - NameOriginType, NameType, Note, NoteType, Person, - PersonRef, Place, PlaceName, PlaceRef, PlaceType, - RepoRef, Repository, Researcher, Source, - SrcAttribute, SrcAttributeType, StyledText, - StyledTextTag, StyledTextTagType, Surname, Tag, Url) +from gramps.gen.lib import ( + Address, + Attribute, + AttributeType, + ChildRef, + ChildRefType, + Citation, + Date, + DateError, + Event, + EventRef, + EventRoleType, + EventType, + Family, + LdsOrd, + Location, + Media, + MediaRef, + Name, + NameOriginType, + NameType, + Note, + NoteType, + Person, + PersonRef, + Place, + PlaceName, + PlaceRef, + PlaceType, + RepoRef, + Repository, + Researcher, + Source, + SrcAttribute, + SrcAttributeType, + StyledText, + StyledTextTag, + StyledTextTagType, + Surname, + Tag, + Url, +) from gramps.gen.db import DbTxn -#from gramps.gen.db.write import CLASS_TO_KEY_MAP + +# from gramps.gen.db.write import CLASS_TO_KEY_MAP from gramps.gen.errors import GrampsImportError from gramps.gen.utils.id import create_id from gramps.gen.utils.db import family_name @@ -65,25 +101,36 @@ from gramps.gen.utils.unknown import make_unknown, create_explanation_note from gramps.gen.utils.file import create_checksum, media_path, expand_media_path from gramps.gen.datehandler import parser, set_date from gramps.gen.display.name import displayer as name_displayer -from gramps.gen.db.dbconst import (PERSON_KEY, FAMILY_KEY, SOURCE_KEY, - EVENT_KEY, MEDIA_KEY, PLACE_KEY, - REPOSITORY_KEY, NOTE_KEY, TAG_KEY, - CITATION_KEY, CLASS_TO_KEY_MAP) +from gramps.gen.db.dbconst import ( + PERSON_KEY, + FAMILY_KEY, + SOURCE_KEY, + EVENT_KEY, + MEDIA_KEY, + PLACE_KEY, + REPOSITORY_KEY, + NOTE_KEY, + TAG_KEY, + CITATION_KEY, + CLASS_TO_KEY_MAP, +) from gramps.gen.updatecallback import UpdateCallback from gramps.version import VERSION from gramps.gen.config import config -#import gramps.plugins.lib.libgrampsxml + +# import gramps.plugins.lib.libgrampsxml from gramps.plugins.lib import libgrampsxml from gramps.gen.plug.utils import version_str_to_tup from gramps.plugins.lib.libplaceimport import PlaceImport -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Try to detect the presence of gzip # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- try: import gzip + GZIP_OK = True except: GZIP_OK = False @@ -91,13 +138,13 @@ except: PERSON_RE = re.compile(r"\s*\ 0 and - not LOG.isEnabledFor(logging.DEBUG)) + self.replace_import_handle = ( + self.db.get_number_of_people() > 0 and not LOG.isEnabledFor(logging.DEBUG) + ) # Similarly, if the data is imported into an empty family tree, we also # import the Researcher; if the tree was not empty, the existing @@ -535,8 +617,7 @@ class GrampsParser(UpdateCallback): # List of new name formats and a dict for remapping them self.name_formats = [] self.name_formats_map = {} - self.taken_name_format_numbers = [num[0] - for num in self.db.name_formats] + self.taken_name_format_numbers = [num[0] for num in self.db.name_formats] self.event = None self.eventref = None @@ -547,7 +628,7 @@ class GrampsParser(UpdateCallback): self.surnamepat = None self.home = None self.owner = Researcher() - self.func_list = [None]*50 + self.func_list = [None] * 50 self.func_index = 0 self.func = None self.witness_comment = "" @@ -575,24 +656,27 @@ class GrampsParser(UpdateCallback): self.default_tag = None self.func_map = { - #name part + # name part "name": (self.start_name, self.stop_name), "first": (None, self.stop_first), "call": (None, self.stop_call), - "aka": (self.start_name, self.stop_aka), #deprecated < 1.3.0 - "last": (self.start_last, self.stop_last), #deprecated in 1.4.0 + "aka": (self.start_name, self.stop_aka), # deprecated < 1.3.0 + "last": (self.start_last, self.stop_last), # deprecated in 1.4.0 "nick": (None, self.stop_nick), "title": (None, self.stop_title), "suffix": (None, self.stop_suffix), - "patronymic": (self.start_patronymic, self.stop_patronymic), #deprecated in 1.4.0 - "familynick": (None, self.stop_familynick), #new in 1.4.0 - "group": (None, self.stop_group), #new in 1.4.0, replaces attribute - #new in 1.4.0 + "patronymic": ( + self.start_patronymic, + self.stop_patronymic, + ), # deprecated in 1.4.0 + "familynick": (None, self.stop_familynick), # new in 1.4.0 + "group": (None, self.stop_group), # new in 1.4.0, replaces attribute + # new in 1.4.0 "surname": (self.start_surname, self.stop_surname), # "namemaps": (None, None), "name-formats": (None, None), - #other + # other "address": (self.start_address, self.stop_address), "addresses": (None, None), "alt_name": (None, self.stop_alt_name), @@ -628,7 +712,7 @@ class GrampsParser(UpdateCallback): "type": (None, self.stop_type), "witness": (self.start_witness, self.stop_witness), "eventref": (self.start_eventref, self.stop_eventref), - "data_item": (self.start_data_item, None), #deprecated in 1.6.0 + "data_item": (self.start_data_item, None), # deprecated in 1.6.0 "families": (None, self.stop_families), "family": (self.start_family, self.stop_family), "rel": (self.start_rel, None), @@ -702,8 +786,9 @@ class GrampsParser(UpdateCallback): "reporef": (self.start_reporef, self.stop_reporef), "rname": (None, self.stop_rname), } - self.grampsuri = re.compile(r"^gramps://(?P[A-Z][a-z]+)/" - r"handle/(?P\w+)$") + self.grampsuri = re.compile( + r"^gramps://(?P[A-Z][a-z]+)/" r"handle/(?P\w+)$" + ) def inaugurate(self, handle, target, prim_obj): """ @@ -727,30 +812,36 @@ class GrampsParser(UpdateCallback): :returns: The handle of the primary object. :rtype: str """ - handle = str(handle.replace('_', '')) + handle = str(handle.replace("_", "")) orig_handle = handle - if (orig_handle in self.import_handles and - target in self.import_handles[orig_handle]): + if ( + orig_handle in self.import_handles + and target in self.import_handles[orig_handle] + ): handle = self.import_handles[handle][target][HANDLE] if not isinstance(prim_obj, abc.Callable): # This method is called by a start_ method. - get_raw_obj_data = {"person": self.db.get_raw_person_data, - "family": self.db.get_raw_family_data, - "event": self.db.get_raw_event_data, - "place": self.db.get_raw_place_data, - "source": self.db.get_raw_source_data, - "citation": self.db.get_raw_citation_data, - "repository": self.db.get_raw_repository_data, - "media": self.db.get_raw_media_data, - "note": self.db.get_raw_note_data, - "tag": self.db.get_raw_tag_data}[target] + get_raw_obj_data = { + "person": self.db.get_raw_person_data, + "family": self.db.get_raw_family_data, + "event": self.db.get_raw_event_data, + "place": self.db.get_raw_place_data, + "source": self.db.get_raw_source_data, + "citation": self.db.get_raw_citation_data, + "repository": self.db.get_raw_repository_data, + "media": self.db.get_raw_media_data, + "note": self.db.get_raw_note_data, + "tag": self.db.get_raw_tag_data, + }[target] raw = get_raw_obj_data(handle) prim_obj.unserialize(raw) self.import_handles[orig_handle][target][INSTANTIATED] = True return handle elif handle in self.import_handles: - LOG.warning("The file you import contains duplicate handles " - "which is illegal and being fixed now.") + LOG.warning( + "The file you import contains duplicate handles " + "which is illegal and being fixed now." + ) handle = create_id() while handle in self.import_handles: handle = create_id() @@ -762,16 +853,18 @@ class GrampsParser(UpdateCallback): while handle in self.import_handles: handle = create_id() else: - has_handle_func = {"person": self.db.has_person_handle, - "family": self.db.has_family_handle, - "event": self.db.has_event_handle, - "place": self.db.has_place_handle, - "source": self.db.has_source_handle, - "citation": self.db.get_raw_citation_data, - "repository": self.db.has_repository_handle, - "media": self.db.has_media_handle, - "note": self.db.has_note_handle, - "tag": self.db.has_tag_handle}[target] + has_handle_func = { + "person": self.db.has_person_handle, + "family": self.db.has_family_handle, + "event": self.db.has_event_handle, + "place": self.db.has_place_handle, + "source": self.db.has_source_handle, + "citation": self.db.get_raw_citation_data, + "repository": self.db.has_repository_handle, + "media": self.db.has_media_handle, + "note": self.db.has_note_handle, + "tag": self.db.has_tag_handle, + }[target] while has_handle_func(handle): handle = create_id() self.import_handles[orig_handle] = {target: [handle, False]} @@ -784,15 +877,17 @@ class GrampsParser(UpdateCallback): if target == "tag": self.db.add_tag(prim_obj, self.trans) else: - add_func = {"person": self.db.add_person, - "family": self.db.add_family, - "event": self.db.add_event, - "place": self.db.add_place, - "source": self.db.add_source, - "citation": self.db.add_citation, - "repository": self.db.add_repository, - "media": self.db.add_media, - "note": self.db.add_note}[target] + add_func = { + "person": self.db.add_person, + "family": self.db.add_family, + "event": self.db.add_event, + "place": self.db.add_place, + "source": self.db.add_source, + "citation": self.db.add_citation, + "repository": self.db.add_repository, + "media": self.db.add_media, + "note": self.db.add_note, + }[target] add_func(prim_obj, self.trans, set_gid=False) return handle @@ -801,67 +896,102 @@ class GrampsParser(UpdateCallback): Equivalent of inaugurate but for old style XML. """ if id_ is None: - raise GrampsImportError(_("The Gramps Xml you are trying to " - "import is malformed."), _("Attributes that link the data " - "together are missing.")) - id2handle_map = [self.gid2id, self.gid2fid, self.gid2sid, - self.gid2eid, self.gid2oid, self.gid2pid, - self.gid2rid, 'reference', self.gid2nid][key] - has_handle_func = [self.db.has_person_handle, - self.db.has_family_handle, - self.db.has_source_handle, - self.db.has_event_handle, - self.db.has_media_handle, - self.db.has_place_handle, - self.db.has_repository_handle, - 'reference', - self.db.has_note_handle][key] - add_func = [self.db.add_person, - self.db.add_family, - self.db.add_source, - self.db.add_event, - self.db.add_media, - self.db.add_place, - self.db.add_repository, - 'reference', - self.db.add_note][key] - get_raw_obj_data = [self.db.get_raw_person_data, - self.db.get_raw_family_data, - self.db.get_raw_source_data, - self.db.get_raw_event_data, - self.db.get_raw_media_data, - self.db.get_raw_place_data, - self.db.get_raw_repository_data, - 'reference', self.db.get_raw_note_data][key] - id2id_map = [self.idswap, self.fidswap, self.sidswap, self.eidswap, - self.oidswap, self.pidswap, self.ridswap, 'reference', - self.nidswap][key] - id2user_format = [self.db.id2user_format, self.db.fid2user_format, - self.db.sid2user_format, self.db.eid2user_format, - self.db.oid2user_format, self.db.pid2user_format, - self.db.rid2user_format, 'reference', - self.db.nid2user_format][key] - find_next_gramps_id = [self.db.find_next_person_gramps_id, - self.db.find_next_family_gramps_id, - self.db.find_next_source_gramps_id, - self.db.find_next_event_gramps_id, - self.db.find_next_media_gramps_id, - self.db.find_next_place_gramps_id, - self.db.find_next_repository_gramps_id, - 'reference', - self.db.find_next_note_gramps_id][key] - has_gramps_id = [self.db.has_person_gramps_id, - self.db.has_family_gramps_id, - self.db.has_source_gramps_id, - self.db.has_event_gramps_id, - self.db.has_media_gramps_id, - self.db.has_place_gramps_id, - self.db.has_repository_gramps_id, - 'reference', - self.db.has_note_gramps_id][key] + raise GrampsImportError( + _("The Gramps Xml you are trying to " "import is malformed."), + _("Attributes that link the data " "together are missing."), + ) + id2handle_map = [ + self.gid2id, + self.gid2fid, + self.gid2sid, + self.gid2eid, + self.gid2oid, + self.gid2pid, + self.gid2rid, + "reference", + self.gid2nid, + ][key] + has_handle_func = [ + self.db.has_person_handle, + self.db.has_family_handle, + self.db.has_source_handle, + self.db.has_event_handle, + self.db.has_media_handle, + self.db.has_place_handle, + self.db.has_repository_handle, + "reference", + self.db.has_note_handle, + ][key] + add_func = [ + self.db.add_person, + self.db.add_family, + self.db.add_source, + self.db.add_event, + self.db.add_media, + self.db.add_place, + self.db.add_repository, + "reference", + self.db.add_note, + ][key] + get_raw_obj_data = [ + self.db.get_raw_person_data, + self.db.get_raw_family_data, + self.db.get_raw_source_data, + self.db.get_raw_event_data, + self.db.get_raw_media_data, + self.db.get_raw_place_data, + self.db.get_raw_repository_data, + "reference", + self.db.get_raw_note_data, + ][key] + id2id_map = [ + self.idswap, + self.fidswap, + self.sidswap, + self.eidswap, + self.oidswap, + self.pidswap, + self.ridswap, + "reference", + self.nidswap, + ][key] + id2user_format = [ + self.db.id2user_format, + self.db.fid2user_format, + self.db.sid2user_format, + self.db.eid2user_format, + self.db.oid2user_format, + self.db.pid2user_format, + self.db.rid2user_format, + "reference", + self.db.nid2user_format, + ][key] + find_next_gramps_id = [ + self.db.find_next_person_gramps_id, + self.db.find_next_family_gramps_id, + self.db.find_next_source_gramps_id, + self.db.find_next_event_gramps_id, + self.db.find_next_media_gramps_id, + self.db.find_next_place_gramps_id, + self.db.find_next_repository_gramps_id, + "reference", + self.db.find_next_note_gramps_id, + ][key] + has_gramps_id = [ + self.db.has_person_gramps_id, + self.db.has_family_gramps_id, + self.db.has_source_gramps_id, + self.db.has_event_gramps_id, + self.db.has_media_gramps_id, + self.db.has_place_gramps_id, + self.db.has_repository_gramps_id, + "reference", + self.db.has_note_gramps_id, + ][key] - gramps_id = self.legalize_id(id_, key, id2id_map, id2user_format, - find_next_gramps_id, has_gramps_id) + gramps_id = self.legalize_id( + id_, key, id2id_map, id2user_format, find_next_gramps_id, has_gramps_id + ) handle = id2handle_map.get(gramps_id) if handle: raw = get_raw_obj_data(handle) @@ -878,8 +1008,9 @@ class GrampsParser(UpdateCallback): id2handle_map[gramps_id] = handle return handle - def legalize_id(self, id_, key, gramps_ids, id2user_format, - find_next_gramps_id, has_gramps_id): + def legalize_id( + self, id_, key, gramps_ids, id2user_format, find_next_gramps_id, has_gramps_id + ): """ Given an import id, adjust it so that it fits with the existing data. @@ -944,14 +1075,20 @@ class GrampsParser(UpdateCallback): if self.mediapath: if not self.db.get_mediapath(): self.db.set_mediapath(self.mediapath) - elif not media_path(self.db) == expand_media_path(self.mediapath, self.db): - self.user.notify_error(_("Could not change media path"), - _("The opened file has media path %s, which conflicts with" - " the media path of the Family Tree you import into. " - "The original media path has been retained. Copy the " - "files to a correct directory or change the media " - "path in the Preferences." - ) % self.mediapath ) + elif not media_path(self.db) == expand_media_path( + self.mediapath, self.db + ): + self.user.notify_error( + _("Could not change media path"), + _( + "The opened file has media path %s, which conflicts with" + " the media path of the Family Tree you import into. " + "The original media path has been retained. Copy the " + "files to a correct directory or change the media " + "path in the Preferences." + ) + % self.mediapath, + ) self.fix_not_instantiated() self.fix_families() @@ -969,18 +1106,18 @@ class GrampsParser(UpdateCallback): """ Get the xml version of the file. """ - if 'xmlns' in attrs: - xmlns = attrs.get('xmlns').split('/') - if len(xmlns)>= 2 and not xmlns[2] == 'gramps-project.org': + if "xmlns" in attrs: + xmlns = attrs.get("xmlns").split("/") + if len(xmlns) >= 2 and not xmlns[2] == "gramps-project.org": self.__xml_version = (0, 0, 0) else: try: self.__xml_version = version_str_to_tup(xmlns[4], 3) except: - #leave version at 1.0.0 although it could be 0.0.0 ?? + # leave version at 1.0.0 although it could be 0.0.0 ?? pass else: - #1.0 or before xml, no dtd schema yet on + # 1.0 or before xml, no dtd schema yet on # http://www.gramps-project.org/xml/ self.__xml_version = (0, 0, 0) @@ -988,67 +1125,74 @@ class GrampsParser(UpdateCallback): """ Get the Gramps version that produced the file. """ - if 'sources' in attrs: - self.num_srcs = int(attrs['sources']) + if "sources" in attrs: + self.num_srcs = int(attrs["sources"]) else: self.num_srcs = 0 - if 'places' in attrs: - self.num_places = int(attrs['places']) + if "places" in attrs: + self.num_places = int(attrs["places"]) else: self.num_places = 0 - if 'version' in attrs: - self.__gramps_version = attrs.get('version') + if "version" in attrs: + self.__gramps_version = attrs.get("version") def stop_header(self, *dummy): """ Check the version of Gramps and XML. """ - xmlversion_str = '.'.join(str(i) for i in self.__xml_version) - if self.__gramps_version == 'unknown': - msg = _("The .gramps file you are importing does not contain information about " - "the version of Gramps with, which it was produced.\n\n" - "The file will not be imported.") - raise GrampsImportError(_('Import file misses Gramps version'), msg) + xmlversion_str = ".".join(str(i) for i in self.__xml_version) + if self.__gramps_version == "unknown": + msg = _( + "The .gramps file you are importing does not contain information about " + "the version of Gramps with, which it was produced.\n\n" + "The file will not be imported." + ) + raise GrampsImportError(_("Import file misses Gramps version"), msg) if self.__xml_version > libgrampsxml.GRAMPS_XML_VERSION_TUPLE: - msg = _("The .gramps file you are importing was made by " - "version %(newer)s of " - "Gramps, while you are running an older version %(older)s. " - "The file will not be imported. Please upgrade to the " - "latest version of Gramps and try again." ) % { - 'newer' : self.__gramps_version, 'older' : VERSION } - raise GrampsImportError('', msg) + msg = _( + "The .gramps file you are importing was made by " + "version %(newer)s of " + "Gramps, while you are running an older version %(older)s. " + "The file will not be imported. Please upgrade to the " + "latest version of Gramps and try again." + ) % {"newer": self.__gramps_version, "older": VERSION} + raise GrampsImportError("", msg) if self.__xml_version < (1, 0, 0): - msg = _("The .gramps file you are importing was made by version " - "%(oldgramps)s of Gramps, while you are running a more " - "recent version %(newgramps)s.\n\n" - "The file will not be imported. Please use an older version" - " of Gramps that supports version %(xmlversion)s of the " - "xml.\nSee\n %(gramps_wiki_xml_url)s\n for more info." - ) % {'oldgramps': self.__gramps_version, - 'newgramps': VERSION, - 'xmlversion': xmlversion_str, - 'gramps_wiki_xml_url': URL_WIKISTRING + "Gramps_XML" , - } - raise GrampsImportError(_('The file will not be imported'), msg) + msg = _( + "The .gramps file you are importing was made by version " + "%(oldgramps)s of Gramps, while you are running a more " + "recent version %(newgramps)s.\n\n" + "The file will not be imported. Please use an older version" + " of Gramps that supports version %(xmlversion)s of the " + "xml.\nSee\n %(gramps_wiki_xml_url)s\n for more info." + ) % { + "oldgramps": self.__gramps_version, + "newgramps": VERSION, + "xmlversion": xmlversion_str, + "gramps_wiki_xml_url": URL_WIKISTRING + "Gramps_XML", + } + raise GrampsImportError(_("The file will not be imported"), msg) elif self.__xml_version < (1, 1, 0): - msg = _("The .gramps file you are importing was made by version " - "%(oldgramps)s of Gramps, while you are running a much " - "more recent version %(newgramps)s.\n\n" - "Ensure after import everything is imported correctly. In " - "the event of problems, please submit a bug and use an " - "older version of Gramps in the meantime to import this " - "file, which is version %(xmlversion)s of the xml.\nSee\n " - "%(gramps_wiki_xml_url)s\nfor more info." - ) % {'oldgramps': self.__gramps_version, - 'newgramps': VERSION, - 'xmlversion': xmlversion_str, - 'gramps_wiki_xml_url': URL_WIKISTRING + "Gramps_XML" , - } - self.user.warn(_('Old xml file'), msg) + msg = _( + "The .gramps file you are importing was made by version " + "%(oldgramps)s of Gramps, while you are running a much " + "more recent version %(newgramps)s.\n\n" + "Ensure after import everything is imported correctly. In " + "the event of problems, please submit a bug and use an " + "older version of Gramps in the meantime to import this " + "file, which is version %(xmlversion)s of the xml.\nSee\n " + "%(gramps_wiki_xml_url)s\nfor more info." + ) % { + "oldgramps": self.__gramps_version, + "newgramps": VERSION, + "xmlversion": xmlversion_str, + "gramps_wiki_xml_url": URL_WIKISTRING + "Gramps_XML", + } + self.user.warn(_("Old xml file"), msg) def start_lds_ord(self, attrs): self.ord = LdsOrd() - self.ord.set_type_from_xml(attrs['type']) + self.ord.set_type_from_xml(attrs["type"]) self.ord.private = bool(attrs.get("priv")) if self.person: self.person.lds_ord_list.append(self.ord) @@ -1056,16 +1200,16 @@ class GrampsParser(UpdateCallback): self.family.lds_ord_list.append(self.ord) def start_temple(self, attrs): - self.ord.set_temple(attrs['val']) + self.ord.set_temple(attrs["val"]) def start_data_item(self, attrs): """ Deprecated in 1.6.0, replaced by srcattribute """ - sat = SrcAttributeType(attrs['key']) + sat = SrcAttributeType(attrs["key"]) sa = SrcAttribute() sa.set_type(sat) - sa.set_value(attrs['value']) + sa.set_value(attrs["value"]) if self.source: self.source.add_attribute(sa) else: @@ -1074,30 +1218,27 @@ class GrampsParser(UpdateCallback): def start_status(self, attrs): try: # old xml with integer statuses - self.ord.set_status(int(attrs['val'])) + self.ord.set_status(int(attrs["val"])) except ValueError: # string - self.ord.set_status_from_xml(attrs['val']) + self.ord.set_status_from_xml(attrs["val"]) def start_sealed_to(self, attrs): """ Add a family reference to the LDS ordinance currently processed. """ - if 'hlink' in attrs: - handle = self.inaugurate(attrs['hlink'], "family", Family) - else: # old style XML - handle = self.inaugurate_id(attrs.get('ref'), FAMILY_KEY, - Family) + if "hlink" in attrs: + handle = self.inaugurate(attrs["hlink"], "family", Family) + else: # old style XML + handle = self.inaugurate_id(attrs.get("ref"), FAMILY_KEY, Family) self.ord.set_family_handle(handle) def start_place(self, attrs): - """A reference to a place in an object: event or lds_ord - """ - if 'hlink' in attrs: - handle = self.inaugurate(attrs['hlink'], "place", Place) - else: # old style XML - handle = self.inaugurate_id(attrs.get('ref'), PLACE_KEY, - Place) + """A reference to a place in an object: event or lds_ord""" + if "hlink" in attrs: + handle = self.inaugurate(attrs["hlink"], "place", Place) + else: # old style XML + handle = self.inaugurate_id(attrs.get("ref"), PLACE_KEY, Place) if self.ord: self.ord.set_place_handle(handle) elif self.event: @@ -1109,35 +1250,39 @@ class GrampsParser(UpdateCallback): id, privacy and changetime. """ self.placeobj = Place() - if 'handle' in attrs: - orig_handle = attrs['handle'].replace('_', '') - is_merge_candidate = (self.replace_import_handle and - self.db.has_place_handle(orig_handle)) + if "handle" in attrs: + orig_handle = attrs["handle"].replace("_", "") + is_merge_candidate = ( + self.replace_import_handle and self.db.has_place_handle(orig_handle) + ) self.inaugurate(orig_handle, "place", self.placeobj) - gramps_id = self.legalize_id(attrs.get('id'), PLACE_KEY, - self.pidswap, self.db.pid2user_format, - self.db.find_next_place_gramps_id, - self.db.has_place_gramps_id) + gramps_id = self.legalize_id( + attrs.get("id"), + PLACE_KEY, + self.pidswap, + self.db.pid2user_format, + self.db.find_next_place_gramps_id, + self.db.has_place_gramps_id, + ) self.placeobj.set_gramps_id(gramps_id) if is_merge_candidate: orig_place = self.db.get_place_from_handle(orig_handle) - self.info.add('merge-candidate', PLACE_KEY, orig_place, - self.placeobj) + self.info.add("merge-candidate", PLACE_KEY, orig_place, self.placeobj) else: - self.inaugurate_id(attrs.get('id'), PLACE_KEY, self.placeobj) + self.inaugurate_id(attrs.get("id"), PLACE_KEY, self.placeobj) self.placeobj.private = bool(attrs.get("priv")) - self.placeobj.change = int(attrs.get('change', self.change)) + self.placeobj.change = int(attrs.get("change", self.change)) if self.__xml_version == (1, 6, 0): place_name = PlaceName() - place_name.set_value(attrs.get('name', '')) + place_name.set_value(attrs.get("name", "")) self.placeobj.name = place_name - if 'type' in attrs: - self.placeobj.place_type.set_from_xml_str(attrs.get('type')) - self.info.add('new-object', PLACE_KEY, self.placeobj) + if "type" in attrs: + self.placeobj.place_type.set_from_xml_str(attrs.get("type")) + self.info.add("new-object", PLACE_KEY, self.placeobj) self.place_names = 0 # Gramps LEGACY: title in the placeobj tag - self.placeobj.title = attrs.get('title', '') + self.placeobj.title = attrs.get("title", "") self.locations = 0 self.update(self.p.CurrentLineNumber) if self.default_tag: @@ -1149,27 +1294,29 @@ class GrampsParser(UpdateCallback): take up quite a bit of time""" loc = Location() - loc.street = attrs.get('street', '') - loc.locality = attrs.get('locality', '') - loc.city = attrs.get('city', '') - loc.parish = attrs.get('parish', '') - loc.county = attrs.get('county', '') - loc.state = attrs.get('state', '') - loc.country = attrs.get('country', '') - loc.postal = attrs.get('postal', '') - loc.phone = attrs.get('phone', '') + loc.street = attrs.get("street", "") + loc.locality = attrs.get("locality", "") + loc.city = attrs.get("city", "") + loc.parish = attrs.get("parish", "") + loc.county = attrs.get("county", "") + loc.state = attrs.get("state", "") + loc.country = attrs.get("country", "") + loc.postal = attrs.get("postal", "") + loc.phone = attrs.get("phone", "") if self.__xml_version < (1, 6, 0): if self.locations > 0: self.placeobj.add_alternate_locations(loc) else: - location = (attrs.get('street', ''), - attrs.get('locality', ''), - attrs.get('parish', ''), - attrs.get('city', ''), - attrs.get('county', ''), - attrs.get('state', ''), - attrs.get('country', '')) + location = ( + attrs.get("street", ""), + attrs.get("locality", ""), + attrs.get("parish", ""), + attrs.get("city", ""), + attrs.get("county", ""), + attrs.get("state", ""), + attrs.get("country", ""), + ) self.place_import.store_location(location, self.placeobj.handle) for level, name in enumerate(location): @@ -1180,8 +1327,8 @@ class GrampsParser(UpdateCallback): self.placeobj.set_name(place_name) type_num = 7 - level if name else PlaceType.UNKNOWN self.placeobj.set_type(PlaceType(type_num)) - codes = [attrs.get('postal'), attrs.get('phone')] - self.placeobj.set_code(' '.join(code for code in codes if code)) + codes = [attrs.get("postal"), attrs.get("phone")] + self.placeobj.set_code(" ".join(code for code in codes if code)) else: self.placeobj.add_alternate_locations(loc) @@ -1196,24 +1343,24 @@ class GrampsParser(UpdateCallback): # Parse witnesses created by older gramps self.in_witness = True self.witness_comment = "" - if 'name' in attrs: + if "name" in attrs: note = Note() note.handle = create_id() - note.set(_("Witness name: %s") % attrs['name']) + note.set(_("Witness name: %s") % attrs["name"]) note.type.set(NoteType.EVENT) note.private = self.event.private self.db.add_note(note, self.trans) - #set correct change time + # set correct change time self.db.commit_note(note, self.trans, self.change) - self.info.add('new-object', NOTE_KEY, note) + self.info.add("new-object", NOTE_KEY, note) self.event.add_note(note.handle) return person = Person() - if 'hlink' in attrs: - self.inaugurate(attrs['hlink'], "person", person) - elif 'ref' in attrs: - self.inaugurate_id(attrs['ref'], PERSON_KEY, person) + if "hlink" in attrs: + self.inaugurate(attrs["hlink"], "person", person) + elif "ref" in attrs: + self.inaugurate_id(attrs["ref"], PERSON_KEY, person) else: person = None @@ -1227,8 +1374,8 @@ class GrampsParser(UpdateCallback): self.db.commit_person(person, self.trans, self.change) def start_coord(self, attrs): - self.placeobj.lat = attrs.get('lat', '') - self.placeobj.long = attrs.get('long', '') + self.placeobj.lat = attrs.get("lat", "") + self.placeobj.long = attrs.get("long", "") def start_event(self, attrs): """ @@ -1241,34 +1388,38 @@ class GrampsParser(UpdateCallback): self.event = Event() self.event.handle = create_id() self.event.type = EventType() - self.event.type.set_from_xml_str(attrs['type']) + self.event.type.set_from_xml_str(attrs["type"]) self.db.add_event(self.event, self.trans) - #set correct change time + # set correct change time self.db.commit_event(self.event, self.trans, self.change) - self.info.add('new-object', EVENT_KEY, self.event) + self.info.add("new-object", EVENT_KEY, self.event) else: # This is new event, with ID and handle already existing self.update(self.p.CurrentLineNumber) self.event = Event() - if 'handle' in attrs: - orig_handle = attrs['handle'].replace('_', '') - is_merge_candidate = (self.replace_import_handle and - self.db.has_event_handle(orig_handle)) + if "handle" in attrs: + orig_handle = attrs["handle"].replace("_", "") + is_merge_candidate = ( + self.replace_import_handle and self.db.has_event_handle(orig_handle) + ) self.inaugurate(orig_handle, "event", self.event) - gramps_id = self.legalize_id(attrs.get('id'), EVENT_KEY, - self.eidswap, self.db.eid2user_format, - self.db.find_next_event_gramps_id, - self.db.has_event_gramps_id) + gramps_id = self.legalize_id( + attrs.get("id"), + EVENT_KEY, + self.eidswap, + self.db.eid2user_format, + self.db.find_next_event_gramps_id, + self.db.has_event_gramps_id, + ) self.event.set_gramps_id(gramps_id) if is_merge_candidate: orig_event = self.db.get_event_from_handle(orig_handle) - self.info.add('merge-candidate', EVENT_KEY, orig_event, - self.event) - else: #old style XML - self.inaugurate_id(attrs.get('id'), EVENT_KEY, self.event) + self.info.add("merge-candidate", EVENT_KEY, orig_event, self.event) + else: # old style XML + self.inaugurate_id(attrs.get("id"), EVENT_KEY, self.event) self.event.private = bool(attrs.get("priv")) - self.event.change = int(attrs.get('change', self.change)) - self.info.add('new-object', EVENT_KEY, self.event) + self.event.change = int(attrs.get("change", self.change)) + self.info.add("new-object", EVENT_KEY, self.event) if self.default_tag: self.event.add_tag(self.default_tag.handle) return self.event @@ -1278,16 +1429,17 @@ class GrampsParser(UpdateCallback): Add an event reference to the object currently processed. """ self.eventref = EventRef() - if 'hlink' in attrs: - handle = self.inaugurate(attrs['hlink'], "event", Event) - else: # there is no old style XML - raise GrampsImportError(_("The Gramps Xml you are trying to " - "import is malformed."), _("Any event reference must have a " - "'hlink' attribute.")) + if "hlink" in attrs: + handle = self.inaugurate(attrs["hlink"], "event", Event) + else: # there is no old style XML + raise GrampsImportError( + _("The Gramps Xml you are trying to " "import is malformed."), + _("Any event reference must have a " "'hlink' attribute."), + ) self.eventref.ref = handle - self.eventref.private = bool(attrs.get('priv')) - if 'role' in attrs: - self.eventref.role.set_from_xml_str(attrs['role']) + self.eventref.private = bool(attrs.get("priv")) + if "role" in attrs: + self.eventref.role.set_from_xml_str(attrs["role"]) # We count here on events being already parsed prior to parsing # people or families. This code will fail if this is not true. @@ -1298,13 +1450,17 @@ class GrampsParser(UpdateCallback): if self.family: self.family.add_event_ref(self.eventref) elif self.person: - if (event.type == EventType.BIRTH) \ - and (self.eventref.role == EventRoleType.PRIMARY) \ - and (self.person.get_birth_ref() is None): + if ( + (event.type == EventType.BIRTH) + and (self.eventref.role == EventRoleType.PRIMARY) + and (self.person.get_birth_ref() is None) + ): self.person.set_birth_ref(self.eventref) - elif (event.type == EventType.DEATH) \ - and (self.eventref.role == EventRoleType.PRIMARY) \ - and (self.person.get_death_ref() is None): + elif ( + (event.type == EventType.DEATH) + and (self.eventref.role == EventRoleType.PRIMARY) + and (self.person.get_death_ref() is None) + ): self.person.set_death_ref(self.eventref) else: self.person.add_event_ref(self.eventref) @@ -1314,7 +1470,7 @@ class GrampsParser(UpdateCallback): Add a place reference to the place currently being processed. """ self.placeref = PlaceRef() - handle = self.inaugurate(attrs['hlink'], "place", Place) + handle = self.inaugurate(attrs["hlink"], "place", Place) self.placeref.ref = handle self.placeobj.add_placeref(self.placeref) @@ -1322,9 +1478,9 @@ class GrampsParser(UpdateCallback): self.attribute = Attribute() self.attribute.private = bool(attrs.get("priv")) self.attribute.type = AttributeType() - if 'type' in attrs: + if "type" in attrs: self.attribute.type.set_from_xml_str(attrs["type"]) - self.attribute.value = attrs.get("value", '') + self.attribute.value = attrs.get("value", "") if self.photo: self.photo.add_attribute(self.attribute) elif self.object: @@ -1344,9 +1500,9 @@ class GrampsParser(UpdateCallback): self.srcattribute = SrcAttribute() self.srcattribute.private = bool(attrs.get("priv")) self.srcattribute.type = SrcAttributeType() - if 'type' in attrs: + if "type" in attrs: self.srcattribute.type.set_from_xml_str(attrs["type"]) - self.srcattribute.value = attrs.get("value", '') + self.srcattribute.value = attrs.get("value", "") if self.source: self.source.add_attribute(self.srcattribute) elif self.citation: @@ -1360,67 +1516,83 @@ class GrampsParser(UpdateCallback): """ Add a bookmark to db. """ - target = attrs.get('target') + target = attrs.get("target") if not target: # Old XML. Can be either handle or id reference # and this is guaranteed to be a person bookmark - if 'hlink' in attrs: - handle = self.inaugurate(attrs['hlink'], "person", - Person) + if "hlink" in attrs: + handle = self.inaugurate(attrs["hlink"], "person", Person) else: - handle = self.inaugurate_id(attrs.get('ref'), PERSON_KEY, - Person) + handle = self.inaugurate_id(attrs.get("ref"), PERSON_KEY, Person) self.db.bookmarks.append(handle) return # This is new XML, so we are guaranteed to have a handle ref - handle = attrs['hlink'].replace('_', '') + handle = attrs["hlink"].replace("_", "") handle = self.import_handles[handle][target][HANDLE] # Due to pre 2.2.9 bug, bookmarks might be handle of other object # Make sure those are filtered out. # Bookmarks are at end, so all handle must exist before we do bookmrks - if target == 'person': - if (self.db.get_person_from_handle(handle) is not None - and handle not in self.db.bookmarks.get() ): + if target == "person": + if ( + self.db.get_person_from_handle(handle) is not None + and handle not in self.db.bookmarks.get() + ): self.db.bookmarks.append(handle) - elif target == 'family': - if (self.db.get_family_from_handle(handle) is not None - and handle not in self.db.family_bookmarks.get() ): + elif target == "family": + if ( + self.db.get_family_from_handle(handle) is not None + and handle not in self.db.family_bookmarks.get() + ): self.db.family_bookmarks.append(handle) - elif target == 'event': - if (self.db.get_event_from_handle(handle) is not None - and handle not in self.db.event_bookmarks.get() ): + elif target == "event": + if ( + self.db.get_event_from_handle(handle) is not None + and handle not in self.db.event_bookmarks.get() + ): self.db.event_bookmarks.append(handle) - elif target == 'source': - if (self.db.get_source_from_handle(handle) is not None - and handle not in self.db.source_bookmarks.get() ): + elif target == "source": + if ( + self.db.get_source_from_handle(handle) is not None + and handle not in self.db.source_bookmarks.get() + ): self.db.source_bookmarks.append(handle) - elif target == 'citation': - if (self.db.get_citation_from_handle(handle) is not None - and handle not in self.db.citation_bookmarks.get() ): + elif target == "citation": + if ( + self.db.get_citation_from_handle(handle) is not None + and handle not in self.db.citation_bookmarks.get() + ): self.db.citation_bookmarks.append(handle) - elif target == 'place': - if (self.db.get_place_from_handle(handle) is not None - and handle not in self.db.place_bookmarks.get() ): + elif target == "place": + if ( + self.db.get_place_from_handle(handle) is not None + and handle not in self.db.place_bookmarks.get() + ): self.db.place_bookmarks.append(handle) - elif target == 'media': - if (self.db.get_media_from_handle(handle) is not None - and handle not in self.db.media_bookmarks.get() ): + elif target == "media": + if ( + self.db.get_media_from_handle(handle) is not None + and handle not in self.db.media_bookmarks.get() + ): self.db.media_bookmarks.append(handle) - elif target == 'repository': - if (self.db.get_repository_from_handle(handle) - is not None and handle not in self.db.repo_bookmarks.get()): + elif target == "repository": + if ( + self.db.get_repository_from_handle(handle) is not None + and handle not in self.db.repo_bookmarks.get() + ): self.db.repo_bookmarks.append(handle) - elif target == 'note': - if (self.db.get_note_from_handle(handle) is not None - and handle not in self.db.note_bookmarks.get() ): + elif target == "note": + if ( + self.db.get_note_from_handle(handle) is not None + and handle not in self.db.note_bookmarks.get() + ): self.db.note_bookmarks.append(handle) def start_format(self, attrs): - number = int(attrs['number']) - name = attrs['name'] - fmt_str = attrs['fmt_str'] - active = bool(attrs.get('active', True)) + number = int(attrs["number"]) + name = attrs["name"] + fmt_str = attrs["fmt_str"] + active = bool(attrs.get("active", True)) if number in self.taken_name_format_numbers: number = self.remap_name_format(number) @@ -1428,7 +1600,7 @@ class GrampsParser(UpdateCallback): self.name_formats.append((number, name, fmt_str, active)) def remap_name_format(self, old_number): - if old_number in self.name_formats_map: # This should not happen + if old_number in self.name_formats_map: # This should not happen return self.name_formats_map[old_number] # Find the lowest new number not taken yet: new_number = -1 @@ -1448,25 +1620,29 @@ class GrampsParser(UpdateCallback): """ self.update(self.p.CurrentLineNumber) self.person = Person() - if 'handle' in attrs: - orig_handle = attrs['handle'].replace('_', '') - is_merge_candidate = (self.replace_import_handle and - self.db.has_person_handle(orig_handle)) + if "handle" in attrs: + orig_handle = attrs["handle"].replace("_", "") + is_merge_candidate = ( + self.replace_import_handle and self.db.has_person_handle(orig_handle) + ) self.inaugurate(orig_handle, "person", self.person) - gramps_id = self.legalize_id(attrs.get('id'), PERSON_KEY, - self.idswap, self.db.id2user_format, - self.db.find_next_person_gramps_id, - self.db.has_person_gramps_id) + gramps_id = self.legalize_id( + attrs.get("id"), + PERSON_KEY, + self.idswap, + self.db.id2user_format, + self.db.find_next_person_gramps_id, + self.db.has_person_gramps_id, + ) self.person.set_gramps_id(gramps_id) if is_merge_candidate: orig_person = self.db.get_person_from_handle(orig_handle) - self.info.add('merge-candidate', PERSON_KEY, orig_person, - self.person) - else: # old style XML - self.inaugurate_id(attrs.get('id'), PERSON_KEY, self.person) + self.info.add("merge-candidate", PERSON_KEY, orig_person, self.person) + else: # old style XML + self.inaugurate_id(attrs.get("id"), PERSON_KEY, self.person) self.person.private = bool(attrs.get("priv")) - self.person.change = int(attrs.get('change', self.change)) - self.info.add('new-object', PERSON_KEY, self.person) + self.person.change = int(attrs.get("change", self.change)) + self.info.add("new-object", PERSON_KEY, self.person) self.convert_marker(attrs, self.person) if self.default_tag: self.person.add_tag(self.default_tag.handle) @@ -1476,30 +1652,28 @@ class GrampsParser(UpdateCallback): """ Store the home person of the database. """ - if 'home' in attrs: - handle = self.inaugurate(attrs['home'], "person", Person) + if "home" in attrs: + handle = self.inaugurate(attrs["home"], "person", Person) self.home = handle def start_father(self, attrs): """ Add a father reference to the family currently processed. """ - if 'hlink' in attrs: - handle = self.inaugurate(attrs['hlink'], "person", Person) - else: # old style XML - handle = self.inaugurate_id(attrs.get('ref'), PERSON_KEY, - Person) + if "hlink" in attrs: + handle = self.inaugurate(attrs["hlink"], "person", Person) + else: # old style XML + handle = self.inaugurate_id(attrs.get("ref"), PERSON_KEY, Person) self.family.set_father_handle(handle) def start_mother(self, attrs): """ Add a mother reference to the family currently processed. """ - if 'hlink' in attrs: - handle = self.inaugurate(attrs['hlink'], "person", Person) - else: # old style XML - handle = self.inaugurate_id(attrs.get('ref'), PERSON_KEY, - Person) + if "hlink" in attrs: + handle = self.inaugurate(attrs["hlink"], "person", Person) + else: # old style XML + handle = self.inaugurate_id(attrs.get("ref"), PERSON_KEY, Person) self.family.set_mother_handle(handle) def start_child(self, attrs): @@ -1509,16 +1683,14 @@ class GrampsParser(UpdateCallback): Here we are handling the old XML, in which frel and mrel belonged to the "childof" tag """ - if 'hlink' in attrs: - handle = self.inaugurate(attrs['hlink'], "person", Person) - else: # old style XML - handle = self.inaugurate_id(attrs.get('ref'), PERSON_KEY, - Person) + if "hlink" in attrs: + handle = self.inaugurate(attrs["hlink"], "person", Person) + else: # old style XML + handle = self.inaugurate_id(attrs.get("ref"), PERSON_KEY, Person) # If that were the case then childref_map has the childref ready if (self.family.handle, handle) in self.childref_map: - self.family.add_child_ref( - self.childref_map[(self.family.handle, handle)]) + self.family.add_child_ref(self.childref_map[(self.family.handle, handle)]) def start_childref(self, attrs): """ @@ -1528,16 +1700,16 @@ class GrampsParser(UpdateCallback): belong to the "childref" tag under family. """ self.childref = ChildRef() - handle = self.inaugurate(attrs['hlink'], "person", Person) + handle = self.inaugurate(attrs["hlink"], "person", Person) self.childref.ref = handle - self.childref.private = bool(attrs.get('priv')) + self.childref.private = bool(attrs.get("priv")) mrel = ChildRefType() - if attrs.get('mrel'): - mrel.set_from_xml_str(attrs['mrel']) + if attrs.get("mrel"): + mrel.set_from_xml_str(attrs["mrel"]) frel = ChildRefType() - if attrs.get('frel'): - frel.set_from_xml_str(attrs['frel']) + if attrs.get("frel"): + frel.set_from_xml_str(attrs["frel"]) if not mrel.is_default(): self.childref.set_mother_relation(mrel) @@ -1550,15 +1722,16 @@ class GrampsParser(UpdateCallback): Add a person reference to the person currently processed. """ self.personref = PersonRef() - if 'hlink' in attrs: - handle = self.inaugurate(attrs['hlink'], "person", Person) - else: # there is no old style XML - raise GrampsImportError(_("The Gramps Xml you are trying to " - "import is malformed."), _("Any person reference must have a " - "'hlink' attribute.")) + if "hlink" in attrs: + handle = self.inaugurate(attrs["hlink"], "person", Person) + else: # there is no old style XML + raise GrampsImportError( + _("The Gramps Xml you are trying to " "import is malformed."), + _("Any person reference must have a " "'hlink' attribute."), + ) self.personref.ref = handle - self.personref.private = bool(attrs.get('priv')) - self.personref.rel = attrs['rel'] + self.personref.private = bool(attrs.get("priv")) + self.personref.rel = attrs["rel"] self.person.add_person_ref(self.personref) def start_url(self, attrs): @@ -1566,9 +1739,9 @@ class GrampsParser(UpdateCallback): return url = Url() url.path = attrs["href"] - url.set_description(attrs.get("description", '')) - url.private = bool(attrs.get('priv')) - url.type.set_from_xml_str(attrs.get('type', '')) + url.set_description(attrs.get("description", "")) + url.private = bool(attrs.get("priv")) + url.type.set_from_xml_str(attrs.get("type", "")) if self.person: self.person.add_url(url) elif self.placeobj: @@ -1583,28 +1756,32 @@ class GrampsParser(UpdateCallback): """ self.update(self.p.CurrentLineNumber) self.family = Family() - if 'handle' in attrs: - orig_handle = attrs['handle'].replace('_', '') - is_merge_candidate = (self.replace_import_handle and - self.db.has_family_handle(orig_handle)) + if "handle" in attrs: + orig_handle = attrs["handle"].replace("_", "") + is_merge_candidate = ( + self.replace_import_handle and self.db.has_family_handle(orig_handle) + ) self.inaugurate(orig_handle, "family", self.family) - gramps_id = self.legalize_id(attrs.get('id'), FAMILY_KEY, - self.fidswap, self.db.fid2user_format, - self.db.find_next_family_gramps_id, - self.db.has_family_gramps_id) + gramps_id = self.legalize_id( + attrs.get("id"), + FAMILY_KEY, + self.fidswap, + self.db.fid2user_format, + self.db.find_next_family_gramps_id, + self.db.has_family_gramps_id, + ) self.family.set_gramps_id(gramps_id) if is_merge_candidate: orig_family = self.db.get_family_from_handle(orig_handle) - self.info.add('merge-candidate', FAMILY_KEY, orig_family, - self.family) - else: # old style XML - self.inaugurate_id(attrs.get('id'), FAMILY_KEY, self.family) + self.info.add("merge-candidate", FAMILY_KEY, orig_family, self.family) + else: # old style XML + self.inaugurate_id(attrs.get("id"), FAMILY_KEY, self.family) self.family.private = bool(attrs.get("priv")) - self.family.change = int(attrs.get('change', self.change)) - self.info.add('new-object', FAMILY_KEY, self.family) + self.family.change = int(attrs.get("change", self.change)) + self.info.add("new-object", FAMILY_KEY, self.family) # Gramps LEGACY: the type now belongs to tag # Here we need to support old format of - if 'type' in attrs: + if "type" in attrs: self.family.type.set_from_xml_str(attrs["type"]) self.convert_marker(attrs, self.family) if self.default_tag: @@ -1612,24 +1789,24 @@ class GrampsParser(UpdateCallback): return self.family def start_rel(self, attrs): - if 'type' in attrs: + if "type" in attrs: self.family.type.set_from_xml_str(attrs["type"]) def start_file(self, attrs): - self.object.mime = attrs['mime'] - if 'description' in attrs: - self.object.desc = attrs['description'] + self.object.mime = attrs["mime"] + if "description" in attrs: + self.object.desc = attrs["description"] else: self.object.desc = "" - #keep value of path, no longer make absolute paths on import + # keep value of path, no longer make absolute paths on import src = attrs["src"] if src: self.object.path = src if self.all_abs and not os.path.isabs(src): self.all_abs = False - self.info.add('relative-path', None, None) - if 'checksum' in attrs: - self.object.checksum = attrs['checksum'] + self.info.add("relative-path", None, None) + if "checksum" in attrs: + self.object.checksum = attrs["checksum"] else: if os.path.isabs(src): full_path = src @@ -1642,20 +1819,19 @@ class GrampsParser(UpdateCallback): Add a family reference to the person currently processed in which that person is a child. """ - if 'hlink' in attrs: - handle = self.inaugurate(attrs['hlink'], "family", Family) - else: # old style XML - handle = self.inaugurate_id(attrs.get('ref'), FAMILY_KEY, - Family) + if "hlink" in attrs: + handle = self.inaugurate(attrs["hlink"], "family", Family) + else: # old style XML + handle = self.inaugurate_id(attrs.get("ref"), FAMILY_KEY, Family) # Here we are handling the old XML, in which # frel and mrel belonged to the "childof" tag mrel = ChildRefType() frel = ChildRefType() - if 'mrel' in attrs: - mrel.set_from_xml_str(attrs['mrel']) - if 'frel' in attrs: - frel.set_from_xml_str(attrs['frel']) + if "mrel" in attrs: + mrel.set_from_xml_str(attrs["mrel"]) + if "frel" in attrs: + frel.set_from_xml_str(attrs["frel"]) childref = ChildRef() childref.ref = self.person.handle @@ -1671,24 +1847,23 @@ class GrampsParser(UpdateCallback): Add a family reference to the person currently processed in which that person is a parent. """ - if 'hlink' in attrs: - handle = self.inaugurate(attrs['hlink'], "family", Family) - else: # old style XML - handle = self.inaugurate_id(attrs.get('ref'), FAMILY_KEY, - Family) + if "hlink" in attrs: + handle = self.inaugurate(attrs["hlink"], "family", Family) + else: # old style XML + handle = self.inaugurate_id(attrs.get("ref"), FAMILY_KEY, Family) self.person.add_family_handle(handle) def start_name(self, attrs): if self.person: self.start_person_name(attrs) - if self.placeobj: # XML 1.7.0 + if self.placeobj: # XML 1.7.0 self.start_place_name(attrs) def start_place_name(self, attrs): self.place_name = PlaceName() self.place_name.set_value(attrs["value"]) if "lang" in attrs: - self.place_name.set_language(attrs["lang"]) + self.place_name.set_language(attrs["lang"]) if self.place_names == 0: self.placeobj.set_name(self.place_name) else: @@ -1698,9 +1873,9 @@ class GrampsParser(UpdateCallback): def start_person_name(self, attrs): if not self.in_witness: self.name = Name() - name_type = attrs.get('type', "Birth Name") + name_type = attrs.get("type", "Birth Name") # Mapping "Other Name" from gramps 2.0.x to Unknown - if (self.__xml_version == (1, 0, 0)) and (name_type == 'Other Name'): + if (self.__xml_version == (1, 0, 0)) and (name_type == "Other Name"): self.name.set_type(NameType.UNKNOWN) else: self.name.type.set_from_xml_str(name_type) @@ -1736,53 +1911,59 @@ class GrampsParser(UpdateCallback): self.surname.origintype.set_from_xml_str(origin_type) def start_namemap(self, attrs): - type = attrs.get('type') - key = attrs['key'] - value = attrs['value'] - if type == 'group_as': + type = attrs.get("type") + key = attrs["key"] + value = attrs["value"] + if type == "group_as": if self.db.has_name_group_key(key): present = self.db.get_name_group_mapping(key) if not value == present: - msg = _('Your Family Tree groups name "%(key)s" together' - ' with "%(parent)s", did not change this grouping to "%(value)s".') % { - 'key' : key, 'parent' : present, 'value' : value } + msg = _( + 'Your Family Tree groups name "%(key)s" together' + ' with "%(parent)s", did not change this grouping to "%(value)s".' + ) % {"key": key, "parent": present, "value": value} self.user.warn(_("Gramps ignored a name grouping"), msg) - elif value != 'None': # None test fixes file corrupted by 11011 + elif value != "None": # None test fixes file corrupted by 11011 self.db.set_name_group_mapping(key, value) def start_last(self, attrs): - """ This is the element in version < 1.4.0 to do the surname""" + """This is the element in version < 1.4.0 to do the surname""" self.surname = Surname() - self.surname.prefix = attrs.get('prefix', '') - self.name.group_as = attrs.get('group', '') + self.surname.prefix = attrs.get("prefix", "") + self.name.group_as = attrs.get("group", "") def start_patronymic(self, attrs): - """ This is the element in version < 1.4.0 to do the patronymic""" + """This is the element in version < 1.4.0 to do the patronymic""" self.surnamepat = Surname() - self.surnamepat.set_origintype(NameOriginType( - NameOriginType.PATRONYMIC)) + self.surnamepat.set_origintype(NameOriginType(NameOriginType.PATRONYMIC)) def start_style(self, attrs): """ Styled text tag in notes (v1.4.0 onwards). """ tagtype = StyledTextTagType() - tagtype.set_from_xml_str(attrs['name'].lower()) + tagtype.set_from_xml_str(attrs["name"].lower()) try: - val = attrs['value'] + val = attrs["value"] match = self.grampsuri.match(val) if match: - target = {"Person" : "person", "Family" : "family", - "Event" : "event", "Place" : "place", - "Source" : "source", "Citation" : "citation", - "Repository" : "repository", "Media" : "media", - "Note" : "note"}[str(match.group('object_class'))] - if match.group('handle') in self.import_handles: - if target in self.import_handles[match.group('handle')]: + target = { + "Person": "person", + "Family": "family", + "Event": "event", + "Place": "place", + "Source": "source", + "Citation": "citation", + "Repository": "repository", + "Media": "media", + "Note": "note", + }[str(match.group("object_class"))] + if match.group("handle") in self.import_handles: + if target in self.import_handles[match.group("handle")]: val = "gramps://%s/handle/%s" % ( - match.group('object_class'), - self.import_handles[match.group('handle')] - [target][HANDLE]) + match.group("object_class"), + self.import_handles[match.group("handle")][target][HANDLE], + ) tagvalue = StyledTextTagType.STYLE_TYPE[int(tagtype)](val) except KeyError: tagvalue = None @@ -1802,12 +1983,12 @@ class GrampsParser(UpdateCallback): # Tag defintion self.tag = Tag() - self.inaugurate(attrs['handle'], "tag", self.tag) - self.tag.change = int(attrs.get('change', self.change)) - self.info.add('new-object', TAG_KEY, self.tag) - self.tag.set_name(attrs.get('name', _('Unknown when imported'))) - self.tag.set_color(attrs.get('color', '#000000000000')) - self.tag.set_priority(int(attrs.get('priority', 0))) + self.inaugurate(attrs["handle"], "tag", self.tag) + self.tag.change = int(attrs.get("change", self.change)) + self.info.add("new-object", TAG_KEY, self.tag) + self.tag.set_name(attrs.get("name", _("Unknown when imported"))) + self.tag.set_color(attrs.get("color", "#000000000000")) + self.tag.set_priority(int(attrs.get("priority", 0))) return self.tag def stop_tag(self, *tag): @@ -1821,7 +2002,7 @@ class GrampsParser(UpdateCallback): """ Tag reference in a primary object. """ - handle = self.inaugurate(attrs['hlink'], "tag", Tag) + handle = self.inaugurate(attrs["hlink"], "tag", Tag) if self.person: self.person.add_tag(handle) @@ -1851,8 +2032,7 @@ class GrampsParser(UpdateCallback): self.citation.add_tag(handle) def start_range(self, attrs): - self.note_tags[-1].ranges.append((int(attrs['start']), - int(attrs['end']))) + self.note_tags[-1].ranges.append((int(attrs["start"]), int(attrs["end"]))) def start_note(self, attrs): """ @@ -1860,32 +2040,35 @@ class GrampsParser(UpdateCallback): id, privacy, changetime, format and type. """ self.in_note = 0 - if 'handle' in attrs: + if "handle" in attrs: # This is new note, with ID and handle already existing self.update(self.p.CurrentLineNumber) self.note = Note() - if 'handle' in attrs: - orig_handle = attrs['handle'].replace('_', '') - is_merge_candidate = (self.replace_import_handle and - self.db.has_note_handle(orig_handle)) + if "handle" in attrs: + orig_handle = attrs["handle"].replace("_", "") + is_merge_candidate = ( + self.replace_import_handle and self.db.has_note_handle(orig_handle) + ) self.inaugurate(orig_handle, "note", self.note) - gramps_id = self.legalize_id(attrs.get('id'), NOTE_KEY, - self.nidswap, self.db.nid2user_format, - self.db.find_next_note_gramps_id, - self.db.has_note_gramps_id) + gramps_id = self.legalize_id( + attrs.get("id"), + NOTE_KEY, + self.nidswap, + self.db.nid2user_format, + self.db.find_next_note_gramps_id, + self.db.has_note_gramps_id, + ) self.note.set_gramps_id(gramps_id) if is_merge_candidate: orig_note = self.db.get_note_from_handle(orig_handle) - self.info.add('merge-candicate', NOTE_KEY, orig_note, - self.note) + self.info.add("merge-candicate", NOTE_KEY, orig_note, self.note) else: - self.inaugurate_id(attrs.get('id'), NOTE_KEY, self.note) + self.inaugurate_id(attrs.get("id"), NOTE_KEY, self.note) self.note.private = bool(attrs.get("priv")) - self.note.change = int(attrs.get('change', self.change)) - self.info.add('new-object', NOTE_KEY, self.note) - self.note.format = int(attrs.get('format', Note.FLOWED)) - self.note.type.set_from_xml_str(attrs.get('type', - NoteType.UNKNOWN)) + self.note.change = int(attrs.get("change", self.change)) + self.info.add("new-object", NOTE_KEY, self.note) + self.note.format = int(attrs.get("format", Note.FLOWED)) + self.note.type.set_from_xml_str(attrs.get("type", NoteType.UNKNOWN)) self.convert_marker(attrs, self.note) # Since StyledText was introduced (XML v1.3.0) the clear text @@ -1901,7 +2084,7 @@ class GrampsParser(UpdateCallback): # On stop_note the reference to this note will be added self.note = Note() self.note.handle = create_id() - self.note.format = int(attrs.get('format', Note.FLOWED)) + self.note.format = int(attrs.get("format", Note.FLOWED)) # The order in this long if-then statement should reflect the # DTD: most deeply nested elements come first. if self.citation: @@ -1960,9 +2143,9 @@ class GrampsParser(UpdateCallback): self.note.private = self.repo.private self.db.add_note(self.note, self.trans) - #set correct change time + # set correct change time self.db.commit_note(self.note, self.trans, self.change) - self.info.add('new-object', NOTE_KEY, self.note) + self.info.add("new-object", NOTE_KEY, self.note) if self.default_tag: self.note.add_tag(self.default_tag.handle) return self.note @@ -1971,12 +2154,13 @@ class GrampsParser(UpdateCallback): """ Add a note reference to the object currently processed. """ - if 'hlink' in attrs: - handle = self.inaugurate(attrs['hlink'], "note", Note) + if "hlink" in attrs: + handle = self.inaugurate(attrs["hlink"], "note", Note) else: - raise GrampsImportError(_("The Gramps Xml you are trying to " - "import is malformed."), _("Any note reference must have a " - "'hlink' attribute.")) + raise GrampsImportError( + _("The Gramps Xml you are trying to " "import is malformed."), + _("Any note reference must have a " "'hlink' attribute."), + ) # The order in this long if-then statement should reflect the # DTD: most deeply nested elements come first. @@ -2052,7 +2236,7 @@ class GrampsParser(UpdateCallback): """ Add a citation reference to the object currently processed. """ - handle = self.inaugurate(attrs['hlink'], "citation", Citation) + handle = self.inaugurate(attrs["hlink"], "citation", Citation) self.__add_citation(handle) @@ -2063,25 +2247,29 @@ class GrampsParser(UpdateCallback): """ self.update(self.p.CurrentLineNumber) self.citation = Citation() - orig_handle = attrs['handle'].replace('_', '') - is_merge_candidate = (self.replace_import_handle and - self.db.has_citation_handle(orig_handle)) + orig_handle = attrs["handle"].replace("_", "") + is_merge_candidate = self.replace_import_handle and self.db.has_citation_handle( + orig_handle + ) self.inaugurate(orig_handle, "citation", self.citation) - gramps_id = self.legalize_id(attrs.get('id'), CITATION_KEY, - self.cidswap, self.db.cid2user_format, - self.db.find_next_citation_gramps_id, - self.db.has_citation_gramps_id) + gramps_id = self.legalize_id( + attrs.get("id"), + CITATION_KEY, + self.cidswap, + self.db.cid2user_format, + self.db.find_next_citation_gramps_id, + self.db.has_citation_gramps_id, + ) self.citation.set_gramps_id(gramps_id) if is_merge_candidate: orig_citation = self.db.get_citation_from_handle(orig_handle) - self.info.add('merge-candidate', CITATION_KEY, orig_citation, - self.citation) + self.info.add("merge-candidate", CITATION_KEY, orig_citation, self.citation) self.citation.private = bool(attrs.get("priv")) - self.citation.change = int(attrs.get('change', self.change)) + self.citation.change = int(attrs.get("change", self.change)) self.citation.confidence = ( - self.conf if self.__xml_version >= (1, 5, 1) - else 0 ) # See bug# 7125 - self.info.add('new-object', CITATION_KEY, self.citation) + self.conf if self.__xml_version >= (1, 5, 1) else 0 + ) # See bug# 7125 + self.info.add("new-object", CITATION_KEY, self.citation) if self.default_tag: self.citation.add_tag(self.default_tag.handle) return self.citation @@ -2090,11 +2278,10 @@ class GrampsParser(UpdateCallback): """ Add a source reference to the object currently processed. """ - if 'hlink' in attrs: - handle = self.inaugurate(attrs['hlink'], "source", Source) + if "hlink" in attrs: + handle = self.inaugurate(attrs["hlink"], "source", Source) else: - handle = self.inaugurate_id(attrs.get('ref'), SOURCE_KEY, - Source) + handle = self.inaugurate_id(attrs.get("ref"), SOURCE_KEY, Source) if self.citation: self.citation.set_reference_handle(handle) @@ -2119,25 +2306,29 @@ class GrampsParser(UpdateCallback): """ self.update(self.p.CurrentLineNumber) self.source = Source() - if 'handle' in attrs: - orig_handle = attrs['handle'].replace('_', '') - is_merge_candidate = (self.replace_import_handle and - self.db.has_source_handle(orig_handle)) + if "handle" in attrs: + orig_handle = attrs["handle"].replace("_", "") + is_merge_candidate = ( + self.replace_import_handle and self.db.has_source_handle(orig_handle) + ) self.inaugurate(orig_handle, "source", self.source) - gramps_id = self.legalize_id(attrs.get('id'), SOURCE_KEY, - self.sidswap, self.db.sid2user_format, - self.db.find_next_source_gramps_id, - self.db.has_source_gramps_id) + gramps_id = self.legalize_id( + attrs.get("id"), + SOURCE_KEY, + self.sidswap, + self.db.sid2user_format, + self.db.find_next_source_gramps_id, + self.db.has_source_gramps_id, + ) self.source.set_gramps_id(gramps_id) if is_merge_candidate: orig_source = self.db.get_source_from_handle(orig_handle) - self.info.add('merge-candidate', SOURCE_KEY, orig_source, - self.source) - else: # old style XML - self.inaugurate_id(attrs.get('id'), SOURCE_KEY, self.source) + self.info.add("merge-candidate", SOURCE_KEY, orig_source, self.source) + else: # old style XML + self.inaugurate_id(attrs.get("id"), SOURCE_KEY, self.source) self.source.private = bool(attrs.get("priv")) - self.source.change = int(attrs.get('change', self.change)) - self.info.add('new-object', SOURCE_KEY, self.source) + self.source.change = int(attrs.get("change", self.change)) + self.info.add("new-object", SOURCE_KEY, self.source) if self.default_tag: self.source.add_tag(self.default_tag.handle) return self.source @@ -2147,16 +2338,14 @@ class GrampsParser(UpdateCallback): Add a repository reference to the source currently processed. """ self.reporef = RepoRef() - if 'hlink' in attrs: - handle = self.inaugurate(attrs['hlink'], "repository", - Repository) - else: # old style XML - handle = self.inaugurate_id(attrs.get('ref'), REPOSITORY_KEY, - Repository) + if "hlink" in attrs: + handle = self.inaugurate(attrs["hlink"], "repository", Repository) + else: # old style XML + handle = self.inaugurate_id(attrs.get("ref"), REPOSITORY_KEY, Repository) self.reporef.ref = handle - self.reporef.call_number = attrs.get('callno', '') - if 'medium' in attrs: - self.reporef.media_type.set_from_xml_str(attrs['medium']) + self.reporef.call_number = attrs.get("callno", "") + if "medium" in attrs: + self.reporef.media_type.set_from_xml_str(attrs["medium"]) self.reporef.private = bool(attrs.get("priv")) # we count here on self.source being available # reporefs can only be found within source @@ -2167,14 +2356,12 @@ class GrampsParser(UpdateCallback): Add a media object reference to the object currently processed. """ self.objref = MediaRef() - if 'hlink' in attrs: - handle = self.inaugurate(attrs['hlink'], "media", - Media) - else: # old style XML - handle = self.inaugurate_id(attrs.get('ref'), MEDIA_KEY, - Media) + if "hlink" in attrs: + handle = self.inaugurate(attrs["hlink"], "media", Media) + else: # old style XML + handle = self.inaugurate_id(attrs.get("ref"), MEDIA_KEY, Media) self.objref.ref = handle - self.objref.private = bool(attrs.get('priv')) + self.objref.private = bool(attrs.get("priv")) if self.event: self.event.add_media_reference(self.objref) elif self.family: @@ -2189,10 +2376,12 @@ class GrampsParser(UpdateCallback): self.citation.add_media_reference(self.objref) def start_region(self, attrs): - rect = (int(attrs.get('corner1_x')), - int(attrs.get('corner1_y')), - int(attrs.get('corner2_x')), - int(attrs.get('corner2_y')) ) + rect = ( + int(attrs.get("corner1_x")), + int(attrs.get("corner1_y")), + int(attrs.get("corner2_x")), + int(attrs.get("corner2_y")), + ) self.objref.set_rectangle(rect) def start_media(self, attrs): @@ -2201,32 +2390,36 @@ class GrampsParser(UpdateCallback): id, privacy and changetime. """ self.object = Media() - if 'handle' in attrs: - orig_handle = attrs['handle'].replace('_', '') - is_merge_candidate = (self.replace_import_handle and - self.db.has_media_handle(orig_handle)) + if "handle" in attrs: + orig_handle = attrs["handle"].replace("_", "") + is_merge_candidate = ( + self.replace_import_handle and self.db.has_media_handle(orig_handle) + ) self.inaugurate(orig_handle, "media", self.object) - gramps_id = self.legalize_id(attrs.get('id'), MEDIA_KEY, - self.oidswap, self.db.oid2user_format, - self.db.find_next_media_gramps_id, - self.db.has_media_gramps_id) + gramps_id = self.legalize_id( + attrs.get("id"), + MEDIA_KEY, + self.oidswap, + self.db.oid2user_format, + self.db.find_next_media_gramps_id, + self.db.has_media_gramps_id, + ) self.object.set_gramps_id(gramps_id) if is_merge_candidate: orig_media = self.db.get_media_from_handle(orig_handle) - self.info.add('merge-candidate', MEDIA_KEY, orig_media, - self.object) + self.info.add("merge-candidate", MEDIA_KEY, orig_media, self.object) else: - self.inaugurate_id(attrs.get('id'), MEDIA_KEY, self.object) + self.inaugurate_id(attrs.get("id"), MEDIA_KEY, self.object) self.object.private = bool(attrs.get("priv")) - self.object.change = int(attrs.get('change', self.change)) - self.info.add('new-object', MEDIA_KEY, self.object) + self.object.change = int(attrs.get("change", self.change)) + self.info.add("new-object", MEDIA_KEY, self.object) # Gramps LEGACY: src, mime, and description attributes # now belong to the tag. Here we are supporting # the old format of - self.object.mime = attrs.get('mime', '') - self.object.desc = attrs.get('description', '') - src = attrs.get("src", '') + self.object.mime = attrs.get("mime", "") + self.object.desc = attrs.get("description", "") + src = attrs.get("src", "") if src: self.object.path = src if self.default_tag: @@ -2239,25 +2432,30 @@ class GrampsParser(UpdateCallback): id, privacy and changetime. """ self.repo = Repository() - if 'handle' in attrs: - orig_handle = attrs['handle'].replace('_', '') - is_merge_candidate = (self.replace_import_handle and - self.db.has_repository_handle(orig_handle)) + if "handle" in attrs: + orig_handle = attrs["handle"].replace("_", "") + is_merge_candidate = ( + self.replace_import_handle + and self.db.has_repository_handle(orig_handle) + ) self.inaugurate(orig_handle, "repository", self.repo) - gramps_id = self.legalize_id(attrs.get('id'), REPOSITORY_KEY, - self.ridswap, self.db.rid2user_format, - self.db.find_next_repository_gramps_id, - self.db.has_repository_gramps_id) + gramps_id = self.legalize_id( + attrs.get("id"), + REPOSITORY_KEY, + self.ridswap, + self.db.rid2user_format, + self.db.find_next_repository_gramps_id, + self.db.has_repository_gramps_id, + ) self.repo.set_gramps_id(gramps_id) if is_merge_candidate: orig_repo = self.db.get_repository_from_handle(orig_handle) - self.info.add('merge-candidate', REPOSITORY_KEY, orig_repo, - self.repo) - else: # old style XML - self.inaugurate_id(attrs.get('id'), REPOSITORY_KEY, self.repo) + self.info.add("merge-candidate", REPOSITORY_KEY, orig_repo, self.repo) + else: # old style XML + self.inaugurate_id(attrs.get("id"), REPOSITORY_KEY, self.repo) self.repo.private = bool(attrs.get("priv")) - self.repo.change = int(attrs.get('change', self.change)) - self.info.add('new-object', REPOSITORY_KEY, self.repo) + self.repo.change = int(attrs.get("change", self.change)) + self.info.add("new-object", REPOSITORY_KEY, self.repo) if self.default_tag: self.repo.add_tag(self.default_tag.handle) return self.repo @@ -2269,16 +2467,14 @@ class GrampsParser(UpdateCallback): self.update(self.p.CurrentLineNumber) def stop_media(self, *tag): - self.db.commit_media(self.object, self.trans, - self.object.get_change_time()) + self.db.commit_media(self.object, self.trans, self.object.get_change_time()) self.object = None def stop_objref(self, *tag): self.objref = None def stop_repo(self, *tag): - self.db.commit_repository(self.repo, self.trans, - self.repo.get_change_time()) + self.db.commit_repository(self.repo, self.trans, self.repo.get_change_time()) self.repo = None def stop_reporef(self, *tag): @@ -2305,9 +2501,9 @@ class GrampsParser(UpdateCallback): self.photo.add_attribute(attr) self.photo.set_mime_type(get_type(self.photo.get_path())) self.db.add_media(self.photo, self.trans) - #set correct change time + # set correct change time self.db.commit_media(self.photo, self.trans, self.change) - self.info.add('new-object', MEDIA_KEY, self.photo) + self.info.add("new-object", MEDIA_KEY, self.photo) if self.family: self.family.add_media_reference(self.pref) elif self.source: @@ -2341,8 +2537,8 @@ class GrampsParser(UpdateCallback): elif self.place_name: date_value = self.place_name.get_date_object() - start = attrs['start'].split('-') - stop = attrs['stop'].split('-') + start = attrs["start"].split("-") + stop = attrs["stop"].split("-") try: year = int(start[0]) @@ -2375,15 +2571,15 @@ class GrampsParser(UpdateCallback): rng_day = 0 if "cformat" in attrs: - cal = Date.calendar_names.index(attrs['cformat']) + cal = Date.calendar_names.index(attrs["cformat"]) else: cal = Date.CAL_GREGORIAN - if 'quality' in attrs: - val = attrs['quality'] - if val == 'estimated': + if "quality" in attrs: + val = attrs["quality"] + if val == "estimated": qual = Date.QUAL_ESTIMATED - elif val == 'calculated': + elif val == "calculated": qual = Date.QUAL_CALCULATED else: qual = Date.QUAL_NONE @@ -2391,29 +2587,34 @@ class GrampsParser(UpdateCallback): qual = Date.QUAL_NONE dualdated = False - if 'dualdated' in attrs: - val = attrs['dualdated'] + if "dualdated" in attrs: + val = attrs["dualdated"] if val == "1": dualdated = True newyear = Date.NEWYEAR_JAN1 - if 'newyear' in attrs: - newyear = attrs['newyear'] + if "newyear" in attrs: + newyear = attrs["newyear"] if newyear.isdigit(): newyear = int(newyear) else: newyear = Date.newyear_to_code(newyear) try: - date_value.set(qual, mode, cal, - (day, month, year, dualdated, - rng_day, rng_month, rng_year, dualdated), - newyear=newyear) + date_value.set( + qual, + mode, + cal, + (day, month, year, dualdated, rng_day, rng_month, rng_year, dualdated), + newyear=newyear, + ) except DateError as e: - self._set_date_to_xml_text(date_value, e, - xml_element_name = ("datespan" if mode == Date.MOD_SPAN - else "daterange"), - xml_attrs = attrs) + self._set_date_to_xml_text( + date_value, + e, + xml_element_name=("datespan" if mode == Date.MOD_SPAN else "daterange"), + xml_attrs=attrs, + ) def start_dateval(self, attrs): if self.citation: @@ -2434,13 +2635,13 @@ class GrampsParser(UpdateCallback): date_value = self.place_name.get_date_object() bce = 1 - val = attrs['val'] - if val[0] == '-': + val = attrs["val"] + if val[0] == "-": bce = -1 val = val[1:] - start = val.split('-') + start = val.split("-") try: - year = int(start[0])*bce + year = int(start[0]) * bce except: year = 0 @@ -2455,26 +2656,30 @@ class GrampsParser(UpdateCallback): day = 0 if "cformat" in attrs: - cal = Date.calendar_names.index(attrs['cformat']) + cal = Date.calendar_names.index(attrs["cformat"]) else: cal = Date.CAL_GREGORIAN - if 'type' in attrs: - val = attrs['type'] + if "type" in attrs: + val = attrs["type"] if val == "about": mod = Date.MOD_ABOUT elif val == "after": mod = Date.MOD_AFTER - else: + elif val == "before": mod = Date.MOD_BEFORE + elif val == "from": + mod = Date.MOD_FROM + else: + mod = Date.MOD_TO else: mod = Date.MOD_NONE - if 'quality' in attrs: - val = attrs['quality'] - if val == 'estimated': + if "quality" in attrs: + val = attrs["quality"] + if val == "estimated": qual = Date.QUAL_ESTIMATED - elif val == 'calculated': + elif val == "calculated": qual = Date.QUAL_CALCULATED else: qual = Date.QUAL_NONE @@ -2482,26 +2687,29 @@ class GrampsParser(UpdateCallback): qual = Date.QUAL_NONE dualdated = False - if 'dualdated' in attrs: - val = attrs['dualdated'] + if "dualdated" in attrs: + val = attrs["dualdated"] if val == "1": dualdated = True newyear = Date.NEWYEAR_JAN1 - if 'newyear' in attrs: - newyear = attrs['newyear'] + if "newyear" in attrs: + newyear = attrs["newyear"] if newyear.isdigit(): newyear = int(newyear) else: newyear = Date.newyear_to_code(newyear) try: - date_value.set(qual, mod, cal, (day, month, year, dualdated), - newyear=newyear) + date_value.set( + qual, mod, cal, (day, month, year, dualdated), newyear=newyear + ) except DateError as e: - self._set_date_to_xml_text(date_value, e, 'dateval', attrs) + self._set_date_to_xml_text(date_value, e, "dateval", attrs) - def _set_date_to_xml_text(self, date_value, date_error, xml_element_name, xml_attrs): + def _set_date_to_xml_text( + self, date_value, date_error, xml_element_name, xml_attrs + ): """ Common handling of invalid dates for the date... element handlers. @@ -2509,14 +2717,21 @@ class GrampsParser(UpdateCallback): with the problematic XML inside. """ xml = "<{element_name} {attrs}/>".format( - element_name = xml_element_name, - attrs = " ".join( - ['{}="{}"'.format(k,escape(v, entities={'"' : """})) - for k,v in xml_attrs.items()])) + element_name=xml_element_name, + attrs=" ".join( + [ + '{}="{}"'.format(k, escape(v, entities={'"': """})) + for k, v in xml_attrs.items() + ] + ), + ) # Translators: leave the {date} and {xml} untranslated in the format string, # but you may re-order them if needed. - LOG.warning(_("Invalid date {date} in XML {xml}, preserving XML as text" - ).format(date=date_error.date.__dict__, xml=xml)) + LOG.warning( + _("Invalid date {date} in XML {xml}, preserving XML as text").format( + date=date_error.date.__dict__, xml=xml + ) + ) date_value.set(modifier=Date.MOD_TEXTONLY, text=xml) def start_datestr(self, attrs): @@ -2537,7 +2752,7 @@ class GrampsParser(UpdateCallback): else: date_value = self.place_name.get_date_object() - date_value.set_as_text(attrs['val']) + date_value.set_as_text(attrs["val"]) def start_pos(self, attrs): self.person.position = (int(attrs["x"]), int(attrs["y"])) @@ -2571,9 +2786,9 @@ class GrampsParser(UpdateCallback): note.type.set(NoteType.EVENT) note.private = self.event.private self.db.add_note(note, self.trans) - #set correct change time + # set correct change time self.db.commit_note(note, self.trans, self.change) - self.info.add('new-object', NOTE_KEY, note) + self.info.add("new-object", NOTE_KEY, note) self.event.add_note(note.handle) self.in_witness = False @@ -2611,15 +2826,13 @@ class GrampsParser(UpdateCallback): self.placeobj.add_alternative_name(place_name) def stop_placeobj(self, *tag): - if self.placeobj.name.get_value() == '': + if self.placeobj.name.get_value() == "": self.placeobj.name.set_value(self.placeobj.title) - self.db.commit_place(self.placeobj, self.trans, - self.placeobj.get_change_time()) + self.db.commit_place(self.placeobj, self.trans, self.placeobj.get_change_time()) self.placeobj = None def stop_family(self, *tag): - self.db.commit_family(self.family, self.trans, - self.family.get_change_time()) + self.db.commit_family(self.family, self.trans, self.family.get_change_time()) self.family = None def stop_type(self, tag): @@ -2654,39 +2867,42 @@ class GrampsParser(UpdateCallback): ref.ref = self.event.handle ref.private = self.event.private ref.role.set(EventRoleType.PRIMARY) - if (self.event.type == EventType.BIRTH) \ - and (self.person.get_birth_ref() is None): + if (self.event.type == EventType.BIRTH) and ( + self.person.get_birth_ref() is None + ): self.person.set_birth_ref(ref) - elif (self.event.type == EventType.DEATH) \ - and (self.person.get_death_ref() is None): + elif (self.event.type == EventType.DEATH) and ( + self.person.get_death_ref() is None + ): self.person.set_death_ref(ref) else: self.person.add_event_ref(ref) - if self.event.get_description() == "" and \ - self.event.get_type() != EventType.CUSTOM: + if ( + self.event.get_description() == "" + and self.event.get_type() != EventType.CUSTOM + ): if self.family: text = EVENT_FAMILY_STR % { - 'event_name' : str(self.event.get_type()), - 'family' : family_name(self.family, self.db), - } + "event_name": str(self.event.get_type()), + "family": family_name(self.family, self.db), + } elif self.person: text = EVENT_PERSON_STR % { - 'event_name' : str(self.event.get_type()), - 'person' : name_displayer.display(self.person), - } + "event_name": str(self.event.get_type()), + "person": name_displayer.display(self.person), + } else: - text = '' + text = "" self.event.set_description(text) - self.db.commit_event(self.event, self.trans, - self.event.get_change_time()) + self.db.commit_event(self.event, self.trans, self.event.get_change_time()) self.event = None def stop_name(self, attrs): if self.person: self.stop_person_name(attrs) - if self.placeobj: # XML 1.7.0 + if self.placeobj: # XML 1.7.0 self.stop_place_name(attrs) def stop_place_name(self, tag): @@ -2701,12 +2917,12 @@ class GrampsParser(UpdateCallback): note.type.set(NoteType.EVENT) note.private = self.event.private self.db.add_note(note, self.trans) - #set correct change time + # set correct change time self.db.commit_note(note, self.trans, self.change) - self.info.add('new-object', NOTE_KEY, note) + self.info.add("new-object", NOTE_KEY, note) self.event.add_note(note.handle) else: - #first correct old xml that has no nametype set + # first correct old xml that has no nametype set if self.alt_name: # alternate name or former aka tag if self.name.get_type() == "": @@ -2715,21 +2931,21 @@ class GrampsParser(UpdateCallback): if self.name.get_type() == "": self.name.set_type(NameType.BIRTH) - #same logic as bsddb upgrade for xml < 1.4.0 which will - #have a surnamepat and/or surname. From 1.4.0 surname has been - #added to name in self.stop_surname + # same logic as bsddb upgrade for xml < 1.4.0 which will + # have a surnamepat and/or surname. From 1.4.0 surname has been + # added to name in self.stop_surname if not self.surnamepat: - #no patronymic, only add surname if present + # no patronymic, only add surname if present if self.surname: self.name.add_surname(self.surname) self.name.set_primary_surname(0) else: - #a patronymic, if no surname, a single surname + # a patronymic, if no surname, a single surname if not self.surname: self.name.add_surname(self.surnamepat) self.name.set_primary_surname(0) else: - #two surnames, first patronymic, then surname which is primary + # two surnames, first patronymic, then surname which is primary self.name.add_surname(self.surnamepat) self.name.add_surname(self.surname) self.name.set_primary_surname(1) @@ -2745,17 +2961,17 @@ class GrampsParser(UpdateCallback): if self.name.get_type() == "": self.name.set_type(NameType.AKA) if not self.surnamepat: - #no patronymic, only add surname if present + # no patronymic, only add surname if present if self.surname: self.name.add_surname(self.surname) self.name.set_primary_surname(0) else: - #a patronymic, if no surname, a single surname + # a patronymic, if no surname, a single surname if not self.surname: self.name.add_surname(self.surnamepat) self.name.set_primary_surname(0) else: - #two surnames, first patronymic, then surname which is primary + # two surnames, first patronymic, then surname which is primary self.name.add_surname(self.surnamepat) self.name.add_surname(self.surname) self.name.set_primary_surname(1) @@ -2782,8 +2998,8 @@ class GrampsParser(UpdateCallback): def stop_place(self, tag): """end of a reference to place, should do nothing ... - Note, if we encounter blabla this method is called - with tag='blabla + Note, if we encounter blabla this method is called + with tag='blabla """ ##place = None ##handle = None @@ -2828,8 +3044,7 @@ class GrampsParser(UpdateCallback): self.family = None def stop_person(self, *tag): - self.db.commit_person(self.person, self.trans, - self.person.get_change_time()) + self.db.commit_person(self.person, self.trans, self.person.get_change_time()) self.person = None def stop_description(self, tag): @@ -2845,13 +3060,13 @@ class GrampsParser(UpdateCallback): def stop_gender(self, tag): t = tag if t == "M": - self.person.set_gender (Person.MALE) + self.person.set_gender(Person.MALE) elif t == "F": self.person.set_gender (Person.FEMALE) elif t == "X": self.person.set_gender (Person.OTHER) else: - self.person.set_gender (Person.UNKNOWN) + self.person.set_gender(Person.UNKNOWN) def stop_stitle(self, tag): self.source.title = tag @@ -2859,19 +3074,20 @@ class GrampsParser(UpdateCallback): def stop_sourceref(self, *tag): # if we are in an old style sourceref we need to commit the citation if self.in_old_sourceref: - self.db.commit_citation(self.citation, self.trans, - self.citation.get_change_time()) + self.db.commit_citation( + self.citation, self.trans, self.citation.get_change_time() + ) self.citation = None self.in_old_sourceref = False def stop_source(self, *tag): - self.db.commit_source(self.source, self.trans, - self.source.get_change_time()) + self.db.commit_source(self.source, self.trans, self.source.get_change_time()) self.source = None def stop_citation(self, *tag): - self.db.commit_citation(self.citation, self.trans, - self.citation.get_change_time()) + self.db.commit_citation( + self.citation, self.trans, self.citation.get_change_time() + ) self.citation = None def stop_sauthor(self, tag): @@ -2936,9 +3152,9 @@ class GrampsParser(UpdateCallback): note.set(text) note.type.set(NoteType.SOURCE_TEXT) self.db.add_note(note, self.trans) - #set correct change time + # set correct change time self.db.commit_note(note, self.trans, self.change) - self.info.add('new-object', NOTE_KEY, note) + self.info.add("new-object", NOTE_KEY, note) self.citation.add_note(note.handle) def stop_scomments(self, tag): @@ -2953,16 +3169,16 @@ class GrampsParser(UpdateCallback): note.set(text) note.type.set(NoteType.CITATION) self.db.add_note(note, self.trans) - #set correct change time + # set correct change time self.db.commit_note(note, self.trans, self.change) - self.info.add('new-object', NOTE_KEY, note) + self.info.add("new-object", NOTE_KEY, note) self.citation.add_note(note.handle) def stop_last(self, tag): if self.surname: self.surname.set_surname(tag) if not tag.strip() and not self.surname.get_prefix().strip(): - #consider empty surname as no surname + # consider empty surname as no surname self.surname = None def stop_surname(self, tag): @@ -2975,7 +3191,7 @@ class GrampsParser(UpdateCallback): self.surname = None def stop_group(self, tag): - """ group name of a name""" + """group name of a name""" if self.name: self.name.set_group_as(tag) @@ -2995,7 +3211,7 @@ class GrampsParser(UpdateCallback): def stop_nick(self, tag): """in < 1.3.0 nick is on person and mapped to attribute - from 1.4.0 it is a name element + from 1.4.0 it is a name element """ if self.name: self.name.set_nick_name(tag) @@ -3133,7 +3349,7 @@ class GrampsParser(UpdateCallback): def endElement(self, tag): if self.func: - self.func(''.join(self.tlist)) + self.func("".join(self.tlist)) self.func_index -= 1 self.func, self.tlist = self.func_list[self.func_index] @@ -3147,10 +3363,10 @@ class GrampsParser(UpdateCallback): Old and new markers: complete=1 and marker=word """ - if attrs.get('complete'): # this is only true for complete=1 - tag_name = 'Complete' + if attrs.get("complete"): # this is only true for complete=1 + tag_name = "Complete" else: - tag_name = attrs.get('marker') + tag_name = attrs.get("marker") if tag_name is not None: tag_name = _(tag_name) @@ -3167,8 +3383,11 @@ class GrampsParser(UpdateCallback): def fix_not_instantiated(self): uninstantiated = [] for orig_handle in self.import_handles.keys(): - tglist = [target for target in self.import_handles[orig_handle].keys() if - not self.import_handles[orig_handle][target][INSTANTIATED]] + tglist = [ + target + for target in self.import_handles[orig_handle].keys() + if not self.import_handles[orig_handle][target][INSTANTIATED] + ] for target in tglist: uninstantiated += [(orig_handle, target)] if uninstantiated: @@ -3176,33 +3395,54 @@ class GrampsParser(UpdateCallback): self.db.commit_note(expl_note, self.trans, time.time()) self.info.expl_note = expl_note.get_gramps_id() for orig_handle, target in uninstantiated: - class_arg = {'handle': orig_handle, 'id': None, 'priv': False} - if target == 'family': - objs = make_unknown(class_arg, expl_note.handle, - self.func_map[target][0], self.func_map[target][1], - self.trans, db=self.db) - elif target == 'citation': - objs = make_unknown(class_arg, expl_note.handle, - self.func_map[target][0], self.func_map[target][1], - self.trans, - source_class_func=self.func_map['source'][0], - source_commit_func=self.func_map['source'][1], - source_class_arg={'handle':create_id(), 'id':None, 'priv':False}) - elif target == 'note': - objs = make_unknown(class_arg, expl_note.handle, - self.func_map[target][0], self.stop_note_asothers, - self.trans) + class_arg = {"handle": orig_handle, "id": None, "priv": False} + if target == "family": + objs = make_unknown( + class_arg, + expl_note.handle, + self.func_map[target][0], + self.func_map[target][1], + self.trans, + db=self.db, + ) + elif target == "citation": + objs = make_unknown( + class_arg, + expl_note.handle, + self.func_map[target][0], + self.func_map[target][1], + self.trans, + source_class_func=self.func_map["source"][0], + source_commit_func=self.func_map["source"][1], + source_class_arg={ + "handle": create_id(), + "id": None, + "priv": False, + }, + ) + elif target == "note": + objs = make_unknown( + class_arg, + expl_note.handle, + self.func_map[target][0], + self.stop_note_asothers, + self.trans, + ) else: - if target == 'place': - target = 'placeobj' - elif target == 'media': - target = 'object' - objs = make_unknown(class_arg, expl_note.handle, - self.func_map[target][0], self.func_map[target][1], - self.trans) + if target == "place": + target = "placeobj" + elif target == "media": + target = "object" + objs = make_unknown( + class_arg, + expl_note.handle, + self.func_map[target][0], + self.func_map[target][1], + self.trans, + ) for obj in objs: key = CLASS_TO_KEY_MAP[obj.__class__.__name__] - self.info.add('unknown-object', key, obj) + self.info.add("unknown-object", key, obj) def fix_families(self): # Fix any imported families where there is a link from the family to an @@ -3210,7 +3450,7 @@ class GrampsParser(UpdateCallback): # family. for orig_handle in list(self.import_handles.keys()): for target in list(self.import_handles[orig_handle].keys()): - if target == 'family': + if target == "family": family_handle = self.import_handles[orig_handle][target][HANDLE] family = self.db.get_family_from_handle(family_handle) father_handle = family.get_father_handle() @@ -3218,64 +3458,84 @@ class GrampsParser(UpdateCallback): if father_handle: father = self.db.get_person_from_handle(father_handle) - if father and \ - family_handle not in father.get_family_handle_list(): + if ( + father + and family_handle not in father.get_family_handle_list() + ): father.add_family_handle(family_handle) self.db.commit_person(father, self.trans) - txt = _("Error: family '%(family)s'" - " father '%(father)s'" - " does not refer" - " back to the family." - " Reference added." % - {'family' : family.gramps_id, - 'father' : father.gramps_id}) - self.info.add('unlinked-family', txt, None) + txt = _( + "Error: family '%(family)s'" + " father '%(father)s'" + " does not refer" + " back to the family." + " Reference added." + % { + "family": family.gramps_id, + "father": father.gramps_id, + } + ) + self.info.add("unlinked-family", txt, None) LOG.warning(txt) if mother_handle: mother = self.db.get_person_from_handle(mother_handle) - if mother and \ - family_handle not in mother.get_family_handle_list(): + if ( + mother + and family_handle not in mother.get_family_handle_list() + ): mother.add_family_handle(family_handle) self.db.commit_person(mother, self.trans) - txt = _("Error: family '%(family)s'" - " mother '%(mother)s'" - " does not refer" - " back to the family." - " Reference added." % - {'family' : family.gramps_id, - 'mother' : mother.gramps_id}) - self.info.add('unlinked-family', txt, None) + txt = _( + "Error: family '%(family)s'" + " mother '%(mother)s'" + " does not refer" + " back to the family." + " Reference added." + % { + "family": family.gramps_id, + "mother": mother.gramps_id, + } + ) + self.info.add("unlinked-family", txt, None) LOG.warning(txt) 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: - if family_handle not in \ - child.get_parent_family_handle_list(): + if ( + family_handle + not in child.get_parent_family_handle_list() + ): # The referenced child has no reference to the # family. There was a link from the FAM record # to the child, but no FAMC link from the child # to the FAM. child.add_parent_family_handle(family_handle) self.db.commit_person(child, self.trans) - txt = _("Error: family '%(family)s'" - " child '%(child)s'" - " does not " - "refer back to the family. " - "Reference added." % - {'family' : family.gramps_id, - 'child' : child.gramps_id}) - self.info.add('unlinked-family', txt, None) + txt = _( + "Error: family '%(family)s'" + " child '%(child)s'" + " does not " + "refer back to the family. " + "Reference added." + % { + "family": family.gramps_id, + "child": child.gramps_id, + } + ) + self.info.add("unlinked-family", txt, None) LOG.warning(txt) + def append_value(orig, val): if orig: return "%s, %s" % (orig, val) else: return val + def build_place_title(loc): "Builds a title from a location" value = "" @@ -3290,4 +3550,3 @@ def build_place_title(loc): if loc.country: value = append_value(value, loc.country) return value - diff --git a/gramps/plugins/lib/libgedcom.py b/gramps/plugins/lib/libgedcom.py index eda0e6ac5..286f37836 100644 --- a/gramps/plugins/lib/libgedcom.py +++ b/gramps/plugins/lib/libgedcom.py @@ -83,14 +83,15 @@ all lines until the next level 2 token is found (in this case, skipping the "3 NOTE DATA" line. """ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # standard python modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- import os import re import time + # from xml.parsers.expat import ParserCreate from collections import defaultdict, OrderedDict import string @@ -98,30 +99,64 @@ import mimetypes from io import StringIO, TextIOWrapper from urllib.parse import urlparse -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ # # Set up logging # -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ import logging + LOG = logging.getLogger(".libgedcom") -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gramps modules # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- from gramps.gen.const import GRAMPS_LOCALE as glocale + _ = glocale.translation.gettext from gramps.gen.errors import GedcomError from gramps.gen.lib import ( - Address, Attribute, AttributeType, ChildRef, - ChildRefType, Citation, Date, Event, EventRef, EventRoleType, - EventType, Family, FamilyRelType, LdsOrd, Location, Media, - MediaRef, Name, NameType, Note, NoteType, Person, PersonRef, Place, - RepoRef, Repository, RepositoryType, Researcher, - Source, SourceMediaType, SrcAttribute, - Surname, Tag, Url, UrlType, PlaceType, PlaceRef, PlaceName) + Address, + Attribute, + AttributeType, + ChildRef, + ChildRefType, + Citation, + Date, + Event, + EventRef, + EventRoleType, + EventType, + Family, + FamilyRelType, + LdsOrd, + Location, + Media, + MediaRef, + Name, + NameType, + Note, + NoteType, + Person, + PersonRef, + Place, + RepoRef, + Repository, + RepositoryType, + Researcher, + Source, + SourceMediaType, + SrcAttribute, + Surname, + Tag, + Url, + UrlType, + PlaceType, + PlaceRef, + PlaceName, +) from gramps.gen.db import DbTxn from gramps.gen.updatecallback import UpdateCallback from gramps.gen.utils.file import media_path @@ -131,17 +166,17 @@ from gramps.gen.utils.unknown import make_unknown, create_explanation_note from gramps.gen.datehandler._dateparser import DateParser from gramps.gen.db.dbconst import EVENT_KEY from gramps.gen.lib.const import IDENTICAL -from gramps.gen.lib import (StyledText, StyledTextTag, StyledTextTagType) +from gramps.gen.lib import StyledText, StyledTextTag, StyledTextTagType from gramps.gen.lib.urlbase import UrlBase from gramps.plugins.lib.libplaceimport import PlaceImport from gramps.gen.display.place import displayer as _pd from gramps.gen.utils.grampslocale import GrampsLocale -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # constants # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- TOKEN_UNKNOWN = 0 TOKEN_ABBR = 1 TOKEN_ADDR = 2 @@ -524,74 +559,73 @@ TYPE_BIRTH = ChildRefType() TYPE_ADOPT = ChildRefType(ChildRefType.ADOPTED) TYPE_FOSTER = ChildRefType(ChildRefType.FOSTER) -RELATION_TYPES = ( - ChildRefType.BIRTH, - ChildRefType.UNKNOWN, - ChildRefType.NONE) +RELATION_TYPES = (ChildRefType.BIRTH, ChildRefType.UNKNOWN, ChildRefType.NONE) PEDIGREE_TYPES = { - 'birth' : ChildRefType(), - 'natural': ChildRefType(), - 'step' : ChildRefType(ChildRefType.STEPCHILD), - 'adopted': TYPE_ADOPT, - 'foster' : TYPE_FOSTER, } + "birth": ChildRefType(), + "natural": ChildRefType(), + "step": ChildRefType(ChildRefType.STEPCHILD), + "adopted": TYPE_ADOPT, + "foster": TYPE_FOSTER, +} FTW_BAD_PLACE = [ EventType.OCCUPATION, EventType.RELIGION, - EventType.DEGREE, ] + EventType.DEGREE, +] MEDIA_MAP = { - 'audio' : SourceMediaType.AUDIO, - 'book' : SourceMediaType.BOOK, - 'card' : SourceMediaType.CARD, - 'electronic' : SourceMediaType.ELECTRONIC, - 'fiche' : SourceMediaType.FICHE, - 'microfiche' : SourceMediaType.FICHE, - 'microfilm' : SourceMediaType.FICHE, - 'film' : SourceMediaType.FILM, - 'magazine' : SourceMediaType.MAGAZINE, - 'manuscript' : SourceMediaType.MANUSCRIPT, - 'map' : SourceMediaType.MAP, - 'newspaper' : SourceMediaType.NEWSPAPER, - 'photo' : SourceMediaType.PHOTO, - 'tombstone' : SourceMediaType.TOMBSTONE, - 'grave' : SourceMediaType.TOMBSTONE, - 'video' : SourceMediaType.VIDEO, + "audio": SourceMediaType.AUDIO, + "book": SourceMediaType.BOOK, + "card": SourceMediaType.CARD, + "electronic": SourceMediaType.ELECTRONIC, + "fiche": SourceMediaType.FICHE, + "microfiche": SourceMediaType.FICHE, + "microfilm": SourceMediaType.FICHE, + "film": SourceMediaType.FILM, + "magazine": SourceMediaType.MAGAZINE, + "manuscript": SourceMediaType.MANUSCRIPT, + "map": SourceMediaType.MAP, + "newspaper": SourceMediaType.NEWSPAPER, + "photo": SourceMediaType.PHOTO, + "tombstone": SourceMediaType.TOMBSTONE, + "grave": SourceMediaType.TOMBSTONE, + "video": SourceMediaType.VIDEO, } OBJ_NOTETYPE = { - "Attribute" : NoteType.ATTRIBUTE, - "Address" : NoteType.ADDRESS, - "Citation" : NoteType.CITATION, - "Event" : NoteType.EVENT, - "Family" : NoteType.FAMILY, - "LdsOrd" : NoteType.LDS, - "Media" : NoteType.MEDIA, - "Name" : NoteType.GENERAL, - "Place" : NoteType.PLACE, - "Person" : NoteType.PERSON, - "Repository" : NoteType.REPO, - "RepoRef" : NoteType.REPOREF, - "Source" : NoteType.SOURCE, - "PersonRef" : NoteType.ASSOCIATION, + "Attribute": NoteType.ATTRIBUTE, + "Address": NoteType.ADDRESS, + "Citation": NoteType.CITATION, + "Event": NoteType.EVENT, + "Family": NoteType.FAMILY, + "LdsOrd": NoteType.LDS, + "Media": NoteType.MEDIA, + "Name": NoteType.GENERAL, + "Place": NoteType.PLACE, + "Person": NoteType.PERSON, + "Repository": NoteType.REPO, + "RepoRef": NoteType.REPOREF, + "Source": NoteType.SOURCE, + "PersonRef": NoteType.ASSOCIATION, } -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Integer to GEDCOM tag mappings for constants # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- CALENDAR_MAP_GEDCOM2XML = { - "FRENCH R" : Date.CAL_FRENCH, - "JULIAN" : Date.CAL_JULIAN, - "HEBREW" : Date.CAL_HEBREW, + "FRENCH R": Date.CAL_FRENCH, + "JULIAN": Date.CAL_JULIAN, + "HEBREW": Date.CAL_HEBREW, } QUALITY_MAP = { - 'CAL' : Date.QUAL_CALCULATED, - 'INT' : Date.QUAL_CALCULATED, - 'EST' : Date.QUAL_ESTIMATED, + "CAL": Date.QUAL_CALCULATED, + "INT": Date.QUAL_CALCULATED, + "EST": Date.QUAL_ESTIMATED, } SEX_MAP = { @@ -601,85 +635,85 @@ SEX_MAP = { } FAMILYCONSTANTEVENTS = { - EventType.ANNULMENT : "ANUL", - EventType.DIV_FILING : "DIVF", - EventType.DIVORCE : "DIV", - EventType.CENSUS : "CENS", - EventType.ENGAGEMENT : "ENGA", - EventType.MARR_BANNS : "MARB", - EventType.MARR_CONTR : "MARC", - EventType.MARR_LIC : "MARL", - EventType.MARR_SETTL : "MARS", - EventType.MARRIAGE : "MARR" + EventType.ANNULMENT: "ANUL", + EventType.DIV_FILING: "DIVF", + EventType.DIVORCE: "DIV", + EventType.CENSUS: "CENS", + EventType.ENGAGEMENT: "ENGA", + EventType.MARR_BANNS: "MARB", + EventType.MARR_CONTR: "MARC", + EventType.MARR_LIC: "MARL", + EventType.MARR_SETTL: "MARS", + EventType.MARRIAGE: "MARR", } PERSONALCONSTANTEVENTS = { - EventType.ADOPT : "ADOP", - EventType.ADULT_CHRISTEN : "CHRA", - EventType.BIRTH : "BIRT", - EventType.DEATH : "DEAT", - EventType.BAPTISM : "BAPM", - EventType.BAR_MITZVAH : "BARM", - EventType.BAS_MITZVAH : "BASM", - EventType.BLESS : "BLES", - EventType.BURIAL : "BURI", + EventType.ADOPT: "ADOP", + EventType.ADULT_CHRISTEN: "CHRA", + EventType.BIRTH: "BIRT", + EventType.DEATH: "DEAT", + EventType.BAPTISM: "BAPM", + EventType.BAR_MITZVAH: "BARM", + EventType.BAS_MITZVAH: "BASM", + EventType.BLESS: "BLES", + EventType.BURIAL: "BURI", # EventType.CAUSE_DEATH : "CAUS", Not legal Gedcom since v5.0 - EventType.ORDINATION : "ORDN", - EventType.CENSUS : "CENS", - EventType.CHRISTEN : "CHR", - EventType.CONFIRMATION : "CONF", - EventType.CREMATION : "CREM", - EventType.DEGREE : "_DEG", - EventType.DIV_FILING : "DIVF", - EventType.EDUCATION : "EDUC", - EventType.ELECTED : "_ELEC", # FTM custom tag - EventType.EMIGRATION : "EMIG", - EventType.FIRST_COMMUN : "FCOM", - EventType.GRADUATION : "GRAD", - EventType.MED_INFO : "_MDCL", - EventType.MILITARY_SERV : "_MILT", - EventType.NATURALIZATION : "NATU", - EventType.NOB_TITLE : "TITL", - EventType.NUM_MARRIAGES : "NMR", - EventType.IMMIGRATION : "IMMI", - EventType.OCCUPATION : "OCCU", - EventType.PROBATE : "PROB", - EventType.PROPERTY : "PROP", - EventType.RELIGION : "RELI", - EventType.RESIDENCE : "RESI", - EventType.RETIREMENT : "RETI", - EventType.WILL : "WILL", + EventType.ORDINATION: "ORDN", + EventType.CENSUS: "CENS", + EventType.CHRISTEN: "CHR", + EventType.CONFIRMATION: "CONF", + EventType.CREMATION: "CREM", + EventType.DEGREE: "_DEG", + EventType.DIV_FILING: "DIVF", + EventType.EDUCATION: "EDUC", + EventType.ELECTED: "_ELEC", # FTM custom tag + EventType.EMIGRATION: "EMIG", + EventType.FIRST_COMMUN: "FCOM", + EventType.GRADUATION: "GRAD", + EventType.MED_INFO: "_MDCL", + EventType.MILITARY_SERV: "_MILT", + EventType.NATURALIZATION: "NATU", + EventType.NOB_TITLE: "TITL", + EventType.NUM_MARRIAGES: "NMR", + EventType.IMMIGRATION: "IMMI", + EventType.OCCUPATION: "OCCU", + EventType.PROBATE: "PROB", + EventType.PROPERTY: "PROP", + EventType.RELIGION: "RELI", + EventType.RESIDENCE: "RESI", + EventType.RETIREMENT: "RETI", + EventType.WILL: "WILL", } FAMILYCONSTANTATTRIBUTES = { - AttributeType.NUM_CHILD : "NCHI", + AttributeType.NUM_CHILD: "NCHI", } PERSONALCONSTANTATTRIBUTES = { - AttributeType.CASTE : "CAST", - AttributeType.DESCRIPTION : "DSCR", - AttributeType.ID : "IDNO", - AttributeType.NATIONAL : "NATI", - AttributeType.NUM_CHILD : "NCHI", - AttributeType.SSN : "SSN", + AttributeType.CASTE: "CAST", + AttributeType.DESCRIPTION: "DSCR", + AttributeType.ID: "IDNO", + AttributeType.NATIONAL: "NATI", + AttributeType.NUM_CHILD: "NCHI", + AttributeType.SSN: "SSN", } -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Gedcom to int constants # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- LDS_STATUS = { - "BIC" : LdsOrd.STATUS_BIC, - "CANCELED" : LdsOrd.STATUS_CANCELED, - "CHILD" : LdsOrd.STATUS_CHILD, - "CLEARED" : LdsOrd.STATUS_CLEARED, + "BIC": LdsOrd.STATUS_BIC, + "CANCELED": LdsOrd.STATUS_CANCELED, + "CHILD": LdsOrd.STATUS_CHILD, + "CLEARED": LdsOrd.STATUS_CLEARED, "COMPLETED": LdsOrd.STATUS_COMPLETED, - "DNS" : LdsOrd.STATUS_DNS, - "INFANT" : LdsOrd.STATUS_INFANT, - "PRE-1970" : LdsOrd.STATUS_PRE_1970, + "DNS": LdsOrd.STATUS_DNS, + "INFANT": LdsOrd.STATUS_INFANT, + "PRE-1970": LdsOrd.STATUS_PRE_1970, "QUALIFIED": LdsOrd.STATUS_QUALIFIED, - "DNS/CAN" : LdsOrd.STATUS_DNS_CAN, + "DNS/CAN": LdsOrd.STATUS_DNS_CAN, "STILLBORN": LdsOrd.STATUS_STILLBORN, "SUBMITTED": LdsOrd.STATUS_SUBMITTED, "UNCLEARED": LdsOrd.STATUS_UNCLEARED, @@ -699,39 +733,38 @@ LDS_STATUS = { # # ------------------------------------------------------------------------- CUSTOMEVENTTAGS = { - "_CIRC" : _("Circumcision"), - "_COML" : _("Common Law Marriage"), - "_DEST" : _("Destination"), - "_DNA" : _("DNA"), - "_DCAUSE" : _("Cause of Death"), - "_EMPLOY" : _("Employment"), - "_EXCM" : _("Excommunication"), - "_EYC" : _("Eye Color"), - "_FUN" : _("Funeral"), - "_HEIG" : _("Height"), - "_INIT" : _("Initiatory (LDS)"), - "_MILTID" : _("Military ID"), - "_MISN" : _("Mission (LDS)"), - "_NAMS" : _("Namesake"), - "_ORDI" : _("Ordinance"), - "_ORIG" : _("Origin"), - "_SEPR" : _("Separation"), # Applies to Families - "_WEIG" : _("Weight"), + "_CIRC": _("Circumcision"), + "_COML": _("Common Law Marriage"), + "_DEST": _("Destination"), + "_DNA": _("DNA"), + "_DCAUSE": _("Cause of Death"), + "_EMPLOY": _("Employment"), + "_EXCM": _("Excommunication"), + "_EYC": _("Eye Color"), + "_FUN": _("Funeral"), + "_HEIG": _("Height"), + "_INIT": _("Initiatory (LDS)"), + "_MILTID": _("Military ID"), + "_MISN": _("Mission (LDS)"), + "_NAMS": _("Namesake"), + "_ORDI": _("Ordinance"), + "_ORIG": _("Origin"), + "_SEPR": _("Separation"), # Applies to Families + "_WEIG": _("Weight"), } # table for skipping illegal control chars in GEDCOM import # Only 09, 0A, 0D are allowed. -STRIP_DICT = dict.fromkeys(list(range(9)) + list(range(11, 13)) + - list(range(14, 32))) +STRIP_DICT = dict.fromkeys(list(range(9)) + list(range(11, 13)) + list(range(14, 32))) # The C1 Control characters are not treated in Latin-1 (ISO-8859-1) as # undefined, but if they have been used, the file is probably supposed to be # cp1252 DEL_AND_C1 = dict.fromkeys(list(range(0x7F, 0x9F))) -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # GEDCOM events to Gramps events conversion # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- GED_TO_GRAMPS_EVENT = {} for __val, __key in PERSONALCONSTANTEVENTS.items(): if __key != "": @@ -746,70 +779,109 @@ for __val, __key in PERSONALCONSTANTATTRIBUTES.items(): if __key != "": GED_TO_GRAMPS_ATTR[__key] = __val -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # GEDCOM Date Constants # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- HMONTH = [ - "", "TSH", "CSH", "KSL", "TVT", "SHV", "ADR", - "ADS", "NSN", "IYR", "SVN", "TMZ", "AAV", "ELL"] + "", + "TSH", + "CSH", + "KSL", + "TVT", + "SHV", + "ADR", + "ADS", + "NSN", + "IYR", + "SVN", + "TMZ", + "AAV", + "ELL", +] FMONTH = [ - "", "VEND", "BRUM", "FRIM", "NIVO", "PLUV", "VENT", - "GERM", "FLOR", "PRAI", "MESS", "THER", "FRUC", "COMP"] + "", + "VEND", + "BRUM", + "FRIM", + "NIVO", + "PLUV", + "VENT", + "GERM", + "FLOR", + "PRAI", + "MESS", + "THER", + "FRUC", + "COMP", +] MONTH = [ - "", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", - "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"] + "", + "JAN", + "FEB", + "MAR", + "APR", + "MAY", + "JUN", + "JUL", + "AUG", + "SEP", + "OCT", + "NOV", + "DEC", +] CALENDAR_MAP = { - Date.CAL_HEBREW : (HMONTH, '@#DHEBREW@'), - Date.CAL_FRENCH : (FMONTH, '@#DFRENCH R@'), - Date.CAL_JULIAN : (MONTH, '@#DJULIAN@'), - Date.CAL_SWEDISH : (MONTH, '@#DUNKNOWN@'), + Date.CAL_HEBREW: (HMONTH, "@#DHEBREW@"), + Date.CAL_FRENCH: (FMONTH, "@#DFRENCH R@"), + Date.CAL_JULIAN: (MONTH, "@#DJULIAN@"), + Date.CAL_SWEDISH: (MONTH, "@#DUNKNOWN@"), } CALENDAR_MAP_PARSESTRING = { - Date.CAL_HEBREW : ' (h)', - Date.CAL_FRENCH : ' (f)', - Date.CAL_JULIAN : ' (j)', - Date.CAL_SWEDISH : ' (s)', + Date.CAL_HEBREW: " (h)", + Date.CAL_FRENCH: " (f)", + Date.CAL_JULIAN: " (j)", + Date.CAL_SWEDISH: " (s)", } -#how wrong calendar use is shown +# how wrong calendar use is shown CALENDAR_MAP_WRONGSTRING = { - Date.CAL_HEBREW : ' ', - Date.CAL_FRENCH : ' ', - Date.CAL_JULIAN : ' ', - Date.CAL_SWEDISH : ' ', + Date.CAL_HEBREW: " ", + Date.CAL_FRENCH: " ", + Date.CAL_JULIAN: " ", + Date.CAL_SWEDISH: " ", } DATE_MODIFIER = { - Date.MOD_ABOUT : "ABT", - Date.MOD_BEFORE : "BEF", - Date.MOD_AFTER : "AFT", - #Date.MOD_INTERPRETED : "INT", + Date.MOD_ABOUT: "ABT", + Date.MOD_BEFORE: "BEF", + Date.MOD_AFTER: "AFT", + Date.MOD_FROM: "FROM", + Date.MOD_TO: "TO", + # Date.MOD_INTERPRETED : "INT", } DATE_QUALITY = { - Date.QUAL_CALCULATED : "CAL", - Date.QUAL_ESTIMATED : "EST", + Date.QUAL_CALCULATED: "CAL", + Date.QUAL_ESTIMATED: "EST", } -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # regular expressions # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- NOTE_RE = re.compile(r"\s*\d+\s+\@(\S+)\@\s+NOTE(.*)$") CONT_RE = re.compile(r"\s*\d+\s+CONT\s?(.*)$") CONC_RE = re.compile(r"\s*\d+\s+CONC\s?(.*)$") PERSON_RE = re.compile(r"\s*\d+\s+\@(\S+)\@\s+INDI(.*)$") MOD = re.compile(r"\s*(INT|EST|CAL)\s+(.*)$") -CAL = re.compile(r"\s*(ABT|BEF|AFT)?\s*@#D?([^@]+)@\s*(.*)$") -RANGE = re.compile( - r"\s*BET\s+@#D?([^@]+)@\s*(.*)\s+AND\s+@#D?([^@]+)@\s*(.*)$") +CAL = re.compile(r"\s*(ABT|BEF|AFT|FROM|TO)?\s*@#D?([^@]+)@\s*(.*)$") +RANGE = re.compile(r"\s*BET\s+@#D?([^@]+)@\s*(.*)\s+AND\s+@#D?([^@]+)@\s*(.*)$") RANGE1 = re.compile(r"\s*BET\s+\s*(.*)\s+AND\s+@#D?([^@]+)@\s*(.*)$") RANGE2 = re.compile(r"\s*BET\s+@#D?([^@]+)@\s*(.*)\s+AND\s+\s*(.*)$") SPAN = re.compile(r"\s*FROM\s+@#D?([^@]+)@\s*(.*)\s+TO\s+@#D?([^@]+)@\s*(.*)$") @@ -819,32 +891,44 @@ NAME_RE = re.compile(r"/?([^/]*)(/([^/]*)(/([^/]*))?)?") SURNAME_RE = re.compile(r"/([^/]*)/([^/]*)") -#----------------------------------------------------------------------- +# ----------------------------------------------------------------------- # # GedcomDateParser # -#----------------------------------------------------------------------- +# ----------------------------------------------------------------------- class GedcomDateParser(DateParser): - """ Parse the dates """ - month_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, } + """Parse the dates""" - _locale = GrampsLocale(lang='en_US') # no register_datehandler here + month_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, + } + + _locale = GrampsLocale(lang="en_US") # no register_datehandler here def dhformat_changed(self): - """ Allow overriding so a subclass can modify it """ + """Allow overriding so a subclass can modify it""" self.dhformat = "%m/%d/%y" -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # Lexer - serves as the lexical analysis engine # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class Lexer: - """ low level line reading and early parsing """ + """low level line reading and early parsing""" + def __init__(self, ifile, __add_msg): self.ifile = ifile self.current_list = [] @@ -852,23 +936,25 @@ class Lexer: self.cnv = None self.cnt = 0 self.index = 0 - self.func_map = {TOKEN_CONT : self.__fix_token_cont, - TOKEN_CONC : self.__fix_token_conc} + self.func_map = { + TOKEN_CONT: self.__fix_token_cont, + TOKEN_CONC: self.__fix_token_conc, + } self.__add_msg = __add_msg def readline(self): - """ read a line from file with possibility of putting it back """ + """read a line from file with possibility of putting it back""" if len(self.current_list) <= 1 and not self.eof: self.__readahead() try: return GedLine(self.current_list.pop()) except: - LOG.debug('Error in reading Gedcom line', exc_info=True) + LOG.debug("Error in reading Gedcom line", exc_info=True) return None def __fix_token_cont(self, data): line = self.current_list[0] - new_value = line[2] + '\n' + data[2] + new_value = line[2] + "\n" + data[2] self.current_list[0] = (line[0], line[1], new_value, line[3], line[4]) def __fix_token_conc(self, data): @@ -881,7 +967,7 @@ class Lexer: # space to separate the new line from the tag. This prevents the # first letter of the new line being lost later # in _GedcomParse.__parse_record - new_value = line[2] + ' ' + data[2] + new_value = line[2] + " " + data[2] else: new_value = line[2] + data[2] self.current_list[0] = (line[0], line[1], new_value, line[3], line[4]) @@ -901,44 +987,45 @@ class Lexer: # a GEDCOM line should be ignored" # We will also strip the terminator which is any combination # of carriage_return and line_feed - line = line.lstrip(' ').rstrip('\n\r') + line = line.lstrip(" ").rstrip("\n\r") # split into level+delim+rest - line = line.partition(' ') + line = line.partition(" ") level = int(line[0]) # there should only be one space after the level, # but we can ignore more, - line = line[2].lstrip(' ') + line = line[2].lstrip(" ") # then split into tag+delim+line_value # or xfef_id+delim+rest # the xref_id can have spaces in it - if line.startswith('@'): - line = line.split('@', 2) + if line.startswith("@"): + line = line.split("@", 2) # line is now [None, alphanum+pointer_string, rest] - tag = '@' + line[1] + '@' + tag = "@" + line[1] + "@" line_value = line[2].lstrip() # Ignore meaningless @IDENT@ on CONT or CONC line # as noted at http://www.tamurajones.net/IdentCONT.xhtml - if (line_value.lstrip().startswith("CONT ") or - line_value.lstrip().startswith("CONC ")): - line = line_value.lstrip().partition(' ') + if line_value.lstrip().startswith( + "CONT " + ) or line_value.lstrip().startswith("CONC "): + line = line_value.lstrip().partition(" ") tag = line[0] line_value = line[2] else: - line = line.partition(' ') + line = line.partition(" ") tag = line[0] line_value = line[2] except: problem = _("Line ignored ") - text = original_line.rstrip('\n\r') + text = original_line.rstrip("\n\r") prob_width = 66 - problem = problem.ljust(prob_width)[0:(prob_width - 1)] + problem = problem.ljust(prob_width)[0 : (prob_width - 1)] text = text.replace("\n", "\n".ljust(prob_width + 22)) message = "%s %s" % (problem, text) self.__add_msg(message) continue # Need to un-double '@' See Gedcom 5.5 spec 'any_char' - line_value = line_value.replace('@@', '@') + line_value = line_value.replace("@@", "@") token = TOKENS.get(tag, TOKEN_UNKNOWN) data = (level, token, line_value, tag, self.index) @@ -965,11 +1052,11 @@ class Lexer: del self.func_map -#----------------------------------------------------------------------- +# ----------------------------------------------------------------------- # # GedLine - represents a tokenized version of a GEDCOM line # -#----------------------------------------------------------------------- +# ----------------------------------------------------------------------- class GedLine: """ GedLine is a class the represents a GEDCOM line. The form of a GEDCOM line @@ -989,6 +1076,7 @@ class GedLine: TOKEN_SEX - Person gender item TOEKN_UKNOWN - Check to see if this is a known event """ + __DATE_CNV = GedcomDateParser() @staticmethod @@ -999,15 +1087,15 @@ class GedLine: dateobj = Date() # Horrible hack for importing illegal GEDCOM from Apple Macintosh # Classic 'Gene' program - text = text.replace('BET ABT', 'EST BET') + text = text.replace("BET ABT", "EST BET") # extract out the MOD line match = MOD.match(text) - mod = '' + mod = "" if match: (mod, text) = match.groups() qual = QUALITY_MAP.get(mod, Date.QUAL_NONE) - mod += ' ' + mod += " " else: qual = Date.QUAL_NONE @@ -1027,20 +1115,30 @@ class GedLine: cal1 = CALENDAR_MAP_GEDCOM2XML.get(cal1, Date.CAL_GREGORIAN) cal2 = CALENDAR_MAP_GEDCOM2XML.get(cal2, Date.CAL_GREGORIAN) if cal1 != cal2: - #not supported by GRAMPS, import as text, we construct a string + # not supported by GRAMPS, import as text, we construct a string # that the parser will not parse as a correct date return GedLine.__DATE_CNV.parse( - '%sbetween %s%s and %s%s' % - (mod, data1, CALENDAR_MAP_WRONGSTRING.get(cal1, ''), - CALENDAR_MAP_WRONGSTRING.get(cal2, ''), data2)) + "%sbetween %s%s and %s%s" + % ( + mod, + data1, + CALENDAR_MAP_WRONGSTRING.get(cal1, ""), + CALENDAR_MAP_WRONGSTRING.get(cal2, ""), + data2, + ) + ) - #add hebrew, ... calendar so that months are recognized - data1 += CALENDAR_MAP_PARSESTRING.get(cal1, '') - data2 += CALENDAR_MAP_PARSESTRING.get(cal2, '') + # add hebrew, ... calendar so that months are recognized + data1 += CALENDAR_MAP_PARSESTRING.get(cal1, "") + data2 += CALENDAR_MAP_PARSESTRING.get(cal2, "") start = GedLine.__DATE_CNV.parse(data1) stop = GedLine.__DATE_CNV.parse(data2) - dateobj.set(Date.QUAL_NONE, Date.MOD_RANGE, cal1, - start.get_start_date() + stop.get_start_date()) + dateobj.set( + Date.QUAL_NONE, + Date.MOD_RANGE, + cal1, + start.get_start_date() + stop.get_start_date(), + ) dateobj.set_quality(qual) return dateobj @@ -1060,19 +1158,29 @@ class GedLine: cal1 = CALENDAR_MAP_GEDCOM2XML.get(cal1, Date.CAL_GREGORIAN) cal2 = CALENDAR_MAP_GEDCOM2XML.get(cal2, Date.CAL_GREGORIAN) if cal1 != cal2: - #not supported by GRAMPS, import as text, we construct a string + # not supported by GRAMPS, import as text, we construct a string # that the parser will not parse as a correct date return GedLine.__DATE_CNV.parse( - '%sfrom %s%s to %s%s' % - (mod, data1, CALENDAR_MAP_WRONGSTRING.get(cal1, ''), - CALENDAR_MAP_WRONGSTRING.get(cal2, ''), data2)) - #add hebrew, ... calendar so that months are recognized - data1 += CALENDAR_MAP_PARSESTRING.get(cal1, '') - data2 += CALENDAR_MAP_PARSESTRING.get(cal2, '') + "%sfrom %s%s to %s%s" + % ( + mod, + data1, + CALENDAR_MAP_WRONGSTRING.get(cal1, ""), + CALENDAR_MAP_WRONGSTRING.get(cal2, ""), + data2, + ) + ) + # add hebrew, ... calendar so that months are recognized + data1 += CALENDAR_MAP_PARSESTRING.get(cal1, "") + data2 += CALENDAR_MAP_PARSESTRING.get(cal2, "") start = GedLine.__DATE_CNV.parse(data1) stop = GedLine.__DATE_CNV.parse(data2) - dateobj.set(Date.QUAL_NONE, Date.MOD_SPAN, cal1, - start.get_start_date() + stop.get_start_date()) + dateobj.set( + Date.QUAL_NONE, + Date.MOD_SPAN, + cal1, + start.get_start_date() + stop.get_start_date(), + ) dateobj.set_quality(qual) return dateobj @@ -1080,7 +1188,7 @@ class GedLine: if match: (abt, call, data) = match.groups() call = CALENDAR_MAP_GEDCOM2XML.get(call, Date.CAL_GREGORIAN) - data += CALENDAR_MAP_PARSESTRING.get(call, '') + data += CALENDAR_MAP_PARSESTRING.get(call, "") if abt: dateobj = GedLine.__DATE_CNV.parse("%s %s" % (abt, data)) else: @@ -1108,8 +1216,11 @@ class GedLine: self.data = str(data[2]) if self.level == 0: - if (self.token_text and self.token_text[0] == '@' and - self.token_text[-1] == '@'): + if ( + self.token_text + and self.token_text[0] == "@" + and self.token_text[-1] == "@" + ): self.token = TOKEN_ID self.token_text = self.token_text[1:-1] self.data = self.data.strip() @@ -1123,8 +1234,7 @@ class GedLine: Converts the data field to a gen.lib token indicating the gender """ try: - self.data = SEX_MAP.get(self.data.strip()[0], - Person.UNKNOWN) + self.data = SEX_MAP.get(self.data.strip()[0], Person.UNKNOWN) except: self.data = Person.UNKNOWN @@ -1158,14 +1268,14 @@ class GedLine: self.data = attr def calc_note(self): - """ look for a note xref @N0001@ """ + """look for a note xref @N0001@""" gid = self.data.strip() - if len(gid) > 2 and gid[0] == '@' and gid[-1] == '@': + if len(gid) > 2 and gid[0] == "@" and gid[-1] == "@": self.token = TOKEN_RNOTE self.data = gid[1:-1] def calc_nchi(self): - """ set attribute for number of children """ + """set attribute for number of children""" attr = Attribute() attr.set_value(self.data) attr.set_type(AttributeType.NUM_CHILD) @@ -1173,7 +1283,7 @@ class GedLine: self.token = TOKEN_ATTR def calc_attr(self): - """ set attribure for general attributes """ + """set attribure for general attributes""" attr = Attribute() attr.set_value(self.data) attr.set_type((AttributeType.CUSTOM, self.token_text)) @@ -1181,63 +1291,74 @@ class GedLine: self.token = TOKEN_ATTR def __repr__(self): - return "%d: %d (%d:%s) %s" % (self.line, self.level, self.token, - self.token_text, self.data) + return "%d: %d (%d:%s) %s" % ( + self.line, + self.level, + self.token, + self.token_text, + self.data, + ) + _MAP_DATA = { - TOKEN_UNKNOWN : GedLine.calc_unknown, - TOKEN_DATE : GedLine.calc_date, - TOKEN__DATE : GedLine.calc_date, - TOKEN_SEX : GedLine.calc_sex, - TOKEN_NOTE : GedLine.calc_note, - TOKEN_NCHI : GedLine.calc_nchi, - TOKEN__STAT : GedLine.calc_attr, - TOKEN__UID : GedLine.calc_attr, - TOKEN_AFN : GedLine.calc_attr, - TOKEN__FSFTID : GedLine.calc_attr, } + TOKEN_UNKNOWN: GedLine.calc_unknown, + TOKEN_DATE: GedLine.calc_date, + TOKEN__DATE: GedLine.calc_date, + TOKEN_SEX: GedLine.calc_sex, + TOKEN_NOTE: GedLine.calc_note, + TOKEN_NCHI: GedLine.calc_nchi, + TOKEN__STAT: GedLine.calc_attr, + TOKEN__UID: GedLine.calc_attr, + TOKEN_AFN: GedLine.calc_attr, + TOKEN__FSFTID: GedLine.calc_attr, +} -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # File Readers # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class BaseReader: - """ base char level reader """ + """base char level reader""" + def __init__(self, ifile, encoding, __add_msg): self.ifile = ifile self.enc = encoding self.__add_msg = __add_msg def reset(self): - """ return to beginning """ + """return to beginning""" self.ifile.seek(0) def readline(self): - """ Read a single line """ + """Read a single line""" raise NotImplementedError() def report_error(self, problem, line): - """ Create an error message """ - line = line.rstrip('\n\r') + """Create an error message""" + line = line.rstrip("\n\r") prob_width = 66 - problem = problem.ljust(prob_width)[0:(prob_width - 1)] + problem = problem.ljust(prob_width)[0 : (prob_width - 1)] text = line.replace("\n", "\n".ljust(prob_width + 22)) message = "%s %s" % (problem, text) self.__add_msg(message) class UTF8Reader(BaseReader): - """ The main UTF-8 reader, uses Python for char handling """ + """The main UTF-8 reader, uses Python for char handling""" + def __init__(self, ifile, __add_msg, enc): BaseReader.__init__(self, ifile, enc, __add_msg) self.reset() - if enc == 'UTF_8_SIG': - self.ifile = TextIOWrapper(ifile, encoding='utf_8_sig', - errors='replace', newline=None) + if enc == "UTF_8_SIG": + self.ifile = TextIOWrapper( + ifile, encoding="utf_8_sig", errors="replace", newline=None + ) else: - self.ifile = TextIOWrapper(ifile, encoding='utf_8', - errors='replace', newline=None) + self.ifile = TextIOWrapper( + ifile, encoding="utf_8", errors="replace", newline=None + ) def readline(self): line = self.ifile.readline() @@ -1245,11 +1366,13 @@ class UTF8Reader(BaseReader): class UTF16Reader(BaseReader): - """ The main UTF-16 reader, uses Python for char handling """ + """The main UTF-16 reader, uses Python for char handling""" + def __init__(self, ifile, __add_msg): - BaseReader.__init__(self, ifile, 'UTF16', __add_msg) - self.ifile = TextIOWrapper(ifile, encoding='utf_16', - errors='replace', newline=None) + BaseReader.__init__(self, ifile, "UTF16", __add_msg) + self.ifile = TextIOWrapper( + ifile, encoding="utf_16", errors="replace", newline=None + ) self.reset() def readline(self): @@ -1258,26 +1381,31 @@ class UTF16Reader(BaseReader): class AnsiReader(BaseReader): - """ The main ANSI (latin1) reader, uses Python for char handling """ + """The main ANSI (latin1) reader, uses Python for char handling""" + def __init__(self, ifile, __add_msg): - BaseReader.__init__(self, ifile, 'latin1', __add_msg) - self.ifile = TextIOWrapper(ifile, encoding='latin1', - errors='replace', newline=None) + BaseReader.__init__(self, ifile, "latin1", __add_msg) + self.ifile = TextIOWrapper( + ifile, encoding="latin1", errors="replace", newline=None + ) def readline(self): line = self.ifile.readline() if line.translate(DEL_AND_C1) != line: - self.report_error("DEL or C1 control chars in line did you mean " - "CHAR cp1252??", line) + self.report_error( + "DEL or C1 control chars in line did you mean " "CHAR cp1252??", line + ) return line.translate(STRIP_DICT) class CP1252Reader(BaseReader): - """ The extra credit CP1252 reader, uses Python for char handling """ + """The extra credit CP1252 reader, uses Python for char handling""" + def __init__(self, ifile, __add_msg): - BaseReader.__init__(self, ifile, 'cp1252', __add_msg) - self.ifile = TextIOWrapper(ifile, encoding='cp1252', - errors='replace', newline=None) + BaseReader.__init__(self, ifile, "cp1252", __add_msg) + self.ifile = TextIOWrapper( + ifile, encoding="cp1252", errors="replace", newline=None + ) def readline(self): line = self.ifile.readline() @@ -1302,26 +1430,55 @@ class AnselReader(BaseReader): --- ?: should we allow TAB, as a Gramps extension? """ + __printable_ascii = list(map(chr, list(range(32, 127)))) # up thru 126 # LF CR Esc GS RS US __use_ASCII = list(map(chr, [10, 13, 27, 29, 30, 31])) + __printable_ascii # mappings of single byte ANSEL codes to unicode __onebyte = { - b'\xA1' : '\u0141', b'\xA2' : '\u00d8', b'\xA3' : '\u0110', - b'\xA4' : '\u00de', b'\xA5' : '\u00c6', b'\xA6' : '\u0152', - b'\xA7' : '\u02b9', b'\xA8' : '\u00b7', b'\xA9' : '\u266d', - b'\xAA' : '\u00ae', b'\xAB' : '\u00b1', b'\xAC' : '\u01a0', - b'\xAD' : '\u01af', b'\xAE' : '\u02bc', b'\xB0' : '\u02bb', - b'\xB1' : '\u0142', b'\xB2' : '\u00f8', b'\xB3' : '\u0111', - b'\xB4' : '\u00fe', b'\xB5' : '\u00e6', b'\xB6' : '\u0153', - b'\xB7' : '\u02ba', b'\xB8' : '\u0131', b'\xB9' : '\u00a3', - b'\xBA' : '\u00f0', b'\xBC' : '\u01a1', b'\xBD' : '\u01b0', - b'\xBE' : '\u25a1', b'\xBF' : '\u25a0', - b'\xC0' : '\u00b0', b'\xC1' : '\u2113', b'\xC2' : '\u2117', - b'\xC3' : '\u00a9', b'\xC4' : '\u266f', b'\xC5' : '\u00bf', - b'\xC6' : '\u00a1', b'\xC7' : '\u00df', b'\xC8' : '\u20ac', - b'\xCD' : '\u0065', b'\xCE' : '\u006f', b'\xCF' : '\u00df', } + b"\xA1": "\u0141", + b"\xA2": "\u00d8", + b"\xA3": "\u0110", + b"\xA4": "\u00de", + b"\xA5": "\u00c6", + b"\xA6": "\u0152", + b"\xA7": "\u02b9", + b"\xA8": "\u00b7", + b"\xA9": "\u266d", + b"\xAA": "\u00ae", + b"\xAB": "\u00b1", + b"\xAC": "\u01a0", + b"\xAD": "\u01af", + b"\xAE": "\u02bc", + b"\xB0": "\u02bb", + b"\xB1": "\u0142", + b"\xB2": "\u00f8", + b"\xB3": "\u0111", + b"\xB4": "\u00fe", + b"\xB5": "\u00e6", + b"\xB6": "\u0153", + b"\xB7": "\u02ba", + b"\xB8": "\u0131", + b"\xB9": "\u00a3", + b"\xBA": "\u00f0", + b"\xBC": "\u01a1", + b"\xBD": "\u01b0", + b"\xBE": "\u25a1", + b"\xBF": "\u25a0", + b"\xC0": "\u00b0", + b"\xC1": "\u2113", + b"\xC2": "\u2117", + b"\xC3": "\u00a9", + b"\xC4": "\u266f", + b"\xC5": "\u00bf", + b"\xC6": "\u00a1", + b"\xC7": "\u00df", + b"\xC8": "\u20ac", + b"\xCD": "\u0065", + b"\xCE": "\u006f", + b"\xCF": "\u00df", + } # combining forms (in ANSEL, they precede the modified ASCII character # whereas the unicode combining term follows the character modified @@ -1331,174 +1488,346 @@ class AnselReader(BaseReader): # (strange things) probably not commonly found in our needs, unless one # starts writing persian (or???) poetry in ANSEL __acombiners = { - b'\x8D' : '\u200d', b'\x8E' : '\u200c', b'\xE0' : '\u0309', - b'\xE1' : '\u0300', b'\xE2' : '\u0301', b'\xE3' : '\u0302', - b'\xE4' : '\u0303', b'\xE5' : '\u0304', b'\xE6' : '\u0306', - b'\xE7' : '\u0307', b'\xE8' : '\u0308', b'\xE9' : '\u030c', - b'\xEA' : '\u030a', b'\xEB' : '\ufe20', b'\xEC' : '\ufe21', - b'\xED' : '\u0315', b'\xEE' : '\u030b', b'\xEF' : '\u0310', - b'\xF0' : '\u0327', b'\xF1' : '\u0328', b'\xF2' : '\u0323', - b'\xF3' : '\u0324', b'\xF4' : '\u0325', b'\xF5' : '\u0333', - b'\xF6' : '\u0332', b'\xF7' : '\u0326', b'\xF8' : '\u031c', - b'\xF9' : '\u032e', b'\xFA' : '\ufe22', b'\xFB' : '\ufe23', - b'\xFC' : '\u0338', - b'\xFE' : '\u0313', } + b"\x8D": "\u200d", + b"\x8E": "\u200c", + b"\xE0": "\u0309", + b"\xE1": "\u0300", + b"\xE2": "\u0301", + b"\xE3": "\u0302", + b"\xE4": "\u0303", + b"\xE5": "\u0304", + b"\xE6": "\u0306", + b"\xE7": "\u0307", + b"\xE8": "\u0308", + b"\xE9": "\u030c", + b"\xEA": "\u030a", + b"\xEB": "\ufe20", + b"\xEC": "\ufe21", + b"\xED": "\u0315", + b"\xEE": "\u030b", + b"\xEF": "\u0310", + b"\xF0": "\u0327", + b"\xF1": "\u0328", + b"\xF2": "\u0323", + b"\xF3": "\u0324", + b"\xF4": "\u0325", + b"\xF5": "\u0333", + b"\xF6": "\u0332", + b"\xF7": "\u0326", + b"\xF8": "\u031c", + b"\xF9": "\u032e", + b"\xFA": "\ufe22", + b"\xFB": "\ufe23", + b"\xFC": "\u0338", + b"\xFE": "\u0313", + } # mappings of two byte (precomposed forms) ANSEL codes to unicode __twobyte = { - b'\xE0\x41' : '\u1ea2', b'\xE0\x45' : '\u1eba', - b'\xE0\x49' : '\u1ec8', b'\xE0\x4F' : '\u1ece', - b'\xE0\x55' : '\u1ee6', b'\xE0\x59' : '\u1ef6', - b'\xE0\x61' : '\u1ea3', b'\xE0\x65' : '\u1ebb', - b'\xE0\x69' : '\u1ec9', b'\xE0\x6F' : '\u1ecf', - b'\xE0\x75' : '\u1ee7', b'\xE0\x79' : '\u1ef7', - b'\xE1\x41' : '\u00c0', b'\xE1\x45' : '\u00c8', - b'\xE1\x49' : '\u00cc', b'\xE1\x4F' : '\u00d2', - b'\xE1\x55' : '\u00d9', b'\xE1\x57' : '\u1e80', - b'\xE1\x59' : '\u1ef2', b'\xE1\x61' : '\u00e0', - b'\xE1\x65' : '\u00e8', b'\xE1\x69' : '\u00ec', - b'\xE1\x6F' : '\u00f2', b'\xE1\x75' : '\u00f9', - b'\xE1\x77' : '\u1e81', b'\xE1\x79' : '\u1ef3', - b'\xE2\x41' : '\u00c1', b'\xE2\x43' : '\u0106', - b'\xE2\x45' : '\u00c9', b'\xE2\x47' : '\u01f4', - b'\xE2\x49' : '\u00cd', b'\xE2\x4B' : '\u1e30', - b'\xE2\x4C' : '\u0139', b'\xE2\x4D' : '\u1e3e', - b'\xE2\x4E' : '\u0143', b'\xE2\x4F' : '\u00d3', - b'\xE2\x50' : '\u1e54', b'\xE2\x52' : '\u0154', - b'\xE2\x53' : '\u015a', b'\xE2\x55' : '\u00da', - b'\xE2\x57' : '\u1e82', b'\xE2\x59' : '\u00dd', - b'\xE2\x5A' : '\u0179', b'\xE2\x61' : '\u00e1', - b'\xE2\x63' : '\u0107', b'\xE2\x65' : '\u00e9', - b'\xE2\x67' : '\u01f5', b'\xE2\x69' : '\u00ed', - b'\xE2\x6B' : '\u1e31', b'\xE2\x6C' : '\u013a', - b'\xE2\x6D' : '\u1e3f', b'\xE2\x6E' : '\u0144', - b'\xE2\x6F' : '\u00f3', b'\xE2\x70' : '\u1e55', - b'\xE2\x72' : '\u0155', b'\xE2\x73' : '\u015b', - b'\xE2\x75' : '\u00fa', b'\xE2\x77' : '\u1e83', - b'\xE2\x79' : '\u00fd', b'\xE2\x7A' : '\u017a', - b'\xE2\xA5' : '\u01fc', b'\xE2\xB5' : '\u01fd', - b'\xE3\x41' : '\u00c2', b'\xE3\x43' : '\u0108', - b'\xE3\x45' : '\u00ca', b'\xE3\x47' : '\u011c', - b'\xE3\x48' : '\u0124', b'\xE3\x49' : '\u00ce', - b'\xE3\x4A' : '\u0134', b'\xE3\x4F' : '\u00d4', - b'\xE3\x53' : '\u015c', b'\xE3\x55' : '\u00db', - b'\xE3\x57' : '\u0174', b'\xE3\x59' : '\u0176', - b'\xE3\x5A' : '\u1e90', b'\xE3\x61' : '\u00e2', - b'\xE3\x63' : '\u0109', b'\xE3\x65' : '\u00ea', - b'\xE3\x67' : '\u011d', b'\xE3\x68' : '\u0125', - b'\xE3\x69' : '\u00ee', b'\xE3\x6A' : '\u0135', - b'\xE3\x6F' : '\u00f4', b'\xE3\x73' : '\u015d', - b'\xE3\x75' : '\u00fb', b'\xE3\x77' : '\u0175', - b'\xE3\x79' : '\u0177', b'\xE3\x7A' : '\u1e91', - b'\xE4\x41' : '\u00c3', b'\xE4\x45' : '\u1ebc', - b'\xE4\x49' : '\u0128', b'\xE4\x4E' : '\u00d1', - b'\xE4\x4F' : '\u00d5', b'\xE4\x55' : '\u0168', - b'\xE4\x56' : '\u1e7c', b'\xE4\x59' : '\u1ef8', - b'\xE4\x61' : '\u00e3', b'\xE4\x65' : '\u1ebd', - b'\xE4\x69' : '\u0129', b'\xE4\x6E' : '\u00f1', - b'\xE4\x6F' : '\u00f5', b'\xE4\x75' : '\u0169', - b'\xE4\x76' : '\u1e7d', b'\xE4\x79' : '\u1ef9', - b'\xE5\x41' : '\u0100', b'\xE5\x45' : '\u0112', - b'\xE5\x47' : '\u1e20', b'\xE5\x49' : '\u012a', - b'\xE5\x4F' : '\u014c', b'\xE5\x55' : '\u016a', - b'\xE5\x61' : '\u0101', b'\xE5\x65' : '\u0113', - b'\xE5\x67' : '\u1e21', b'\xE5\x69' : '\u012b', - b'\xE5\x6F' : '\u014d', b'\xE5\x75' : '\u016b', - b'\xE5\xA5' : '\u01e2', b'\xE5\xB5' : '\u01e3', - b'\xE6\x41' : '\u0102', b'\xE6\x45' : '\u0114', - b'\xE6\x47' : '\u011e', b'\xE6\x49' : '\u012c', - b'\xE6\x4F' : '\u014e', b'\xE6\x55' : '\u016c', - b'\xE6\x61' : '\u0103', b'\xE6\x65' : '\u0115', - b'\xE6\x67' : '\u011f', b'\xE6\x69' : '\u012d', - b'\xE6\x6F' : '\u014f', b'\xE6\x75' : '\u016d', - b'\xE7\x42' : '\u1e02', b'\xE7\x43' : '\u010a', - b'\xE7\x44' : '\u1e0a', b'\xE7\x45' : '\u0116', - b'\xE7\x46' : '\u1e1e', b'\xE7\x47' : '\u0120', - b'\xE7\x48' : '\u1e22', b'\xE7\x49' : '\u0130', - b'\xE7\x4D' : '\u1e40', b'\xE7\x4E' : '\u1e44', - b'\xE7\x50' : '\u1e56', b'\xE7\x52' : '\u1e58', - b'\xE7\x53' : '\u1e60', b'\xE7\x54' : '\u1e6a', - b'\xE7\x57' : '\u1e86', b'\xE7\x58' : '\u1e8a', - b'\xE7\x59' : '\u1e8e', b'\xE7\x5A' : '\u017b', - b'\xE7\x62' : '\u1e03', b'\xE7\x63' : '\u010b', - b'\xE7\x64' : '\u1e0b', b'\xE7\x65' : '\u0117', - b'\xE7\x66' : '\u1e1f', b'\xE7\x67' : '\u0121', - b'\xE7\x68' : '\u1e23', b'\xE7\x6D' : '\u1e41', - b'\xE7\x6E' : '\u1e45', b'\xE7\x70' : '\u1e57', - b'\xE7\x72' : '\u1e59', b'\xE7\x73' : '\u1e61', - b'\xE7\x74' : '\u1e6b', b'\xE7\x77' : '\u1e87', - b'\xE7\x78' : '\u1e8b', b'\xE7\x79' : '\u1e8f', - b'\xE7\x7A' : '\u017c', b'\xE8\x41' : '\u00c4', - b'\xE8\x45' : '\u00cb', b'\xE8\x48' : '\u1e26', - b'\xE8\x49' : '\u00cf', b'\xE8\x4F' : '\u00d6', - b'\xE8\x55' : '\u00dc', b'\xE8\x57' : '\u1e84', - b'\xE8\x58' : '\u1e8c', b'\xE8\x59' : '\u0178', - b'\xE8\x61' : '\u00e4', b'\xE8\x65' : '\u00eb', - b'\xE8\x68' : '\u1e27', b'\xE8\x69' : '\u00ef', - b'\xE8\x6F' : '\u00f6', b'\xE8\x74' : '\u1e97', - b'\xE8\x75' : '\u00fc', b'\xE8\x77' : '\u1e85', - b'\xE8\x78' : '\u1e8d', b'\xE8\x79' : '\u00ff', - b'\xE9\x41' : '\u01cd', b'\xE9\x43' : '\u010c', - b'\xE9\x44' : '\u010e', b'\xE9\x45' : '\u011a', - b'\xE9\x47' : '\u01e6', b'\xE9\x49' : '\u01cf', - b'\xE9\x4B' : '\u01e8', b'\xE9\x4C' : '\u013d', - b'\xE9\x4E' : '\u0147', b'\xE9\x4F' : '\u01d1', - b'\xE9\x52' : '\u0158', b'\xE9\x53' : '\u0160', - b'\xE9\x54' : '\u0164', b'\xE9\x55' : '\u01d3', - b'\xE9\x5A' : '\u017d', b'\xE9\x61' : '\u01ce', - b'\xE9\x63' : '\u010d', b'\xE9\x64' : '\u010f', - b'\xE9\x65' : '\u011b', b'\xE9\x67' : '\u01e7', - b'\xE9\x69' : '\u01d0', b'\xE9\x6A' : '\u01f0', - b'\xE9\x6B' : '\u01e9', b'\xE9\x6C' : '\u013e', - b'\xE9\x6E' : '\u0148', b'\xE9\x6F' : '\u01d2', - b'\xE9\x72' : '\u0159', b'\xE9\x73' : '\u0161', - b'\xE9\x74' : '\u0165', b'\xE9\x75' : '\u01d4', - b'\xE9\x7A' : '\u017e', b'\xEA\x41' : '\u00c5', - b'\xEA\x61' : '\u00e5', b'\xEA\x75' : '\u016f', - b'\xEA\x77' : '\u1e98', b'\xEA\x79' : '\u1e99', - b'\xEA\xAD' : '\u016e', b'\xEE\x4F' : '\u0150', - b'\xEE\x55' : '\u0170', b'\xEE\x6F' : '\u0151', - b'\xEE\x75' : '\u0171', b'\xF0\x20' : '\u00b8', - b'\xF0\x43' : '\u00c7', b'\xF0\x44' : '\u1e10', - b'\xF0\x47' : '\u0122', b'\xF0\x48' : '\u1e28', - b'\xF0\x4B' : '\u0136', b'\xF0\x4C' : '\u013b', - b'\xF0\x4E' : '\u0145', b'\xF0\x52' : '\u0156', - b'\xF0\x53' : '\u015e', b'\xF0\x54' : '\u0162', - b'\xF0\x63' : '\u00e7', b'\xF0\x64' : '\u1e11', - b'\xF0\x67' : '\u0123', b'\xF0\x68' : '\u1e29', - b'\xF0\x6B' : '\u0137', b'\xF0\x6C' : '\u013c', - b'\xF0\x6E' : '\u0146', b'\xF0\x72' : '\u0157', - b'\xF0\x73' : '\u015f', b'\xF0\x74' : '\u0163', - b'\xF1\x41' : '\u0104', b'\xF1\x45' : '\u0118', - b'\xF1\x49' : '\u012e', b'\xF1\x4F' : '\u01ea', - b'\xF1\x55' : '\u0172', b'\xF1\x61' : '\u0105', - b'\xF1\x65' : '\u0119', b'\xF1\x69' : '\u012f', - b'\xF1\x6F' : '\u01eb', b'\xF1\x75' : '\u0173', - b'\xF2\x41' : '\u1ea0', b'\xF2\x42' : '\u1e04', - b'\xF2\x44' : '\u1e0c', b'\xF2\x45' : '\u1eb8', - b'\xF2\x48' : '\u1e24', b'\xF2\x49' : '\u1eca', - b'\xF2\x4B' : '\u1e32', b'\xF2\x4C' : '\u1e36', - b'\xF2\x4D' : '\u1e42', b'\xF2\x4E' : '\u1e46', - b'\xF2\x4F' : '\u1ecc', b'\xF2\x52' : '\u1e5a', - b'\xF2\x53' : '\u1e62', b'\xF2\x54' : '\u1e6c', - b'\xF2\x55' : '\u1ee4', b'\xF2\x56' : '\u1e7e', - b'\xF2\x57' : '\u1e88', b'\xF2\x59' : '\u1ef4', - b'\xF2\x5A' : '\u1e92', b'\xF2\x61' : '\u1ea1', - b'\xF2\x62' : '\u1e05', b'\xF2\x64' : '\u1e0d', - b'\xF2\x65' : '\u1eb9', b'\xF2\x68' : '\u1e25', - b'\xF2\x69' : '\u1ecb', b'\xF2\x6B' : '\u1e33', - b'\xF2\x6C' : '\u1e37', b'\xF2\x6D' : '\u1e43', - b'\xF2\x6E' : '\u1e47', b'\xF2\x6F' : '\u1ecd', - b'\xF2\x72' : '\u1e5b', b'\xF2\x73' : '\u1e63', - b'\xF2\x74' : '\u1e6d', b'\xF2\x75' : '\u1ee5', - b'\xF2\x76' : '\u1e7f', b'\xF2\x77' : '\u1e89', - b'\xF2\x79' : '\u1ef5', b'\xF2\x7A' : '\u1e93', - b'\xF3\x55' : '\u1e72', b'\xF3\x75' : '\u1e73', - b'\xF4\x41' : '\u1e00', b'\xF4\x61' : '\u1e01', - b'\xF9\x48' : '\u1e2a', b'\xF9\x68' : '\u1e2b', } + b"\xE0\x41": "\u1ea2", + b"\xE0\x45": "\u1eba", + b"\xE0\x49": "\u1ec8", + b"\xE0\x4F": "\u1ece", + b"\xE0\x55": "\u1ee6", + b"\xE0\x59": "\u1ef6", + b"\xE0\x61": "\u1ea3", + b"\xE0\x65": "\u1ebb", + b"\xE0\x69": "\u1ec9", + b"\xE0\x6F": "\u1ecf", + b"\xE0\x75": "\u1ee7", + b"\xE0\x79": "\u1ef7", + b"\xE1\x41": "\u00c0", + b"\xE1\x45": "\u00c8", + b"\xE1\x49": "\u00cc", + b"\xE1\x4F": "\u00d2", + b"\xE1\x55": "\u00d9", + b"\xE1\x57": "\u1e80", + b"\xE1\x59": "\u1ef2", + b"\xE1\x61": "\u00e0", + b"\xE1\x65": "\u00e8", + b"\xE1\x69": "\u00ec", + b"\xE1\x6F": "\u00f2", + b"\xE1\x75": "\u00f9", + b"\xE1\x77": "\u1e81", + b"\xE1\x79": "\u1ef3", + b"\xE2\x41": "\u00c1", + b"\xE2\x43": "\u0106", + b"\xE2\x45": "\u00c9", + b"\xE2\x47": "\u01f4", + b"\xE2\x49": "\u00cd", + b"\xE2\x4B": "\u1e30", + b"\xE2\x4C": "\u0139", + b"\xE2\x4D": "\u1e3e", + b"\xE2\x4E": "\u0143", + b"\xE2\x4F": "\u00d3", + b"\xE2\x50": "\u1e54", + b"\xE2\x52": "\u0154", + b"\xE2\x53": "\u015a", + b"\xE2\x55": "\u00da", + b"\xE2\x57": "\u1e82", + b"\xE2\x59": "\u00dd", + b"\xE2\x5A": "\u0179", + b"\xE2\x61": "\u00e1", + b"\xE2\x63": "\u0107", + b"\xE2\x65": "\u00e9", + b"\xE2\x67": "\u01f5", + b"\xE2\x69": "\u00ed", + b"\xE2\x6B": "\u1e31", + b"\xE2\x6C": "\u013a", + b"\xE2\x6D": "\u1e3f", + b"\xE2\x6E": "\u0144", + b"\xE2\x6F": "\u00f3", + b"\xE2\x70": "\u1e55", + b"\xE2\x72": "\u0155", + b"\xE2\x73": "\u015b", + b"\xE2\x75": "\u00fa", + b"\xE2\x77": "\u1e83", + b"\xE2\x79": "\u00fd", + b"\xE2\x7A": "\u017a", + b"\xE2\xA5": "\u01fc", + b"\xE2\xB5": "\u01fd", + b"\xE3\x41": "\u00c2", + b"\xE3\x43": "\u0108", + b"\xE3\x45": "\u00ca", + b"\xE3\x47": "\u011c", + b"\xE3\x48": "\u0124", + b"\xE3\x49": "\u00ce", + b"\xE3\x4A": "\u0134", + b"\xE3\x4F": "\u00d4", + b"\xE3\x53": "\u015c", + b"\xE3\x55": "\u00db", + b"\xE3\x57": "\u0174", + b"\xE3\x59": "\u0176", + b"\xE3\x5A": "\u1e90", + b"\xE3\x61": "\u00e2", + b"\xE3\x63": "\u0109", + b"\xE3\x65": "\u00ea", + b"\xE3\x67": "\u011d", + b"\xE3\x68": "\u0125", + b"\xE3\x69": "\u00ee", + b"\xE3\x6A": "\u0135", + b"\xE3\x6F": "\u00f4", + b"\xE3\x73": "\u015d", + b"\xE3\x75": "\u00fb", + b"\xE3\x77": "\u0175", + b"\xE3\x79": "\u0177", + b"\xE3\x7A": "\u1e91", + b"\xE4\x41": "\u00c3", + b"\xE4\x45": "\u1ebc", + b"\xE4\x49": "\u0128", + b"\xE4\x4E": "\u00d1", + b"\xE4\x4F": "\u00d5", + b"\xE4\x55": "\u0168", + b"\xE4\x56": "\u1e7c", + b"\xE4\x59": "\u1ef8", + b"\xE4\x61": "\u00e3", + b"\xE4\x65": "\u1ebd", + b"\xE4\x69": "\u0129", + b"\xE4\x6E": "\u00f1", + b"\xE4\x6F": "\u00f5", + b"\xE4\x75": "\u0169", + b"\xE4\x76": "\u1e7d", + b"\xE4\x79": "\u1ef9", + b"\xE5\x41": "\u0100", + b"\xE5\x45": "\u0112", + b"\xE5\x47": "\u1e20", + b"\xE5\x49": "\u012a", + b"\xE5\x4F": "\u014c", + b"\xE5\x55": "\u016a", + b"\xE5\x61": "\u0101", + b"\xE5\x65": "\u0113", + b"\xE5\x67": "\u1e21", + b"\xE5\x69": "\u012b", + b"\xE5\x6F": "\u014d", + b"\xE5\x75": "\u016b", + b"\xE5\xA5": "\u01e2", + b"\xE5\xB5": "\u01e3", + b"\xE6\x41": "\u0102", + b"\xE6\x45": "\u0114", + b"\xE6\x47": "\u011e", + b"\xE6\x49": "\u012c", + b"\xE6\x4F": "\u014e", + b"\xE6\x55": "\u016c", + b"\xE6\x61": "\u0103", + b"\xE6\x65": "\u0115", + b"\xE6\x67": "\u011f", + b"\xE6\x69": "\u012d", + b"\xE6\x6F": "\u014f", + b"\xE6\x75": "\u016d", + b"\xE7\x42": "\u1e02", + b"\xE7\x43": "\u010a", + b"\xE7\x44": "\u1e0a", + b"\xE7\x45": "\u0116", + b"\xE7\x46": "\u1e1e", + b"\xE7\x47": "\u0120", + b"\xE7\x48": "\u1e22", + b"\xE7\x49": "\u0130", + b"\xE7\x4D": "\u1e40", + b"\xE7\x4E": "\u1e44", + b"\xE7\x50": "\u1e56", + b"\xE7\x52": "\u1e58", + b"\xE7\x53": "\u1e60", + b"\xE7\x54": "\u1e6a", + b"\xE7\x57": "\u1e86", + b"\xE7\x58": "\u1e8a", + b"\xE7\x59": "\u1e8e", + b"\xE7\x5A": "\u017b", + b"\xE7\x62": "\u1e03", + b"\xE7\x63": "\u010b", + b"\xE7\x64": "\u1e0b", + b"\xE7\x65": "\u0117", + b"\xE7\x66": "\u1e1f", + b"\xE7\x67": "\u0121", + b"\xE7\x68": "\u1e23", + b"\xE7\x6D": "\u1e41", + b"\xE7\x6E": "\u1e45", + b"\xE7\x70": "\u1e57", + b"\xE7\x72": "\u1e59", + b"\xE7\x73": "\u1e61", + b"\xE7\x74": "\u1e6b", + b"\xE7\x77": "\u1e87", + b"\xE7\x78": "\u1e8b", + b"\xE7\x79": "\u1e8f", + b"\xE7\x7A": "\u017c", + b"\xE8\x41": "\u00c4", + b"\xE8\x45": "\u00cb", + b"\xE8\x48": "\u1e26", + b"\xE8\x49": "\u00cf", + b"\xE8\x4F": "\u00d6", + b"\xE8\x55": "\u00dc", + b"\xE8\x57": "\u1e84", + b"\xE8\x58": "\u1e8c", + b"\xE8\x59": "\u0178", + b"\xE8\x61": "\u00e4", + b"\xE8\x65": "\u00eb", + b"\xE8\x68": "\u1e27", + b"\xE8\x69": "\u00ef", + b"\xE8\x6F": "\u00f6", + b"\xE8\x74": "\u1e97", + b"\xE8\x75": "\u00fc", + b"\xE8\x77": "\u1e85", + b"\xE8\x78": "\u1e8d", + b"\xE8\x79": "\u00ff", + b"\xE9\x41": "\u01cd", + b"\xE9\x43": "\u010c", + b"\xE9\x44": "\u010e", + b"\xE9\x45": "\u011a", + b"\xE9\x47": "\u01e6", + b"\xE9\x49": "\u01cf", + b"\xE9\x4B": "\u01e8", + b"\xE9\x4C": "\u013d", + b"\xE9\x4E": "\u0147", + b"\xE9\x4F": "\u01d1", + b"\xE9\x52": "\u0158", + b"\xE9\x53": "\u0160", + b"\xE9\x54": "\u0164", + b"\xE9\x55": "\u01d3", + b"\xE9\x5A": "\u017d", + b"\xE9\x61": "\u01ce", + b"\xE9\x63": "\u010d", + b"\xE9\x64": "\u010f", + b"\xE9\x65": "\u011b", + b"\xE9\x67": "\u01e7", + b"\xE9\x69": "\u01d0", + b"\xE9\x6A": "\u01f0", + b"\xE9\x6B": "\u01e9", + b"\xE9\x6C": "\u013e", + b"\xE9\x6E": "\u0148", + b"\xE9\x6F": "\u01d2", + b"\xE9\x72": "\u0159", + b"\xE9\x73": "\u0161", + b"\xE9\x74": "\u0165", + b"\xE9\x75": "\u01d4", + b"\xE9\x7A": "\u017e", + b"\xEA\x41": "\u00c5", + b"\xEA\x61": "\u00e5", + b"\xEA\x75": "\u016f", + b"\xEA\x77": "\u1e98", + b"\xEA\x79": "\u1e99", + b"\xEA\xAD": "\u016e", + b"\xEE\x4F": "\u0150", + b"\xEE\x55": "\u0170", + b"\xEE\x6F": "\u0151", + b"\xEE\x75": "\u0171", + b"\xF0\x20": "\u00b8", + b"\xF0\x43": "\u00c7", + b"\xF0\x44": "\u1e10", + b"\xF0\x47": "\u0122", + b"\xF0\x48": "\u1e28", + b"\xF0\x4B": "\u0136", + b"\xF0\x4C": "\u013b", + b"\xF0\x4E": "\u0145", + b"\xF0\x52": "\u0156", + b"\xF0\x53": "\u015e", + b"\xF0\x54": "\u0162", + b"\xF0\x63": "\u00e7", + b"\xF0\x64": "\u1e11", + b"\xF0\x67": "\u0123", + b"\xF0\x68": "\u1e29", + b"\xF0\x6B": "\u0137", + b"\xF0\x6C": "\u013c", + b"\xF0\x6E": "\u0146", + b"\xF0\x72": "\u0157", + b"\xF0\x73": "\u015f", + b"\xF0\x74": "\u0163", + b"\xF1\x41": "\u0104", + b"\xF1\x45": "\u0118", + b"\xF1\x49": "\u012e", + b"\xF1\x4F": "\u01ea", + b"\xF1\x55": "\u0172", + b"\xF1\x61": "\u0105", + b"\xF1\x65": "\u0119", + b"\xF1\x69": "\u012f", + b"\xF1\x6F": "\u01eb", + b"\xF1\x75": "\u0173", + b"\xF2\x41": "\u1ea0", + b"\xF2\x42": "\u1e04", + b"\xF2\x44": "\u1e0c", + b"\xF2\x45": "\u1eb8", + b"\xF2\x48": "\u1e24", + b"\xF2\x49": "\u1eca", + b"\xF2\x4B": "\u1e32", + b"\xF2\x4C": "\u1e36", + b"\xF2\x4D": "\u1e42", + b"\xF2\x4E": "\u1e46", + b"\xF2\x4F": "\u1ecc", + b"\xF2\x52": "\u1e5a", + b"\xF2\x53": "\u1e62", + b"\xF2\x54": "\u1e6c", + b"\xF2\x55": "\u1ee4", + b"\xF2\x56": "\u1e7e", + b"\xF2\x57": "\u1e88", + b"\xF2\x59": "\u1ef4", + b"\xF2\x5A": "\u1e92", + b"\xF2\x61": "\u1ea1", + b"\xF2\x62": "\u1e05", + b"\xF2\x64": "\u1e0d", + b"\xF2\x65": "\u1eb9", + b"\xF2\x68": "\u1e25", + b"\xF2\x69": "\u1ecb", + b"\xF2\x6B": "\u1e33", + b"\xF2\x6C": "\u1e37", + b"\xF2\x6D": "\u1e43", + b"\xF2\x6E": "\u1e47", + b"\xF2\x6F": "\u1ecd", + b"\xF2\x72": "\u1e5b", + b"\xF2\x73": "\u1e63", + b"\xF2\x74": "\u1e6d", + b"\xF2\x75": "\u1ee5", + b"\xF2\x76": "\u1e7f", + b"\xF2\x77": "\u1e89", + b"\xF2\x79": "\u1ef5", + b"\xF2\x7A": "\u1e93", + b"\xF3\x55": "\u1e72", + b"\xF3\x75": "\u1e73", + b"\xF4\x41": "\u1e00", + b"\xF4\x61": "\u1e01", + b"\xF9\x48": "\u1e2a", + b"\xF9\x68": "\u1e2b", + } def __ansel_to_unicode(self, text): - """ Convert an ANSEL encoded text to unicode """ + """Convert an ANSEL encoded text to unicode""" buff = StringIO() error = "" @@ -1509,7 +1838,7 @@ class AnselReader(BaseReader): else: # substitute space for disallowed (control) chars error += " (%#X)" % text[0] - head = ' ' + head = " " text = text[1:] else: if text[0:2] in AnselReader.__twobyte: @@ -1523,8 +1852,10 @@ class AnselReader(BaseReader): # always consume the combiner text = text[1:] next_byte = text[0] - if next_byte < 128 and chr(next_byte) in \ - AnselReader.__printable_ascii: + if ( + next_byte < 128 + and chr(next_byte) in AnselReader.__printable_ascii + ): # consume next as well text = text[1:] # unicode: combiner follows base-char @@ -1535,7 +1866,7 @@ class AnselReader(BaseReader): continue else: error += " (%#X)" % text[0] - head = '\ufffd' # "Replacement Char" + head = "\ufffd" # "Replacement Char" text = text[1:] buff.write(head) ans = buff.getvalue() @@ -1550,25 +1881,26 @@ class AnselReader(BaseReader): BaseReader.__init__(self, ifile, "ANSEL", __add_msg) # In theory, we should have been able to skip the encode/decode from # ascii. But this way allows us to use pythons universal newline - self.ifile = TextIOWrapper(ifile, encoding='ascii', - errors='surrogateescape', newline=None) + self.ifile = TextIOWrapper( + ifile, encoding="ascii", errors="surrogateescape", newline=None + ) def readline(self): line = self.ifile.readline() - linebytes = line.encode(encoding='ascii', - errors='surrogateescape') + linebytes = line.encode(encoding="ascii", errors="surrogateescape") return self.__ansel_to_unicode(linebytes) -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # CurrentState # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class CurrentState: """ Keep track of the current state variables. """ + def __init__(self, person=None, level=0, event=None, event_ref=None): """ Initialize the object. @@ -1584,20 +1916,20 @@ class CurrentState: self.note = None self.lds_ord = None self.msg = "" - self.primary = False # _PRIMARY tag on an INDI.FAMC tag + self.primary = False # _PRIMARY tag on an INDI.FAMC tag self.filename = "" self.title = "" self.addr = None self.res = None self.source = None self.ftype = None - self.pf = None # method for parsing places + self.pf = None # method for parsing places self.location = None - self.place_fields = None # method for parsing places - self.ref = None # PersonRef - self.handle = None # - self.form = "" # Multimedia format - self.frel = None # Child relation to father + self.place_fields = None # method for parsing places + self.ref = None # PersonRef + self.handle = None # + self.form = "" # Multimedia format + self.frel = None # Child relation to father self.mrel = None self.repo = None self.attr = None @@ -1607,8 +1939,8 @@ class CurrentState: self.repo_ref = None self.place = None self.media = None - self.photo = "" # Person primary photo - self.prim = None # Photo is primary + self.photo = "" # Person primary photo + self.prim = None # Photo is primary def __getattr__(self, name): """ @@ -1623,11 +1955,11 @@ class CurrentState: self.__dict__[name] = value -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # PlaceParser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class PlaceParser: """ Provide the ability to parse GEDCOM FORM statements for places, and @@ -1636,27 +1968,28 @@ class PlaceParser: """ __field_map = { - 'addr' : Location.set_street, - 'subdivision' : Location.set_street, - 'addr1' : Location.set_street, - 'adr1' : Location.set_street, - 'street' : Location.set_street, - 'addr2' : Location.set_locality, - 'adr2' : Location.set_locality, - 'locality' : Location.set_locality, - 'neighborhood' : Location.set_locality, - 'city' : Location.set_city, - 'town' : Location.set_city, - 'village' : Location.set_city, - 'county' : Location.set_county, - 'country' : Location.set_country, - 'state' : Location.set_state, - 'state/province': Location.set_state, - 'region' : Location.set_state, - 'province' : Location.set_state, - 'area code' : Location.set_postal_code, - 'post code' : Location.set_postal_code, - 'zip code' : Location.set_postal_code, } + "addr": Location.set_street, + "subdivision": Location.set_street, + "addr1": Location.set_street, + "adr1": Location.set_street, + "street": Location.set_street, + "addr2": Location.set_locality, + "adr2": Location.set_locality, + "locality": Location.set_locality, + "neighborhood": Location.set_locality, + "city": Location.set_city, + "town": Location.set_city, + "village": Location.set_city, + "county": Location.set_county, + "country": Location.set_country, + "state": Location.set_state, + "state/province": Location.set_state, + "region": Location.set_state, + "province": Location.set_state, + "area code": Location.set_postal_code, + "post code": Location.set_postal_code, + "zip code": Location.set_postal_code, + } def __init__(self, line=None): self.parse_function = [] @@ -1671,7 +2004,7 @@ class PlaceParser: (separated by commas) to the corresponding Location method via the __field_map variable """ - for item in line.data.split(','): + for item in line.data.split(","): item = item.lower().strip() fcn = self.__field_map.get(item, lambda x, y: None) self.parse_function.append(fcn) @@ -1683,7 +2016,7 @@ class PlaceParser: function based of its position, depending on the parsed value from the FORM statement. """ - items = [item.strip() for item in text.split(',')] + items = [item.strip() for item in text.split(",")] if len(items) != len(self.parse_function): return index = 0 @@ -1692,13 +2025,15 @@ class PlaceParser: self.parse_function[index](loc, item) index += 1 - location = (loc.get_street(), - loc.get_locality(), - loc.get_parish(), - loc.get_city(), - loc.get_county(), - loc.get_state(), - loc.get_country()) + location = ( + loc.get_street(), + loc.get_locality(), + loc.get_parish(), + loc.get_city(), + loc.get_county(), + loc.get_state(), + loc.get_country(), + ) for level, name in enumerate(location): if name: @@ -1713,21 +2048,22 @@ class PlaceParser: place.set_type(PlaceType(type_num)) code = loc.get_postal_code() place.set_code(code) - if place.handle: # if handle is available, store immediately + if place.handle: # if handle is available, store immediately place_import.store_location(location, place.handle) - else: # return for storage later + else: # return for storage later return location -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # IdFinder # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class IdFinder: """ Provide method of finding the next available ID. """ + def __init__(self, keys, prefix): """ Initialize the object. @@ -1753,14 +2089,15 @@ class IdFinder: return index -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # IdMapper # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class IdMapper: - """ This class provide methods to keep track of the correspoindence between - Gedcom xrefs (@P1023@) and Gramps IDs. """ + """This class provide methods to keep track of the correspoindence between + Gedcom xrefs (@P1023@) and Gramps IDs.""" + def __init__(self, has_gid, find_next, id2user_format): self.has_gid = has_gid self.find_next = find_next @@ -1787,8 +2124,9 @@ class IdMapper: # have found it. If we had already encountered I0001 and we are # now looking for I1, it wouldn't be in self.swap, and we now # find that I0001 is in use, so we have to create a new id. - if self.has_gid(formatted_gid) or \ - (formatted_gid in list(self.swap.values())): + if self.has_gid(formatted_gid) or ( + formatted_gid in list(self.swap.values()) + ): new_val = self.find_next() while new_val in list(self.swap.values()): new_val = self.find_next() @@ -1800,30 +2138,31 @@ class IdMapper: return new_val def clean(self, gid): - """ remove '@' from start and end of xref """ + """remove '@' from start and end of xref""" temp = gid.strip() - if len(temp) > 1 and temp[0] == '@' and temp[-1] == '@': + if len(temp) > 1 and temp[0] == "@" and temp[-1] == "@": temp = temp[1:-1] return temp def map(self): - """ return the xref to GID translation map """ + """return the xref to GID translation map""" return self.swap -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # GedcomParser # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class GedcomParser(UpdateCallback): """ Performs the second pass of the GEDCOM parser, which does all the heavy lifting. """ - __TRUNC_MSG = _("Your GEDCOM file is corrupted. " - "It appears to have been truncated.") + __TRUNC_MSG = _( + "Your GEDCOM file is corrupted. " "It appears to have been truncated." + ) _EMPTY_LOC = Location().serialize() SyntaxError = "Syntax Error" @@ -1853,7 +2192,7 @@ class GedcomParser(UpdateCallback): match = SURNAME_RE.match(text) if match: - #/surname/ extra, we assume extra is given name + # /surname/ extra, we assume extra is given name names = match.groups() name.set_first_name(names[1].strip()) surn = Surname() @@ -1875,8 +2214,16 @@ class GedcomParser(UpdateCallback): name.set_first_name(text.strip()) return name - def __init__(self, dbase, ifile, filename, user, stage_one, - default_source, default_tag_format=None): + def __init__( + self, + dbase, + ifile, + filename, + user, + stage_one, + default_source, + default_tag_format=None, + ): UpdateCallback.__init__(self, user.callback) self.user = user self.set_total(stage_one.get_line_count()) @@ -1905,7 +2252,7 @@ class GedcomParser(UpdateCallback): self.func_list = [] if self.use_def_src: self.def_src = Source() - fname = os.path.basename(filename).split('\\')[-1] + fname = os.path.basename(filename).split("\\")[-1] self.def_src.set_title(_("Import from GEDCOM (%s)") % fname) if default_tag_format: name = time.strftime(default_tag_format) @@ -1926,27 +2273,33 @@ class GedcomParser(UpdateCallback): self.pid_map = IdMapper( self.dbase.has_person_gramps_id, self.dbase.find_next_person_gramps_id, - self.dbase.id2user_format) + self.dbase.id2user_format, + ) self.fid_map = IdMapper( self.dbase.has_family_gramps_id, self.dbase.find_next_family_gramps_id, - self.dbase.fid2user_format) + self.dbase.fid2user_format, + ) self.sid_map = IdMapper( self.dbase.has_source_gramps_id, self.dbase.find_next_source_gramps_id, - self.dbase.sid2user_format) + self.dbase.sid2user_format, + ) self.oid_map = IdMapper( self.dbase.has_media_gramps_id, self.dbase.find_next_media_gramps_id, - self.dbase.oid2user_format) + self.dbase.oid2user_format, + ) self.rid_map = IdMapper( self.dbase.has_repository_gramps_id, self.dbase.find_next_repository_gramps_id, - self.dbase.rid2user_format) + self.dbase.rid2user_format, + ) self.nid_map = IdMapper( self.dbase.has_note_gramps_id, self.dbase.find_next_note_gramps_id, - self.dbase.nid2user_format) + self.dbase.nid2user_format, + ) self.gid2id = {} self.oid2id = {} @@ -1974,22 +2327,23 @@ class GedcomParser(UpdateCallback): # (N.B. GEDCOM allows multiple SUBMitter records) self.subm_parse_tbl = { # +1 NAME - TOKEN_NAME : self.__subm_name, + TOKEN_NAME: self.__subm_name, # +1 <> - TOKEN_ADDR : self.__subm_addr, - TOKEN_PHON : self.__subm_phon, - TOKEN_EMAIL : self.__subm_email, - TOKEN_WWW : self.__repo_www, - TOKEN_FAX : self.__repo_fax, + TOKEN_ADDR: self.__subm_addr, + TOKEN_PHON: self.__subm_phon, + TOKEN_EMAIL: self.__subm_email, + TOKEN_WWW: self.__repo_www, + TOKEN_FAX: self.__repo_fax, # +1 <> # +1 LANG # +1 <> - TOKEN_NOTE : self.__repo_note, - TOKEN_RNOTE : self.__repo_note, + TOKEN_NOTE: self.__repo_note, + TOKEN_RNOTE: self.__repo_note, # +1 RFN # +1 RIN # +1 <> - TOKEN_CHAN : self.__repo_chan, } + TOKEN_CHAN: self.__repo_chan, + } self.func_list.append(self.subm_parse_tbl) # @@ -2021,107 +2375,109 @@ class GedcomParser(UpdateCallback): self.indi_parse_tbl = { # +1 RESN {0:1} - TOKEN_RESN : self.__person_resn, + TOKEN_RESN: self.__person_resn, # +1 <> {0:M} - TOKEN_NAME : self.__person_name, + TOKEN_NAME: self.__person_name, # +1 SEX {0:1} - TOKEN_SEX : self.__person_sex, + TOKEN_SEX: self.__person_sex, # +1 <> {0:M} - TOKEN_EVEN : self.__person_even, + TOKEN_EVEN: self.__person_even, TOKEN_GEVENT: self.__person_std_event, - TOKEN_BIRT : self.__person_birt, - TOKEN_RELI : self.__person_reli, - TOKEN_ADOP : self.__person_adop, - TOKEN_DEAT : self.__person_deat, + TOKEN_BIRT: self.__person_birt, + TOKEN_RELI: self.__person_reli, + TOKEN_ADOP: self.__person_adop, + TOKEN_DEAT: self.__person_deat, # +1 <> {0:M} # +1 AFN {0:1} - TOKEN_ATTR : self.__person_std_attr, - TOKEN_FACT : self.__person_fact, - #+1 <> {0:M} - TOKEN_BAPL : self.__person_bapl, - TOKEN_CONL : self.__person_conl, - TOKEN_ENDL : self.__person_endl, - TOKEN_SLGC : self.__person_slgc, - #+1 <> {0:M} - TOKEN_FAMC : self.__person_famc, + TOKEN_ATTR: self.__person_std_attr, + TOKEN_FACT: self.__person_fact, + # +1 <> {0:M} + TOKEN_BAPL: self.__person_bapl, + TOKEN_CONL: self.__person_conl, + TOKEN_ENDL: self.__person_endl, + TOKEN_SLGC: self.__person_slgc, + # +1 <> {0:M} + TOKEN_FAMC: self.__person_famc, # +1 <> {0:M} - TOKEN_FAMS : self.__person_fams, + TOKEN_FAMS: self.__person_fams, # +1 SUBM @@ {0:M} - TOKEN_SUBM : self.__skip_record, + TOKEN_SUBM: self.__skip_record, # +1 <> {0:M} - TOKEN_ASSO : self.__person_asso, + TOKEN_ASSO: self.__person_asso, # +1 ALIA @@ {0:M} - TOKEN_ALIA : self.__person_alt_name, + TOKEN_ALIA: self.__person_alt_name, # +1 ANCI @@ {0:M} - TOKEN_ANCI : self.__skip_record, + TOKEN_ANCI: self.__skip_record, # +1 DESI @@ {0:M} - TOKEN_DESI : self.__skip_record, + TOKEN_DESI: self.__skip_record, # +1 <> {0:M} - TOKEN_SOUR : self.__person_sour, + TOKEN_SOUR: self.__person_sour, # +1 <> {0:M} - TOKEN_OBJE : self.__person_object, + TOKEN_OBJE: self.__person_object, # +1 <> {0:M} - TOKEN_NOTE : self.__person_note, - TOKEN_RNOTE : self.__person_note, - TOKEN__COMM : self.__person_note, + TOKEN_NOTE: self.__person_note, + TOKEN_RNOTE: self.__person_note, + TOKEN__COMM: self.__person_note, # +1 RFN {0:1} - TOKEN_RFN : self.__person_attr, + TOKEN_RFN: self.__person_attr, # +1 REFN {0:M} # +2 TYPE {0:1} - TOKEN_REFN : self.__person_refn, + TOKEN_REFN: self.__person_refn, # TYPE should be below REFN, but will work here anyway - TOKEN_TYPE : self.__person_attr, + TOKEN_TYPE: self.__person_attr, # +1 RIN {0:1} - TOKEN_RIN : self.__person_attr, + TOKEN_RIN: self.__person_attr, # +1 <> {0:1} - TOKEN_CHAN : self.__person_chan, + TOKEN_CHAN: self.__person_chan, # The following tags are not part of Gedcom spec but are commonly # found here anyway - TOKEN_ADDR : self.__person_addr, - TOKEN_PHON : self.__person_phon, - TOKEN_FAX : self.__person_fax, - TOKEN_EMAIL : self.__person_email, - TOKEN_WWW : self.__person_www, - TOKEN__TODO : self.__skip_record, - TOKEN_TITL : self.__person_titl, - TOKEN__PHOTO: self.__person_photo, } + TOKEN_ADDR: self.__person_addr, + TOKEN_PHON: self.__person_phon, + TOKEN_FAX: self.__person_fax, + TOKEN_EMAIL: self.__person_email, + TOKEN_WWW: self.__person_www, + TOKEN__TODO: self.__skip_record, + TOKEN_TITL: self.__person_titl, + TOKEN__PHOTO: self.__person_photo, + } self.func_list.append(self.indi_parse_tbl) self.name_parse_tbl = { # +1 NPFX {0:1} - TOKEN_NPFX : self.__name_npfx, + TOKEN_NPFX: self.__name_npfx, # +1 GIVN {0:1} - TOKEN_GIVN : self.__name_givn, + TOKEN_GIVN: self.__name_givn, # NICK {0:1} TOKEN_NICK : self.__name_nick, # _RUFNAME {0:1} TOKEN__CALLNAME: self.__name_call, # +1 SPFX {0:1} - TOKEN_SURN : self.__name_surn, + TOKEN_SURN: self.__name_surn, # +1 NSFX {0:1} - TOKEN_NSFX : self.__name_nsfx, + TOKEN_NSFX: self.__name_nsfx, # +1 <> {0:M} - TOKEN_SOUR : self.__name_sour, + TOKEN_SOUR: self.__name_sour, # +1 <> {0:M} - TOKEN_NOTE : self.__name_note, - TOKEN_RNOTE : self.__name_note, + TOKEN_NOTE: self.__name_note, + TOKEN_RNOTE: self.__name_note, # Extensions - TOKEN_ALIA : self.__name_alia, - TOKEN__MARNM : self.__name_marnm, - TOKEN__MAR : self.__name_marnm, # Generated by geni.com - TOKEN__MARN : self.__name_marnm, # Gen'd by BROSKEEP 6.1.31 WIN - TOKEN__AKA : self.__name_aka, # PAF and AncestQuest - TOKEN_TYPE : self.__name_type, # This is legal GEDCOM 5.5.1 - TOKEN_BIRT : self.__ignore, - TOKEN_DATE : self.__name_date, + TOKEN_ALIA: self.__name_alia, + TOKEN__MARNM: self.__name_marnm, + TOKEN__MAR: self.__name_marnm, # Generated by geni.com + TOKEN__MARN: self.__name_marnm, # Gen'd by BROSKEEP 6.1.31 WIN + TOKEN__AKA: self.__name_aka, # PAF and AncestQuest + TOKEN_TYPE: self.__name_type, # This is legal GEDCOM 5.5.1 + TOKEN_BIRT: self.__ignore, + TOKEN_DATE: self.__name_date, # This handles date as a subsidiary of "1 ALIA" which might be used # by Family Tree Maker and Reunion, and by cheating (handling a # lower level from the current parse table) handles date as # subsidiary to "2 _MARN", "2 _AKAN" and "2 _ADPN" which has been # found in Brother's keeper. - TOKEN__ADPN : self.__name_adpn, } + TOKEN__ADPN: self.__name_adpn, + } self.func_list.append(self.name_parse_tbl) # @@ -2137,162 +2493,163 @@ class GedcomParser(UpdateCallback): # +1 <> {0:1} self.repo_parse_tbl = { - TOKEN_NAME : self.__repo_name, - TOKEN_ADDR : self.__repo_addr, - TOKEN_RIN : self.__ignore, - TOKEN_NOTE : self.__repo_note, - TOKEN_RNOTE : self.__repo_note, - TOKEN_CHAN : self.__repo_chan, - TOKEN_PHON : self.__repo_phon, - TOKEN_EMAIL : self.__repo_email, - TOKEN_WWW : self.__repo_www, - TOKEN_FAX : self.__repo_fax, } + TOKEN_NAME: self.__repo_name, + TOKEN_ADDR: self.__repo_addr, + TOKEN_RIN: self.__ignore, + TOKEN_NOTE: self.__repo_note, + TOKEN_RNOTE: self.__repo_note, + TOKEN_CHAN: self.__repo_chan, + TOKEN_PHON: self.__repo_phon, + TOKEN_EMAIL: self.__repo_email, + TOKEN_WWW: self.__repo_www, + TOKEN_FAX: self.__repo_fax, + } self.func_list.append(self.repo_parse_tbl) self.event_parse_tbl = { # n TYPE {0:1} - TOKEN_TYPE : self.__event_type, + TOKEN_TYPE: self.__event_type, # n DATE {0:1} p.*/* - TOKEN_DATE : self.__event_date, + TOKEN_DATE: self.__event_date, # n <> {0:1} p.* - TOKEN_PLAC : self.__event_place, + TOKEN_PLAC: self.__event_place, # n <> {0:1} p.* - TOKEN_ADDR : self.__event_addr, + TOKEN_ADDR: self.__event_addr, # n AGE {0:1} p.* - TOKEN_AGE : self.__event_age, + TOKEN_AGE: self.__event_age, # n AGNC {0:1} p.* - TOKEN_AGNC : self.__event_agnc, + TOKEN_AGNC: self.__event_agnc, # n CAUS {0:1} p.* - TOKEN_CAUS : self.__event_cause, + TOKEN_CAUS: self.__event_cause, # n <> {0:M} p.* - TOKEN_SOUR : self.__event_source, + TOKEN_SOUR: self.__event_source, # n <> {0:M} p.*, * - TOKEN_OBJE : self.__event_object, + TOKEN_OBJE: self.__event_object, # n <> {0:M} p. - TOKEN_NOTE : self.__event_inline_note, - TOKEN_RNOTE : self.__event_note, + TOKEN_NOTE: self.__event_inline_note, + TOKEN_RNOTE: self.__event_note, # Other - TOKEN__PRIV : self.__event_privacy, - TOKEN_OFFI : self.__event_note, - TOKEN_PHON : self.__event_phon, - TOKEN__GODP : self.__event_witness, - TOKEN__WITN : self.__event_witness, - TOKEN__WTN : self.__event_witness, - TOKEN_RELI : self.__ignore, + TOKEN__PRIV: self.__event_privacy, + TOKEN_OFFI: self.__event_note, + TOKEN_PHON: self.__event_phon, + TOKEN__GODP: self.__event_witness, + TOKEN__WITN: self.__event_witness, + TOKEN__WTN: self.__event_witness, + TOKEN_RELI: self.__ignore, # Not legal, but inserted by PhpGedView - TOKEN_TIME : self.__event_time, - TOKEN_ASSO : self.__ignore, - TOKEN_IGNORE : self.__ignore, - TOKEN_STAT : self.__ignore, - TOKEN_TEMP : self.__ignore, - TOKEN_HUSB : self.__event_husb, - TOKEN_WIFE : self.__event_wife, - TOKEN_FAMC : self.__person_birth_famc, + TOKEN_TIME: self.__event_time, + TOKEN_ASSO: self.__ignore, + TOKEN_IGNORE: self.__ignore, + TOKEN_STAT: self.__ignore, + TOKEN_TEMP: self.__ignore, + TOKEN_HUSB: self.__event_husb, + TOKEN_WIFE: self.__event_wife, + TOKEN_FAMC: self.__person_birth_famc, # Not legal, but inserted by Ultimate Family Tree - TOKEN_CHAN : self.__ignore, - TOKEN_QUAY : self.__ignore, + TOKEN_CHAN: self.__ignore, + TOKEN_QUAY: self.__ignore, # Not legal, but inserted by FamilyTreeBuilder - TOKEN_RIN : self.__event_rin, - TOKEN_ATTR : self.__event_attr, # FTB for _UID - TOKEN_EMAIL : self.__event_email, # FTB for RESI events - TOKEN_WWW : self.__event_www, # FTB for RESI events - TOKEN_FAX : self.__event_fax, # legal... + TOKEN_RIN: self.__event_rin, + TOKEN_ATTR: self.__event_attr, # FTB for _UID + TOKEN_EMAIL: self.__event_email, # FTB for RESI events + TOKEN_WWW: self.__event_www, # FTB for RESI events + TOKEN_FAX: self.__event_fax, # legal... } self.func_list.append(self.event_parse_tbl) self.adopt_parse_tbl = { - TOKEN_TYPE : self.__event_type, - TOKEN__PRIV : self.__event_privacy, - TOKEN_DATE : self.__event_date, - TOKEN_SOUR : self.__event_source, - TOKEN_PLAC : self.__event_place, - TOKEN_ADDR : self.__event_addr, - TOKEN_PHON : self.__event_phon, - TOKEN_CAUS : self.__event_cause, - TOKEN_AGNC : self.__event_agnc, - TOKEN_AGE : self.__event_age, - TOKEN_NOTE : self.__event_note, - TOKEN_RNOTE : self.__event_note, - TOKEN_OFFI : self.__event_note, - TOKEN__GODP : self.__event_witness, - TOKEN__WITN : self.__event_witness, - TOKEN__WTN : self.__event_witness, - TOKEN_RELI : self.__ignore, - TOKEN_TIME : self.__ignore, - TOKEN_ASSO : self.__ignore, - TOKEN_IGNORE : self.__ignore, - TOKEN_STAT : self.__ignore, - TOKEN_TEMP : self.__ignore, - TOKEN_OBJE : self.__event_object, - TOKEN_FAMC : self.__person_adopt_famc, + TOKEN_TYPE: self.__event_type, + TOKEN__PRIV: self.__event_privacy, + TOKEN_DATE: self.__event_date, + TOKEN_SOUR: self.__event_source, + TOKEN_PLAC: self.__event_place, + TOKEN_ADDR: self.__event_addr, + TOKEN_PHON: self.__event_phon, + TOKEN_CAUS: self.__event_cause, + TOKEN_AGNC: self.__event_agnc, + TOKEN_AGE: self.__event_age, + TOKEN_NOTE: self.__event_note, + TOKEN_RNOTE: self.__event_note, + TOKEN_OFFI: self.__event_note, + TOKEN__GODP: self.__event_witness, + TOKEN__WITN: self.__event_witness, + TOKEN__WTN: self.__event_witness, + TOKEN_RELI: self.__ignore, + TOKEN_TIME: self.__ignore, + TOKEN_ASSO: self.__ignore, + TOKEN_IGNORE: self.__ignore, + TOKEN_STAT: self.__ignore, + TOKEN_TEMP: self.__ignore, + TOKEN_OBJE: self.__event_object, + TOKEN_FAMC: self.__person_adopt_famc, # Not legal, but inserted by Ultimate Family Tree - TOKEN_CHAN : self.__ignore, - TOKEN_QUAY : self.__ignore, + TOKEN_CHAN: self.__ignore, + TOKEN_QUAY: self.__ignore, } self.func_list.append(self.adopt_parse_tbl) self.famc_parse_tbl = { # n FAMC @@ {1:1} # +1 PEDI {0:1} p.* - TOKEN_PEDI : self.__person_famc_pedi, + TOKEN_PEDI: self.__person_famc_pedi, # +1 _FREL {0:1} non-standard - TOKEN__FREL : self.__person_famc_frel, + TOKEN__FREL: self.__person_famc_frel, # +1 _MREL {0:1} non-standard - TOKEN__MREL : self.__person_famc_mrel, + TOKEN__MREL: self.__person_famc_mrel, # +1 <> {0:M} p.* - TOKEN_NOTE : self.__person_famc_note, - TOKEN_RNOTE : self.__person_famc_note, + TOKEN_NOTE: self.__person_famc_note, + TOKEN_RNOTE: self.__person_famc_note, # Extras TOKEN__PRIMARY: self.__person_famc_primary, - TOKEN_SOUR : self.__person_famc_sour, + TOKEN_SOUR: self.__person_famc_sour, # GEDit - TOKEN_STAT : self.__ignore, + TOKEN_STAT: self.__ignore, } self.func_list.append(self.famc_parse_tbl) self.person_fact_parse_tbl = { - TOKEN_TYPE : self.__person_fact_type, - TOKEN_SOUR : self.__person_attr_source, - TOKEN_NOTE : self.__person_attr_note, - TOKEN_RNOTE : self.__person_attr_note, + TOKEN_TYPE: self.__person_fact_type, + TOKEN_SOUR: self.__person_attr_source, + TOKEN_NOTE: self.__person_attr_note, + TOKEN_RNOTE: self.__person_attr_note, } self.func_list.append(self.person_fact_parse_tbl) self.person_attr_parse_tbl = { - TOKEN_TYPE : self.__person_attr_type, - TOKEN_CAUS : self.__ignore, - TOKEN_DATE : self.__ignore, - TOKEN_TIME : self.__ignore, - TOKEN_ADDR : self.__ignore, - TOKEN_IGNORE : self.__ignore, - TOKEN_STAT : self.__ignore, - TOKEN_TEMP : self.__ignore, - TOKEN_OBJE : self.__ignore, - TOKEN_SOUR : self.__person_attr_source, - TOKEN_PLAC : self.__person_attr_place, - TOKEN_NOTE : self.__person_attr_note, - TOKEN_RNOTE : self.__person_attr_note, + TOKEN_TYPE: self.__person_attr_type, + TOKEN_CAUS: self.__ignore, + TOKEN_DATE: self.__ignore, + TOKEN_TIME: self.__ignore, + TOKEN_ADDR: self.__ignore, + TOKEN_IGNORE: self.__ignore, + TOKEN_STAT: self.__ignore, + TOKEN_TEMP: self.__ignore, + TOKEN_OBJE: self.__ignore, + TOKEN_SOUR: self.__person_attr_source, + TOKEN_PLAC: self.__person_attr_place, + TOKEN_NOTE: self.__person_attr_note, + TOKEN_RNOTE: self.__person_attr_note, } self.func_list.append(self.person_attr_parse_tbl) self.lds_parse_tbl = { - TOKEN_TEMP : self.__lds_temple, - TOKEN_DATE : self.__lds_date, - TOKEN_FAMC : self.__lds_famc, - TOKEN_FORM : self.__lds_form, - TOKEN_PLAC : self.__lds_plac, - TOKEN_SOUR : self.__lds_sour, - TOKEN_NOTE : self.__lds_note, - TOKEN_RNOTE : self.__lds_note, - TOKEN_STAT : self.__lds_stat, + TOKEN_TEMP: self.__lds_temple, + TOKEN_DATE: self.__lds_date, + TOKEN_FAMC: self.__lds_famc, + TOKEN_FORM: self.__lds_form, + TOKEN_PLAC: self.__lds_plac, + TOKEN_SOUR: self.__lds_sour, + TOKEN_NOTE: self.__lds_note, + TOKEN_RNOTE: self.__lds_note, + TOKEN_STAT: self.__lds_stat, } self.func_list.append(self.lds_parse_tbl) self.asso_parse_tbl = { - TOKEN_RELA : self.__person_asso_rela, - TOKEN_SOUR : self.__person_asso_sour, - TOKEN_NOTE : self.__person_asso_note, - TOKEN_RNOTE : self.__person_asso_note, + TOKEN_RELA: self.__person_asso_rela, + TOKEN_SOUR: self.__person_asso_sour, + TOKEN_NOTE: self.__person_asso_note, + TOKEN_RNOTE: self.__person_asso_note, } self.func_list.append(self.asso_parse_tbl) @@ -2316,33 +2673,33 @@ class GedcomParser(UpdateCallback): self.func_list.append(self.citation_parse_tbl) self.media_parse_tbl = { - TOKEN_FORM : self.__media_ref_form, - TOKEN_MEDI : self.__media_ref_medi, # v5.5.1 - TOKEN_TITL : self.__media_ref_titl, - TOKEN_FILE : self.__media_ref_file, - TOKEN_NOTE : self.__obje_note, # illegal, but often there - TOKEN_RNOTE : self.__obje_note, # illegal, but often there - TOKEN__PRIM : self.__media_ref_prim, # LFT etc. - TOKEN_IGNORE : self.__ignore, + TOKEN_FORM: self.__media_ref_form, + TOKEN_MEDI: self.__media_ref_medi, # v5.5.1 + TOKEN_TITL: self.__media_ref_titl, + TOKEN_FILE: self.__media_ref_file, + TOKEN_NOTE: self.__obje_note, # illegal, but often there + TOKEN_RNOTE: self.__obje_note, # illegal, but often there + TOKEN__PRIM: self.__media_ref_prim, # LFT etc. + TOKEN_IGNORE: self.__ignore, } self.func_list.append(self.media_parse_tbl) self.parse_loc_tbl = { - TOKEN_ADR1 : self.__location_adr1, - TOKEN_ADR2 : self.__location_adr2, - TOKEN_CITY : self.__location_city, - TOKEN_STAE : self.__location_stae, - TOKEN_POST : self.__location_post, - TOKEN_CTRY : self.__location_ctry, + TOKEN_ADR1: self.__location_adr1, + TOKEN_ADR2: self.__location_adr2, + TOKEN_CITY: self.__location_city, + TOKEN_STAE: self.__location_stae, + TOKEN_POST: self.__location_post, + TOKEN_CTRY: self.__location_ctry, # Not legal GEDCOM - not clear why these are included at this level - TOKEN_ADDR : self.__ignore, - TOKEN_DATE : self.__ignore, # there is nowhere to put a date - TOKEN_NOTE : self.__location_note, - TOKEN_RNOTE : self.__location_note, - TOKEN__LOC : self.__ignore, - TOKEN__NAME : self.__ignore, - TOKEN_PHON : self.__location_phone, - TOKEN_IGNORE : self.__ignore, + TOKEN_ADDR: self.__ignore, + TOKEN_DATE: self.__ignore, # there is nowhere to put a date + TOKEN_NOTE: self.__location_note, + TOKEN_RNOTE: self.__location_note, + TOKEN__LOC: self.__ignore, + TOKEN__NAME: self.__ignore, + TOKEN_PHON: self.__location_phone, + TOKEN_IGNORE: self.__ignore, } self.func_list.append(self.parse_loc_tbl) @@ -2366,46 +2723,46 @@ class GedcomParser(UpdateCallback): self.family_func = { # +1 <> {0:M} - TOKEN_GEVENT : self.__family_std_event, - TOKEN_EVEN : self.__fam_even, + TOKEN_GEVENT: self.__family_std_event, + TOKEN_EVEN: self.__fam_even, # +1 HUSB @@ {0:1} - TOKEN_HUSB : self.__family_husb, + TOKEN_HUSB: self.__family_husb, # +1 WIFE @@ {0:1} - TOKEN_WIFE : self.__family_wife, + TOKEN_WIFE: self.__family_wife, # +1 CHIL @@ {0:M} - TOKEN_CHIL : self.__family_chil, + TOKEN_CHIL: self.__family_chil, # +1 NCHI {0:1} # +1 SUBM @@ {0:M} # +1 <> {0:M} - TOKEN_SLGS : self.__family_slgs, + TOKEN_SLGS: self.__family_slgs, # +1 <> {0:M} - TOKEN_SOUR : self.__family_source, + TOKEN_SOUR: self.__family_source, # +1 <> {0:M} - TOKEN_OBJE : self.__family_object, + TOKEN_OBJE: self.__family_object, # +1 <> {0:M} - TOKEN__COMM : self.__family_comm, - TOKEN_NOTE : self.__family_note, - TOKEN_RNOTE : self.__family_note, + TOKEN__COMM: self.__family_comm, + TOKEN_NOTE: self.__family_note, + TOKEN_RNOTE: self.__family_note, # +1 REFN {0:M} - TOKEN_REFN : self.__family_refn, + TOKEN_REFN: self.__family_refn, # TYPE should be below REFN, but will work here anyway - TOKEN_TYPE : self.__family_cust_attr, + TOKEN_TYPE: self.__family_cust_attr, # +1 RIN {0:1} # +1 <> {0:1} - TOKEN_CHAN : self.__family_chan, - TOKEN_ENDL : self.__ignore, - TOKEN_ADDR : self.__ignore, - TOKEN_RIN : self.__family_cust_attr, - TOKEN_SUBM : self.__ignore, - TOKEN_ATTR : self.__family_attr, + TOKEN_CHAN: self.__family_chan, + TOKEN_ENDL: self.__ignore, + TOKEN_ADDR: self.__ignore, + TOKEN_RIN: self.__family_cust_attr, + TOKEN_SUBM: self.__ignore, + TOKEN_ATTR: self.__family_attr, } self.func_list.append(self.family_func) self.family_rel_tbl = { - TOKEN__FREL : self.__family_frel, - TOKEN__MREL : self.__family_mrel, - TOKEN_ADOP : self.__family_adopt, - TOKEN__STAT : self.__family_stat, + TOKEN__FREL: self.__family_frel, + TOKEN__MREL: self.__family_mrel, + TOKEN_ADOP: self.__family_adopt, + TOKEN__STAT: self.__family_stat, } self.func_list.append(self.family_rel_tbl) @@ -2437,26 +2794,26 @@ class GedcomParser(UpdateCallback): # +1 <> {0:1} self.source_func = { - TOKEN_TITL : self.__source_title, - TOKEN_TAXT : self.__source_taxt_peri, - TOKEN_PERI : self.__source_taxt_peri, - TOKEN_AUTH : self.__source_auth, - TOKEN_PUBL : self.__source_publ, - TOKEN_NOTE : self.__source_note, - TOKEN_RNOTE : self.__source_note, - TOKEN_TEXT : self.__source_text, - TOKEN_ABBR : self.__source_abbr, - TOKEN_REFN : self.__source_attr, - TOKEN_RIN : self.__source_attr, - TOKEN_REPO : self.__source_repo, - TOKEN_OBJE : self.__source_object, - TOKEN_CHAN : self.__source_chan, - TOKEN_MEDI : self.__source_attr, - TOKEN__NAME : self.__source_attr, - TOKEN_DATA : self.__ignore, + TOKEN_TITL: self.__source_title, + TOKEN_TAXT: self.__source_taxt_peri, + TOKEN_PERI: self.__source_taxt_peri, + TOKEN_AUTH: self.__source_auth, + TOKEN_PUBL: self.__source_publ, + TOKEN_NOTE: self.__source_note, + TOKEN_RNOTE: self.__source_note, + TOKEN_TEXT: self.__source_text, + TOKEN_ABBR: self.__source_abbr, + TOKEN_REFN: self.__source_attr, + TOKEN_RIN: self.__source_attr, + TOKEN_REPO: self.__source_repo, + TOKEN_OBJE: self.__source_object, + TOKEN_CHAN: self.__source_chan, + TOKEN_MEDI: self.__source_attr, + TOKEN__NAME: self.__source_attr, + TOKEN_DATA: self.__ignore, # TYPE should be below REFN, but will work here anyway - TOKEN_TYPE : self.__source_attr, - TOKEN_CALN : self.__ignore, + TOKEN_TYPE: self.__source_attr, + TOKEN_CALN: self.__ignore, # not legal, but Ultimate Family Tree does this TOKEN_DATE : self.__ignore, TOKEN_IGNORE : self.__ignore, @@ -2495,99 +2852,99 @@ class GedcomParser(UpdateCallback): # +1 <> {0:1} self.obje_func = { - TOKEN_FORM : self.__obje_form, - TOKEN_TYPE : self.__obje_type, # v5.5.1 - TOKEN_TITL : self.__obje_title, - TOKEN_FILE : self.__obje_file, # de-facto extension - TOKEN_TEXT : self.__obje_text, # FTM extension - TOKEN__TEXT : self.__obje_text, # FTM 2017 extension - TOKEN_DATE : self.__obje_date, # FTM extension - TOKEN__DATE : self.__obje_date, # FTM 2017 extension - TOKEN_NOTE : self.__obje_note, - TOKEN_RNOTE : self.__obje_note, - TOKEN_SOUR : self.__obje_sour, - TOKEN_BLOB : self.__ignore, # v5.5.1 deprecated - TOKEN_REFN : self.__obje_refn, - TOKEN_RIN : self.__obje_rin, - TOKEN_CHAN : self.__obje_chan, + TOKEN_FORM: self.__obje_form, + TOKEN_TYPE: self.__obje_type, # v5.5.1 + TOKEN_TITL: self.__obje_title, + TOKEN_FILE: self.__obje_file, # de-facto extension + TOKEN_TEXT: self.__obje_text, # FTM extension + TOKEN__TEXT: self.__obje_text, # FTM 2017 extension + TOKEN_DATE: self.__obje_date, # FTM extension + TOKEN__DATE: self.__obje_date, # FTM 2017 extension + TOKEN_NOTE: self.__obje_note, + TOKEN_RNOTE: self.__obje_note, + TOKEN_SOUR: self.__obje_sour, + TOKEN_BLOB: self.__ignore, # v5.5.1 deprecated + TOKEN_REFN: self.__obje_refn, + TOKEN_RIN: self.__obje_rin, + TOKEN_CHAN: self.__obje_chan, } self.func_list.append(self.obje_func) self.parse_addr_tbl = { - TOKEN_DATE : self.__address_date, - TOKEN_ADR1 : self.__address_adr1, - TOKEN_ADR2 : self.__address_adr2, - TOKEN_CITY : self.__address_city, - TOKEN_STAE : self.__address_state, - TOKEN_POST : self.__address_post, - TOKEN_CTRY : self.__address_country, - TOKEN_PHON : self.__ignore, - TOKEN_SOUR : self.__address_sour, - TOKEN_NOTE : self.__address_note, - TOKEN_RNOTE : self.__address_note, - TOKEN__LOC : self.__ignore, - TOKEN__NAME : self.__ignore, - TOKEN_IGNORE : self.__ignore, - TOKEN_TYPE : self.__ignore, - TOKEN_CAUS : self.__ignore, + TOKEN_DATE: self.__address_date, + TOKEN_ADR1: self.__address_adr1, + TOKEN_ADR2: self.__address_adr2, + TOKEN_CITY: self.__address_city, + TOKEN_STAE: self.__address_state, + TOKEN_POST: self.__address_post, + TOKEN_CTRY: self.__address_country, + TOKEN_PHON: self.__ignore, + TOKEN_SOUR: self.__address_sour, + TOKEN_NOTE: self.__address_note, + TOKEN_RNOTE: self.__address_note, + TOKEN__LOC: self.__ignore, + TOKEN__NAME: self.__ignore, + TOKEN_IGNORE: self.__ignore, + TOKEN_TYPE: self.__ignore, + TOKEN_CAUS: self.__ignore, } self.func_list.append(self.parse_addr_tbl) self.event_cause_tbl = { - TOKEN_SOUR : self.__event_cause_source, + TOKEN_SOUR: self.__event_cause_source, } self.func_list.append(self.event_cause_tbl) self.event_place_map = { - TOKEN_NOTE : self.__event_place_note, - TOKEN_RNOTE : self.__event_place_note, - TOKEN_FORM : self.__event_place_form, + TOKEN_NOTE: self.__event_place_note, + TOKEN_RNOTE: self.__event_place_note, + TOKEN_FORM: self.__event_place_form, # Not legal. - TOKEN_OBJE : self.__event_place_object, - TOKEN_SOUR : self.__event_place_sour, - TOKEN__LOC : self.__ignore, - TOKEN_MAP : self.__place_map, + TOKEN_OBJE: self.__event_place_object, + TOKEN_SOUR: self.__event_place_sour, + TOKEN__LOC: self.__ignore, + TOKEN_MAP: self.__place_map, # Not legal, but generated by Ultimate Family Tree - TOKEN_QUAY : self.__ignore, + TOKEN_QUAY: self.__ignore, } self.func_list.append(self.event_place_map) self.place_map_tbl = { - TOKEN_LATI : self.__place_lati, - TOKEN_LONG : self.__place_long, + TOKEN_LATI: self.__place_lati, + TOKEN_LONG: self.__place_long, } self.func_list.append(self.place_map_tbl) self.repo_ref_tbl = { - TOKEN_CALN : self.__repo_ref_call, - TOKEN_NOTE : self.__repo_ref_note, - TOKEN_RNOTE : self.__repo_ref_note, - TOKEN_MEDI : self.__repo_ref_medi, - TOKEN_IGNORE : self.__ignore, + TOKEN_CALN: self.__repo_ref_call, + TOKEN_NOTE: self.__repo_ref_note, + TOKEN_RNOTE: self.__repo_ref_note, + TOKEN_MEDI: self.__repo_ref_medi, + TOKEN_IGNORE: self.__ignore, } self.func_list.append(self.repo_ref_tbl) self.parse_person_adopt = { - TOKEN_ADOP : self.__person_adopt_famc_adopt, + TOKEN_ADOP: self.__person_adopt_famc_adopt, } self.func_list.append(self.parse_person_adopt) self.opt_note_tbl = { - TOKEN_RNOTE : self.__optional_note, - TOKEN_NOTE : self.__optional_note, + TOKEN_RNOTE: self.__optional_note, + TOKEN_NOTE: self.__optional_note, } self.func_list.append(self.opt_note_tbl) self.citation_data_tbl = { - TOKEN_DATE : self.__citation_data_date, - TOKEN_TEXT : self.__citation_data_text, - TOKEN_RNOTE : self.__citation_data_note, - TOKEN_NOTE : self.__citation_data_note, + TOKEN_DATE: self.__citation_data_date, + TOKEN_TEXT: self.__citation_data_text, + TOKEN_RNOTE: self.__citation_data_note, + TOKEN_NOTE: self.__citation_data_note, } self.func_list.append(self.citation_data_tbl) self.citation_even_tbl = { - TOKEN_ROLE : self.__citation_even_role, + TOKEN_ROLE: self.__citation_even_role, } self.func_list.append(self.citation_even_tbl) @@ -2626,57 +2983,57 @@ class GedcomParser(UpdateCallback): # DESTination of ANSTFILE or TempleReady. self.head_parse_tbl = { - TOKEN_SOUR : self.__header_sour, - TOKEN_NAME : self.__header_sour_name, # This should be below SOUR - TOKEN_VERS : self.__header_sour_vers, # This should be below SOUR - TOKEN_FILE : self.__header_file, - TOKEN_COPR : self.__header_copr, - TOKEN_SUBM : self.__header_subm, - TOKEN_CORP : self.__ignore, # This should be below SOUR - TOKEN_DATA : self.__ignore, # This should be below SOUR - TOKEN_SUBN : self.__header_subn, - TOKEN_LANG : self.__header_lang, - TOKEN_TIME : self.__ignore, # This should be below DATE - TOKEN_DEST : self.__header_dest, - TOKEN_CHAR : self.__header_char, - TOKEN_GEDC : self.__header_gedc, - TOKEN_PLAC : self.__header_plac, - TOKEN_DATE : self.__header_date, - TOKEN_NOTE : self.__header_note, + TOKEN_SOUR: self.__header_sour, + TOKEN_NAME: self.__header_sour_name, # This should be below SOUR + TOKEN_VERS: self.__header_sour_vers, # This should be below SOUR + TOKEN_FILE: self.__header_file, + TOKEN_COPR: self.__header_copr, + TOKEN_SUBM: self.__header_subm, + TOKEN_CORP: self.__ignore, # This should be below SOUR + TOKEN_DATA: self.__ignore, # This should be below SOUR + TOKEN_SUBN: self.__header_subn, + TOKEN_LANG: self.__header_lang, + TOKEN_TIME: self.__ignore, # This should be below DATE + TOKEN_DEST: self.__header_dest, + TOKEN_CHAR: self.__header_char, + TOKEN_GEDC: self.__header_gedc, + TOKEN_PLAC: self.__header_plac, + TOKEN_DATE: self.__header_date, + TOKEN_NOTE: self.__header_note, TOKEN__SCHEMA: self.__ignore, } self.func_list.append(self.head_parse_tbl) self.header_sour_parse_tbl = { - TOKEN_VERS : self.__header_sour_vers, - TOKEN_NAME : self.__header_sour_name, - TOKEN_CORP : self.__header_sour_corp, - TOKEN_DATA : self.__header_sour_data, + TOKEN_VERS: self.__header_sour_vers, + TOKEN_NAME: self.__header_sour_name, + TOKEN_CORP: self.__header_sour_corp, + TOKEN_DATA: self.__header_sour_data, } self.func_list.append(self.header_sour_parse_tbl) self.header_sour_data = { - TOKEN_DATE : self.__header_sour_date, - TOKEN_COPR : self.__header_sour_copr, + TOKEN_DATE: self.__header_sour_date, + TOKEN_COPR: self.__header_sour_copr, } self.func_list.append(self.header_sour_data) self.header_corp_addr = { - TOKEN_ADDR : self.__repo_addr, - TOKEN_PHON : self.__repo_phon, - TOKEN_FAX : self.__repo_fax, - TOKEN_WWW : self.__repo_www, - TOKEN_EMAIL : self.__repo_email, + TOKEN_ADDR: self.__repo_addr, + TOKEN_PHON: self.__repo_phon, + TOKEN_FAX: self.__repo_fax, + TOKEN_WWW: self.__repo_www, + TOKEN_EMAIL: self.__repo_email, } self.func_list.append(self.header_corp_addr) self.header_subm = { - TOKEN_NAME : self.__header_subm_name, + TOKEN_NAME: self.__header_subm_name, } self.func_list.append(self.header_subm) self.place_form = { - TOKEN_FORM : self.__place_form, + TOKEN_FORM: self.__place_form, } self.func_list.append(self.place_form) @@ -2692,10 +3049,10 @@ class GedcomParser(UpdateCallback): # +1 <> {0:1} self.note_parse_tbl = { - TOKEN_SOUR : self.__ignore, - TOKEN_REFN : self.__ignore, - TOKEN_RIN : self.__ignore, - TOKEN_CHAN : self.__note_chan, + TOKEN_SOUR: self.__ignore, + TOKEN_REFN: self.__ignore, + TOKEN_RIN: self.__ignore, + TOKEN_CHAN: self.__note_chan, } self.func_list.append(self.note_parse_tbl) @@ -2746,8 +3103,7 @@ class GedcomParser(UpdateCallback): 0 TRLR {1:1} """ - with DbTxn(_("GEDCOM import"), self.dbase, - not use_trans) as self.trans: + with DbTxn(_("GEDCOM import"), self.dbase, not use_trans) as self.trans: self.dbase.disable_signals() self.__parse_header_head() @@ -2776,14 +3132,16 @@ class GedcomParser(UpdateCallback): if self.number_of_errors == 0: message = _("GEDCOM import report: No errors detected") else: - message = _("GEDCOM import report: %s errors detected") % \ - self.number_of_errors - if hasattr(self.user.uistate, 'window'): + message = ( + _("GEDCOM import report: %s errors detected") % self.number_of_errors + ) + if hasattr(self.user.uistate, "window"): parent_window = self.user.uistate.window else: parent_window = None - self.user.info(message, "".join(self.errors), - parent=parent_window, monospaced=True) + self.user.info( + message, "".join(self.errors), parent=parent_window, monospaced=True + ) def __clean_up(self): """ @@ -2964,15 +3322,17 @@ class GedcomParser(UpdateCallback): for place_handle in self.place_names[title]: place = self.dbase.get_place_from_handle(place_handle) if place.get_title() == title: - if self.__loc_is_empty(location) and \ - self.__loc_is_empty(self.__get_first_loc(place)) and \ - place.get_placeref_list() == placeref_list: + if ( + self.__loc_is_empty(location) + and self.__loc_is_empty(self.__get_first_loc(place)) + and place.get_placeref_list() == placeref_list + ): return place - elif (not self.__loc_is_empty(location) and - not self.__loc_is_empty(self.__get_first_loc(place)) and - self.__get_first_loc(place).is_equivalent(location) == - IDENTICAL) and \ - place.get_placeref_list() == placeref_list: + elif ( + not self.__loc_is_empty(location) + and not self.__loc_is_empty(self.__get_first_loc(place)) + and self.__get_first_loc(place).is_equivalent(location) == IDENTICAL + ) and place.get_placeref_list() == placeref_list: return place return None @@ -2989,14 +3349,17 @@ class GedcomParser(UpdateCallback): """ if sub_state.place: # see whether this place already exists - place = self.__find_place(sub_state.place.get_title(), - self.__get_first_loc(sub_state.place), - sub_state.place.get_placeref_list()) + place = self.__find_place( + sub_state.place.get_title(), + self.__get_first_loc(sub_state.place), + sub_state.place.get_placeref_list(), + ) if place is None: place = sub_state.place place_title = _pd.display(self.dbase, place) - location = sub_state.pf.load_place(self.place_import, place, - place_title) + location = sub_state.pf.load_place( + self.place_import, place, place_title + ) self.dbase.add_place(place, self.trans) # if 'location was created, then store it, now that we have a # handle. @@ -3007,8 +3370,9 @@ class GedcomParser(UpdateCallback): else: place.merge(sub_state.place) place_title = _pd.display(self.dbase, place) - location = sub_state.pf.load_place(self.place_import, place, - place_title) + location = sub_state.pf.load_place( + self.place_import, place, place_title + ) self.dbase.commit_place(place, self.trans) if location: self.place_import.store_location(location, place.handle) @@ -3016,7 +3380,7 @@ class GedcomParser(UpdateCallback): def __find_file(self, fullname, altpath): # try to find the media file - fullname = fullname.replace('\\', os.path.sep) + fullname = fullname.replace("\\", os.path.sep) try: if os.path.isfile(fullname): @@ -3026,7 +3390,7 @@ class GedcomParser(UpdateCallback): # in filename return (0, fullname) # strip off Windows drive letter, if present - if len(fullname) > 3 and fullname[1] == ':': + if len(fullname) > 3 and fullname[1] == ":": fullname = fullname[2:] # look where we found the '.ged', using the full path in fullname other = os.path.join(altpath, fullname) @@ -3041,8 +3405,7 @@ class GedcomParser(UpdateCallback): if os.path.isfile(other): return (1, fullname) # lets try using the base path for relative media paths with base name - other = os.path.join(media_path(self.dbase), - os.path.basename(fullname)) + other = os.path.join(media_path(self.dbase), os.path.basename(fullname)) if os.path.isfile(other): return (1, os.path.basename(fullname)) return (0, fullname) @@ -3096,8 +3459,7 @@ class GedcomParser(UpdateCallback): if line.token == token: got_line = line else: - self.__add_msg(_("Line ignored as not understood"), - line, state) + self.__add_msg(_("Line ignored as not understood"), line, state) skips += 1 def __undefined(self, line, state): @@ -3178,11 +3540,15 @@ class GedcomParser(UpdateCallback): self.number_of_errors += 1 if line: prob_width = 66 - problem = problem.ljust(prob_width)[0:(prob_width - 1)] + problem = problem.ljust(prob_width)[0 : (prob_width - 1)] text = str(line.data).replace("\n", "\n".ljust(prob_width + 22)) - message = "%s Line %5d: %s %s %s\n" % (problem, line.line, - line.level, - line.token_text, text) + message = "%s Line %5d: %s %s %s\n" % ( + problem, + line.line, + line.level, + line.token_text, + text, + ) else: message = problem + "\n" if state: @@ -3192,11 +3558,11 @@ class GedcomParser(UpdateCallback): def __check_msgs(self, record_name, state, obj): if state.msg == "": return - message = _("Records not imported into ") + record_name + ":\n\n" + \ - state.msg + message = _("Records not imported into ") + record_name + ":\n\n" + state.msg new_note = Note() - tag = StyledTextTag(StyledTextTagType.FONTFACE, 'Monospace', - [(0, len(message))]) + tag = StyledTextTag( + StyledTextTagType.FONTFACE, "Monospace", [(0, len(message))] + ) text = StyledText(message, [tag]) new_note.set_styledtext(text) new_note.set_handle(create_id()) @@ -3218,56 +3584,99 @@ class GedcomParser(UpdateCallback): self.backoff = True def __check_xref(self): - - def __check(_map, has_gid_func, class_func, commit_func, - gramps_id2handle, msg): + def __check(_map, has_gid_func, class_func, commit_func, gramps_id2handle, msg): for input_id, gramps_id in _map.map().items(): # Check whether an object exists for the mapped gramps_id if not has_gid_func(gramps_id): - _handle = self.__find_from_handle(gramps_id, - gramps_id2handle) + _handle = self.__find_from_handle(gramps_id, gramps_id2handle) if msg == "FAM": - make_unknown(gramps_id, self.explanation.handle, - class_func, commit_func, self.trans, - db=self.dbase) + make_unknown( + gramps_id, + self.explanation.handle, + class_func, + commit_func, + self.trans, + db=self.dbase, + ) self.missing_references += 1 - self.__add_msg(_("Error: %(msg)s '%(gramps_id)s'" - " (input as @%(xref)s@) not in input" - " GEDCOM. Record synthesised") % - {'msg' : msg, 'gramps_id' : gramps_id, - 'xref' : input_id}) + self.__add_msg( + _( + "Error: %(msg)s '%(gramps_id)s'" + " (input as @%(xref)s@) not in input" + " GEDCOM. Record synthesised" + ) + % {"msg": msg, "gramps_id": gramps_id, "xref": input_id} + ) else: - make_unknown(gramps_id, self.explanation.handle, - class_func, commit_func, self.trans) + make_unknown( + gramps_id, + self.explanation.handle, + class_func, + commit_func, + self.trans, + ) self.missing_references += 1 - self.__add_msg(_("Error: %(msg)s '%(gramps_id)s'" - " (input as @%(xref)s@) not in input" - " GEDCOM. Record with typifying" - " attribute 'Unknown' created") % - {'msg' : msg, 'gramps_id' : gramps_id, - 'xref' : input_id}) + self.__add_msg( + _( + "Error: %(msg)s '%(gramps_id)s'" + " (input as @%(xref)s@) not in input" + " GEDCOM. Record with typifying" + " attribute 'Unknown' created" + ) + % {"msg": msg, "gramps_id": gramps_id, "xref": input_id} + ) self.explanation = create_explanation_note(self.dbase) self.missing_references = 0 - __check(self.pid_map, self.dbase.has_person_gramps_id, - self.__find_or_create_person, self.dbase.commit_person, - self.gid2id, "INDI") - __check(self.fid_map, self.dbase.has_family_gramps_id, - self.__find_or_create_family, self.dbase.commit_family, - self.fid2id, "FAM") - __check(self.sid_map, self.dbase.has_source_gramps_id, - self.__find_or_create_source, self.dbase.commit_source, - self.sid2id, "SOUR") - __check(self.oid_map, self.dbase.has_media_gramps_id, - self.__find_or_create_media, self.dbase.commit_media, - self.oid2id, "OBJE") - __check(self.rid_map, self.dbase.has_repository_gramps_id, - self.__find_or_create_repository, self.dbase.commit_repository, - self.rid2id, "REPO") - __check(self.nid_map, self.dbase.has_note_gramps_id, - self.__find_or_create_note, self.dbase.commit_note, - self.nid2id, "NOTE") + __check( + self.pid_map, + self.dbase.has_person_gramps_id, + self.__find_or_create_person, + self.dbase.commit_person, + self.gid2id, + "INDI", + ) + __check( + self.fid_map, + self.dbase.has_family_gramps_id, + self.__find_or_create_family, + self.dbase.commit_family, + self.fid2id, + "FAM", + ) + __check( + self.sid_map, + self.dbase.has_source_gramps_id, + self.__find_or_create_source, + self.dbase.commit_source, + self.sid2id, + "SOUR", + ) + __check( + self.oid_map, + self.dbase.has_media_gramps_id, + self.__find_or_create_media, + self.dbase.commit_media, + self.oid2id, + "OBJE", + ) + __check( + self.rid_map, + self.dbase.has_repository_gramps_id, + self.__find_or_create_repository, + self.dbase.commit_repository, + self.rid2id, + "REPO", + ) + __check( + self.nid_map, + self.dbase.has_note_gramps_id, + self.__find_or_create_note, + self.dbase.commit_note, + self.nid2id, + "NOTE", + ) # Check persons membership in referenced families def __input_fid(gramps_id): @@ -3280,20 +3689,28 @@ class GedcomParser(UpdateCallback): person = self.dbase.get_person_from_handle(person_handle) for family_handle in person.get_family_handle_list(): family = self.dbase.get_family_from_handle(family_handle) - if family and family.get_father_handle() != person_handle and \ - family.get_mother_handle() != person_handle: + if ( + family + and family.get_father_handle() != person_handle + and family.get_mother_handle() != person_handle + ): person.remove_family_handle(family_handle) self.dbase.commit_person(person, self.trans) - self.__add_msg(_("Error: family '%(family)s' (input as" - " @%(orig_family)s@) person %(person)s" - " (input as %(orig_person)s) is not a" - " member of the referenced family." - " Family reference removed from person") % - {'family' : family.gramps_id, - 'orig_family' : - __input_fid(family.gramps_id), - 'person' : person.gramps_id, - 'orig_person' : input_id}) + self.__add_msg( + _( + "Error: family '%(family)s' (input as" + " @%(orig_family)s@) person %(person)s" + " (input as %(orig_person)s) is not a" + " member of the referenced family." + " Family reference removed from person" + ) + % { + "family": family.gramps_id, + "orig_family": __input_fid(family.gramps_id), + "person": person.gramps_id, + "orig_person": input_id, + } + ) def __input_pid(gramps_id): for (key, val) in self.pid_map.map().items(): @@ -3308,67 +3725,73 @@ class GedcomParser(UpdateCallback): if father_handle: father = self.dbase.get_person_from_handle(father_handle) - if father and \ - family_handle not in father.get_family_handle_list(): + if father and family_handle not in father.get_family_handle_list(): father.add_family_handle(family_handle) self.dbase.commit_person(father, self.trans) - self.__add_msg("Error: family '%(family)s' (input as" - " @%(orig_family)s@) father '%(father)s'" - " (input as '%(orig_father)s') does not " - "refer back to the family. Reference added." - % {'family' : family.gramps_id, - 'orig_family' : input_id, - 'father' : father.gramps_id, - 'orig_father' : - __input_pid(father.gramps_id)}) + self.__add_msg( + "Error: family '%(family)s' (input as" + " @%(orig_family)s@) father '%(father)s'" + " (input as '%(orig_father)s') does not " + "refer back to the family. Reference added." + % { + "family": family.gramps_id, + "orig_family": input_id, + "father": father.gramps_id, + "orig_father": __input_pid(father.gramps_id), + } + ) if mother_handle: mother = self.dbase.get_person_from_handle(mother_handle) - if mother and \ - family_handle not in mother.get_family_handle_list(): + if mother and family_handle not in mother.get_family_handle_list(): mother.add_family_handle(family_handle) self.dbase.commit_person(mother, self.trans) - self.__add_msg("Error: family '%(family)s' (input as" - " @%(orig_family)s@) mother '%(mother)s'" - " (input as '%(orig_mother)s') does not " - "refer back to the family. Reference added." - % {'family' : family.gramps_id, - 'orig_family' : input_id, - 'mother' : mother.gramps_id, - 'orig_mother' : - __input_pid(mother.gramps_id)}) + self.__add_msg( + "Error: family '%(family)s' (input as" + " @%(orig_family)s@) mother '%(mother)s'" + " (input as '%(orig_mother)s') does not " + "refer back to the family. Reference added." + % { + "family": family.gramps_id, + "orig_family": input_id, + "mother": mother.gramps_id, + "orig_mother": __input_pid(mother.gramps_id), + } + ) for child_ref in family.get_child_ref_list(): child_handle = child_ref.ref child = self.dbase.get_person_from_handle(child_handle) if child: - if family_handle not in \ - child.get_parent_family_handle_list(): + if family_handle not in child.get_parent_family_handle_list(): # The referenced child has no reference to the family. # There was a link from the FAM record to the child, # but no FAMC link from the child to the FAM. child.add_parent_family_handle(family_handle) self.dbase.commit_person(child, self.trans) - self.__add_msg("Error: family '%(family)s' (input as" - " @%(orig_family)s@) child '%(child)s'" - " (input as '%(orig_child)s') does not " - "refer back to the family. " - "Reference added." % - {'family' : family.gramps_id, - 'orig_family' : input_id, - 'child' : child.gramps_id, - 'orig_child' : - __input_pid(child.gramps_id)}) + self.__add_msg( + "Error: family '%(family)s' (input as" + " @%(orig_family)s@) child '%(child)s'" + " (input as '%(orig_child)s') does not " + "refer back to the family. " + "Reference added." + % { + "family": family.gramps_id, + "orig_family": input_id, + "child": child.gramps_id, + "orig_child": __input_pid(child.gramps_id), + } + ) if self.missing_references: self.dbase.commit_note(self.explanation, self.trans, time.time()) - txt = _("\nThe imported file was not self-contained.\n" - "To correct for that, %(new)d objects were created and\n" - "their typifying attribute was set to 'Unknown'.\n" - "Where possible these 'Unknown' objects are \n" - "referenced by note %(unknown)s.\n" - ) % {'new': self.missing_references, - 'unknown': self.explanation.gramps_id} + txt = _( + "\nThe imported file was not self-contained.\n" + "To correct for that, %(new)d objects were created and\n" + "their typifying attribute was set to 'Unknown'.\n" + "Where possible these 'Unknown' objects are \n" + "referenced by note %(unknown)s.\n" + ) % {"new": self.missing_references, "unknown": self.explanation.gramps_id} self.__add_msg(txt) self.number_of_errors -= 1 @@ -3414,11 +3837,15 @@ class GedcomParser(UpdateCallback): then just the structrued address is used. The routine returns a string suitable for a title. """ - title = '' - free_form_address = free_form_address.replace('\n', ', ') - if not (addr.get_street() or addr.get_locality() or - addr.get_city() or addr.get_state() or - addr.get_postal_code()): + title = "" + free_form_address = free_form_address.replace("\n", ", ") + if not ( + addr.get_street() + or addr.get_locality() + or addr.get_city() + or addr.get_state() + or addr.get_postal_code() + ): addr.set_street(free_form_address) return free_form_address @@ -3426,25 +3853,28 @@ class GedcomParser(UpdateCallback): # structured address provided addr_list = free_form_address.split(",") str_list = [] - for func in (addr.get_street(), addr.get_locality(), - addr.get_city(), addr.get_state(), - addr.get_postal_code(), addr.get_country()): - str_list += [i.strip(',' + string.whitespace) - for i in func.split("\n")] + for func in ( + addr.get_street(), + addr.get_locality(), + addr.get_city(), + addr.get_state(), + addr.get_postal_code(), + addr.get_country(), + ): + str_list += [i.strip("," + string.whitespace) for i in func.split("\n")] for elmn in addr_list: - if elmn.strip(',' + string.whitespace) not in str_list: + if elmn.strip("," + string.whitespace) not in str_list: # message means that the element %s was ignored, but # expressed the wrong way round because the message is # truncated for output - self.__add_msg(_("ADDR element ignored '%s'" - % elmn), line, state) + self.__add_msg(_("ADDR element ignored '%s'" % elmn), line, state) # The free-form address ADDR is discarded # Assemble a title out of structured address for elmn in str_list: if elmn: - if title != '': + if title != "": # TODO for Arabic, should the next comma be translated? - title += ', ' + title += ", " title += elmn return title @@ -3488,12 +3918,13 @@ class GedcomParser(UpdateCallback): localized_submitter = _("(Submitter):") if state.res.get_name() == "": - submitter_name = "SUBM %s @%s@" % (localized_submitter, - line.token_text) + submitter_name = "SUBM %s @%s@" % (localized_submitter, line.token_text) else: - submitter_name = "SUBM %s (@%s@) %s" % (localized_submitter, - line.token_text, - state.res.get_name()) + submitter_name = "SUBM %s (@%s@) %s" % ( + localized_submitter, + line.token_text, + state.res.get_name(), + ) if self.use_def_src: repo.set_name(submitter_name) repo.set_handle(create_id()) @@ -3510,14 +3941,14 @@ class GedcomParser(UpdateCallback): addr.set_phone(state.res.get_phone()) repo.add_address(addr) rtype = RepositoryType() - rtype.set((RepositoryType.CUSTOM, _('GEDCOM data'))) + rtype.set((RepositoryType.CUSTOM, _("GEDCOM data"))) repo.set_type(rtype) self.__check_msgs(submitter_name, state, repo) self.dbase.commit_repository(repo, self.trans, state.repo.change) repo_ref = RepoRef() repo_ref.set_reference_handle(repo.handle) mtype = SourceMediaType() - mtype.set((SourceMediaType.UNKNOWN, '')) + mtype.set((SourceMediaType.UNKNOWN, "")) repo_ref.set_media_type(mtype) self.def_src.add_repo_reference(repo_ref) self.dbase.commit_source(self.def_src, self.trans) @@ -3578,8 +4009,7 @@ class GedcomParser(UpdateCallback): self.__check_msgs(_("Top Level"), state, None) elif key in ("SOUR", "SOURCE"): self.__parse_source(line.token_text, 1) - elif (line.data.startswith("SOUR ") or - line.data.startswith("SOURCE ")): + elif line.data.startswith("SOUR ") or line.data.startswith("SOURCE "): # A source formatted in a single line, for example: # 0 @S62@ SOUR This is the title of the source source = self.__find_or_create_source(self.sid_map[line.data]) @@ -3616,11 +4046,11 @@ class GedcomParser(UpdateCallback): func = __map.get(line.token, default) func(line, state) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # # INDI parsing # - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def __parse_indi(self, line): """ @@ -3671,8 +4101,9 @@ class GedcomParser(UpdateCallback): # Set up primary photo if present self.__do_photo(state) - self.__check_msgs(_("INDI (individual) Gramps ID %s") % - person.get_gramps_id(), state, person) + self.__check_msgs( + _("INDI (individual) Gramps ID %s") % person.get_gramps_id(), state, person + ) # commit the person to the database self.dbase.commit_person(person, self.trans, state.person.change) @@ -3720,9 +4151,9 @@ class GedcomParser(UpdateCallback): # the TYPE in a custom event cust_tag = CUSTOMEVENTTAGS.get(line.token_text, line.token_text) cust_type = EventType((EventType.CUSTOM, cust_tag)) - event_ref = self.__build_event_pair(state, cust_type, - self.event_parse_tbl, - str(line.data)) + event_ref = self.__build_event_pair( + state, cust_type, self.event_parse_tbl, str(line.data) + ) state.person.add_event_ref(event_ref) def __fam_even(self, line, state): @@ -3732,10 +4163,9 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - event_ref = self.__build_family_event_pair(state, - EventType.CUSTOM, - self.event_parse_tbl, - line.data) + event_ref = self.__build_family_event_pair( + state, EventType.CUSTOM, self.event_parse_tbl, line.data + ) state.family.add_event_ref(event_ref) def __person_chan(self, line, state): @@ -3757,7 +4187,7 @@ class GedcomParser(UpdateCallback): @type state: CurrentState """ attr = Attribute() - attr.set_type((AttributeType.CUSTOM, 'RESN')) + attr.set_type((AttributeType.CUSTOM, "RESN")) state.person.add_attribute(attr) def __person_alt_name(self, line, state): @@ -3798,11 +4228,10 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - if line.data == '': - self.__add_msg(_("Empty Alias ignored"), - line, state) + if line.data == "": + self.__add_msg(_("Empty Alias ignored"), line, state) self.__skip_subordinate_levels(state.level + 1, state) - elif line.data[0] == '@': + elif line.data[0] == "@": handle = self.__find_person_handle(self.pid_map[line.data]) ref = PersonRef() ref.ref = handle @@ -3863,7 +4292,7 @@ class GedcomParser(UpdateCallback): This handles the FTM _PHOTO feature, which identifies an OBJE to use as the person's primary photo. """ - state.photo = line.data # Just save it for now. + state.photo = line.data # Just save it for now. def __person_name(self, line, state): """ @@ -3943,8 +4372,9 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - event_ref = self.__build_event_pair(state, EventType.CUSTOM, - self.event_parse_tbl, line.data) + event_ref = self.__build_event_pair( + state, EventType.CUSTOM, self.event_parse_tbl, line.data + ) state.person.add_event_ref(event_ref) def __person_std_event(self, line, state): @@ -3993,8 +4423,9 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - event_ref = self.__build_event_pair(state, EventType.RELIGION, - self.event_parse_tbl, line.data) + event_ref = self.__build_event_pair( + state, EventType.RELIGION, self.event_parse_tbl, line.data + ) state.person.add_event_ref(event_ref) def __person_birt(self, line, state): @@ -4016,8 +4447,9 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - event_ref = self.__build_event_pair(state, EventType.BIRTH, - self.event_parse_tbl, line.data) + event_ref = self.__build_event_pair( + state, EventType.BIRTH, self.event_parse_tbl, line.data + ) if state.person.get_birth_ref(): state.person.add_event_ref(event_ref) else: @@ -4038,8 +4470,9 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - event_ref = self.__build_event_pair(state, EventType.ADOPT, - self.adopt_parse_tbl, line.data) + event_ref = self.__build_event_pair( + state, EventType.ADOPT, self.adopt_parse_tbl, line.data + ) state.person.add_event_ref(event_ref) def __person_deat(self, line, state): @@ -4056,8 +4489,9 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - event_ref = self.__build_event_pair(state, EventType.DEATH, - self.event_parse_tbl, line.data) + event_ref = self.__build_event_pair( + state, EventType.DEATH, self.event_parse_tbl, line.data + ) if state.person.get_death_ref(): state.person.add_event_ref(event_ref) else: @@ -4133,9 +4567,10 @@ class GedcomParser(UpdateCallback): @type state: CurrentState """ self.backoff = True # reprocess the current ADDR line - line.level += 1 # as if it was next level down - event_ref = self.__build_event_pair(state, EventType.RESIDENCE, - self.event_parse_tbl, '') + line.level += 1 # as if it was next level down + event_ref = self.__build_event_pair( + state, EventType.RESIDENCE, self.event_parse_tbl, "" + ) state.person.add_event_ref(event_ref) def __person_phon(self, line, state): @@ -4149,7 +4584,7 @@ class GedcomParser(UpdateCallback): """ url = Url() url.set_path(line.data) - url.set_type(UrlType(_('Phone'))) + url.set_type(UrlType(_("Phone"))) state.person.add_url(url) def __person_fax(self, line, state): @@ -4164,7 +4599,7 @@ class GedcomParser(UpdateCallback): """ url = Url() url.set_path(line.data) - url.set_type(UrlType(_('FAX'))) + url.set_type(UrlType(_("FAX"))) state.person.add_url(url) def __person_email(self, line, state): @@ -4410,13 +4845,12 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - if state.name.get_suffix() == "" or \ - state.name.get_suffix() == line.data: - #suffix might be set before when parsing name string + if state.name.get_suffix() == "" or state.name.get_suffix() == line.data: + # suffix might be set before when parsing name string state.name.set_suffix(line.data) else: - #previously set suffix different, to not loose information, append - state.name.set_suffix(state.name.get_suffix() + ' ' + line.data) + # previously set suffix different, to not loose information, append + state.name.set_suffix(state.name.get_suffix() + " " + line.data) self.__skip_subordinate_levels(state.level + 1, state) def __name_nick(self, line, state): @@ -4481,8 +4915,8 @@ class GedcomParser(UpdateCallback): surname.set_surname(lname[-1].strip()) surname.set_primary() name.set_surname_list([surname]) - name.set_first_name(' '.join(lname[0:name_len - 1])) -# name = self.__parse_name_personal(line.data) + name.set_first_name(" ".join(lname[0 : name_len - 1])) + # name = self.__parse_name_personal(line.data) name.set_type(NameType.AKA) state.person.add_alternate_name(name) @@ -4532,8 +4966,7 @@ class GedcomParser(UpdateCallback): sub_state.attr = line.data sub_state.level = state.level + 1 state.person.add_attribute(sub_state.attr) - self.__parse_level(sub_state, self.person_attr_parse_tbl, - self.__ignore) + self.__parse_level(sub_state, self.person_attr_parse_tbl, self.__ignore) state.msg += sub_state.msg def __person_fact(self, line, state): @@ -4551,8 +4984,7 @@ class GedcomParser(UpdateCallback): sub_state.attr.set_value(line.data) sub_state.level = state.level + 1 state.person.add_attribute(sub_state.attr) - self.__parse_level(sub_state, self.person_fact_parse_tbl, - self.__ignore) + self.__parse_level(sub_state, self.person_fact_parse_tbl, self.__ignore) state.msg += sub_state.msg def __person_fact_type(self, line, state): @@ -4625,9 +5057,9 @@ class GedcomParser(UpdateCallback): if sub_state.place: place_title = _pd.display(self.dbase, sub_state.place) - sub_state.place_fields.load_place(self.place_import, - sub_state.place, - place_title) + sub_state.place_fields.load_place( + self.place_import, sub_state.place, place_title + ) def __lds_temple(self, line, state): """ @@ -4777,8 +5209,7 @@ class GedcomParser(UpdateCallback): state.person.add_parent_family_handle(handle) # search childrefs - family, _new = self.dbase.find_family_from_handle(handle, - self.trans) + family, _new = self.dbase.find_family_from_handle(handle, self.trans) family.set_gramps_id(gid) for ref in family.get_child_ref_list(): @@ -4811,8 +5242,7 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - state.ftype = PEDIGREE_TYPES.get(line.data.lower(), - ChildRefType.UNKNOWN) + state.ftype = PEDIGREE_TYPES.get(line.data.lower(), ChildRefType.UNKNOWN) def __person_famc_frel(self, line, state): """ @@ -4982,11 +5412,11 @@ class GedcomParser(UpdateCallback): """ self.__parse_note(line, state.ref, state) - #------------------------------------------------------------------- + # ------------------------------------------------------------------- # # FAM parsing # - #------------------------------------------------------------------- + # ------------------------------------------------------------------- def __parse_fam(self, line): """ @@ -5043,8 +5473,9 @@ class GedcomParser(UpdateCallback): # Add a default tag if provided self.__add_default_tag(family) - self.__check_msgs(_("FAM (family) Gramps ID %s") % - family.get_gramps_id(), state, family) + self.__check_msgs( + _("FAM (family) Gramps ID %s") % family.get_gramps_id(), state, family + ) # commit family to database self.dbase.commit_family(family, self.trans, family.change) @@ -5058,7 +5489,7 @@ class GedcomParser(UpdateCallback): @type line: GedLine @param state: The current state @type state: CurrentState - """ + """ handle = self.__find_person_handle(self.pid_map[line.data]) state.family.set_father_handle(handle) @@ -5072,7 +5503,7 @@ class GedcomParser(UpdateCallback): @type line: GedLine @param state: The current state @type state: CurrentState - """ + """ handle = self.__find_person_handle(self.pid_map[line.data]) state.family.set_mother_handle(handle) @@ -5110,14 +5541,14 @@ class GedcomParser(UpdateCallback): descr = event.get_description() if descr == "Civil Union": state.family.type.set(FamilyRelType.CIVIL_UNION) - event.set_description('') + event.set_description("") elif descr == "Unmarried": state.family.type.set(FamilyRelType.UNMARRIED) - event.set_description('') + event.set_description("") else: state.family.type.set(FamilyRelType.MARRIED) if descr == "Y": - event.set_description('') + event.set_description("") self.dbase.commit_event(event, self.trans) event_ref.ref = event.handle @@ -5147,7 +5578,7 @@ class GedcomParser(UpdateCallback): event.set_gramps_id(self.emapper.find_next()) event.set_type(cust_type) # in case a description ever shows up - if line.data and line.data != 'Y': + if line.data and line.data != "Y": event.set_description(str(line.data)) self.dbase.add_event(event, self.trans) @@ -5189,8 +5620,9 @@ class GedcomParser(UpdateCallback): child = self.__find_or_create_person(self.pid_map[line.data]) - reflist = [ref for ref in state.family.get_child_ref_list() - if ref.ref == child.handle] + reflist = [ + ref for ref in state.family.get_child_ref_list() if ref.ref == child.handle + ] if reflist: # The child has been referenced already ref = reflist[0] @@ -5233,7 +5665,7 @@ class GedcomParser(UpdateCallback): @type line: GedLine @param state: The current state @type state: CurrentState - """ + """ sub_state = CurrentState() sub_state.level = state.level + 1 sub_state.lds_ord = LdsOrd() @@ -5248,9 +5680,9 @@ class GedcomParser(UpdateCallback): if sub_state.place: place_title = _pd.display(self.dbase, sub_state.place) - sub_state.place_fields.load_place(self.place_import, - sub_state.place, - place_title) + sub_state.place_fields.load_place( + self.place_import, sub_state.place, place_title + ) def __family_source(self, line, state): """ @@ -5333,8 +5765,7 @@ class GedcomParser(UpdateCallback): sub_state.attr = line.data sub_state.level = state.level + 1 state.family.add_attribute(line.data) - self.__parse_level(sub_state, self.person_attr_parse_tbl, - self.__ignore) + self.__parse_level(sub_state, self.person_attr_parse_tbl, self.__ignore) state.msg += sub_state.msg def __family_refn(self, line, state): @@ -5360,36 +5791,36 @@ class GedcomParser(UpdateCallback): def __obje(self, line, state, pri_obj): """ - Embedded form + Embedded form - n OBJE @@ {1:1} - +1 _PRIM {0:1} # Indicates primary photo + n OBJE @@ {1:1} + +1 _PRIM {0:1} # Indicates primary photo - Linked form + Linked form - n OBJE {1:1} - +1 FORM {1:1} # v5.5 layout - +1 TITL {0:1} - +1 FILE {1:1} # v5.5.1 allows multiple - +2 FORM {1:1} # v5.5.1 layout - +3 MEDI {0:1} # v5.5.1 layout - +1 <> {0:M} - +1 _PRIM {0:1} # Indicates primary photo + n OBJE {1:1} + +1 FORM {1:1} # v5.5 layout + +1 TITL {0:1} + +1 FILE {1:1} # v5.5.1 allows multiple + +2 FORM {1:1} # v5.5.1 layout + +3 MEDI {0:1} # v5.5.1 layout + +1 <> {0:M} + +1 _PRIM {0:1} # Indicates primary photo - @param line: The current line in GedLine format - @type line: GedLine - @param state: The current state - @type state: CurrentState - @param pri_obj: The Primary object to which this is attached - @type state: Person # or Family, or Source etc. + @param line: The current line in GedLine format + @type line: GedLine + @param state: The current state + @type state: CurrentState + @param pri_obj: The Primary object to which this is attached + @type state: Person # or Family, or Source etc. """ - if line.data and line.data[0] == '@': + if line.data and line.data[0] == "@": # Reference to a named multimedia object defined elsewhere gramps_id = self.oid_map[line.data] handle = self.__find_media_handle(gramps_id) # check to see if this is a primary photo line = self.__chk_subordinate(state.level + 1, state, TOKEN__PRIM) - if line and line.data == 'Y': + if line and line.data == "Y": state.photo = handle oref = MediaRef() oref.set_reference_handle(handle) @@ -5433,8 +5864,9 @@ class GedcomParser(UpdateCallback): new_note = Note(sub_state.filename) new_note.set_gramps_id(self.nid_map[""]) new_note.set_handle(create_id()) - new_note.set_type(OBJ_NOTETYPE.get(type(pri_obj).__name__, - NoteType.GENERAL)) + new_note.set_type( + OBJ_NOTETYPE.get(type(pri_obj).__name__, NoteType.GENERAL) + ) self.dbase.commit_note(new_note, self.trans, new_note.change) pri_obj.add_note(new_note.get_handle()) @@ -5442,14 +5874,14 @@ class GedcomParser(UpdateCallback): # to allow import of references to URLs (especially for import from # geni.com), do not try to find the file if it is blatently a URL res = urlparse(sub_state.filename) - if sub_state.filename != '' and (res.scheme == '' or - len(res.scheme) == 1 or - res.scheme == 'file'): - (valid, path) = self.__find_file(sub_state.filename, - self.dir_path) + if sub_state.filename != "" and ( + res.scheme == "" or len(res.scheme) == 1 or res.scheme == "file" + ): + (valid, path) = self.__find_file(sub_state.filename, self.dir_path) if not valid: - self.__add_msg(_("Could not import %s") % - sub_state.filename, line, state) + self.__add_msg( + _("Could not import %s") % sub_state.filename, line, state + ) else: path = sub_state.filename # Multiple references to the same media silently drops the later @@ -5461,18 +5893,19 @@ class GedcomParser(UpdateCallback): if sub_state.title: photo.set_description(sub_state.title) else: - photo.set_description(path.replace('\\', '/')) + photo.set_description(path.replace("\\", "/")) full_path = os.path.abspath(path) # deal with mime types value = mimetypes.guess_type(full_path) if value and value[0]: # found from filename photo.set_mime_type(value[0]) else: # get from OBJE.FILE.FORM - if '/' in sub_state.form: # already has expanded mime type + if "/" in sub_state.form: # already has expanded mime type photo.set_mime_type(sub_state.form) else: - value = mimetypes.types_map.get('.' + sub_state.form, - _('unknown')) + value = mimetypes.types_map.get( + "." + sub_state.form, _("unknown") + ) photo.set_mime_type(value) if sub_state.attr: photo.attribute_list.append(sub_state.attr) @@ -5512,9 +5945,8 @@ class GedcomParser(UpdateCallback): @type state: CurrentState """ state.attr = Attribute() - mtype = MEDIA_MAP.get(line.data.lower(), - (SourceMediaType.CUSTOM, line.data)) - state.attr.set_type(_('Media-Type')) + mtype = MEDIA_MAP.get(line.data.lower(), (SourceMediaType.CUSTOM, line.data)) + state.attr.set_type(_("Media-Type")) state.attr.set_value(str(SourceMediaType(mtype))) def __media_ref_titl(self, line, state): @@ -5538,8 +5970,7 @@ class GedcomParser(UpdateCallback): @type state: CurrentState """ if state.filename != "": - self.__add_msg(_("Multiple FILE in a single OBJE ignored"), - line, state) + self.__add_msg(_("Multiple FILE in a single OBJE ignored"), line, state) self.__skip_subordinate_levels(state.level + 1, state) return state.filename = line.data @@ -5636,8 +6067,7 @@ class GedcomParser(UpdateCallback): state.event.set_type(name) else: try: - if line.data not in GED_TO_GRAMPS_EVENT and \ - line.data[0] != 'Y': + if line.data not in GED_TO_GRAMPS_EVENT and line.data[0] != "Y": state.event.set_description(line.data) except IndexError: return @@ -5668,8 +6098,11 @@ class GedcomParser(UpdateCallback): @type state: CurrentState """ - if self.is_ftw and (state.event.type in FTW_BAD_PLACE) \ - and not state.event.get_description(): + if ( + self.is_ftw + and (state.event.type in FTW_BAD_PLACE) + and not state.event.get_description() + ): state.event.set_description(line.data) else: place = state.place @@ -5694,11 +6127,10 @@ class GedcomParser(UpdateCallback): sub_state.place = place sub_state.level = state.level + 1 - self.__parse_level(sub_state, self.event_place_map, - self.__undefined) + self.__parse_level(sub_state, self.event_place_map, self.__undefined) state.msg += sub_state.msg - if sub_state.pf: # if we found local PLAC:FORM - state.pf = sub_state.pf # save to override global value + if sub_state.pf: # if we found local PLAC:FORM + state.pf = sub_state.pf # save to override global value # merge notes etc into place state.place.merge(sub_state.place) @@ -5792,15 +6224,15 @@ class GedcomParser(UpdateCallback): self.__parse_level(sub_state, self.parse_loc_tbl, self.__undefined) state.msg += sub_state.msg - title = self.__merge_address(free_form, sub_state.location, - line, state) + title = self.__merge_address(free_form, sub_state.location, line, state) location = sub_state.location if self.addr_is_detail and state.place: # Commit the enclosing place - place = self.__find_place(state.place.get_title(), None, - state.place.get_placeref_list()) + place = self.__find_place( + state.place.get_title(), None, state.place.get_placeref_list() + ) if place is None: place = state.place self.dbase.add_place(place, self.trans) @@ -5825,12 +6257,15 @@ class GedcomParser(UpdateCallback): place = state.place if place: # We encounter an ADDR having previously encountered a PLAC - if len(place.get_alternate_locations()) != 0 and \ - not self.__get_first_loc(place).is_empty(): + if ( + len(place.get_alternate_locations()) != 0 + and not self.__get_first_loc(place).is_empty() + ): # We have perviously found an ADDR, or have populated # location from PLAC title - self.__add_msg(_("Location already populated; ADDR " - "ignored"), line, state) + self.__add_msg( + _("Location already populated; ADDR " "ignored"), line, state + ) # ignore this second ADDR, and use the old one else: # This is the first ADDR @@ -6037,7 +6472,7 @@ class GedcomParser(UpdateCallback): attr.set_value(line.data) state.event_ref.add_attribute(attr) elif line.token == TOKEN_WIFE: - #wife event can be on same level, if so call it and finish + # wife event can be on same level, if so call it and finish self.__event_wife(line, state) break @@ -6058,7 +6493,7 @@ class GedcomParser(UpdateCallback): attr.set_value(line.data) state.event_ref.add_attribute(attr) elif line.token == TOKEN_HUSB: - #husband event can be on same level, if so call it and finish + # husband event can be on same level, if so call it and finish self.__event_husb(line, state) break @@ -6081,8 +6516,8 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - if hasattr(state, 'event'): - #read in time as attribute of event + if hasattr(state, "event"): + # read in time as attribute of event attr = Attribute() attr.set_type(AttributeType.TIME) attr.set_value(line.data) @@ -6110,11 +6545,9 @@ class GedcomParser(UpdateCallback): break elif line.token == TOKEN_TYPE: if line.data == "WITNESS_OF_MARRIAGE": - role = EventRoleType( - EventRoleType.WITNESS) + role = EventRoleType(EventRoleType.WITNESS) else: - role = EventRoleType( - (EventRoleType.CUSTOM, line.data)) + role = EventRoleType((EventRoleType.CUSTOM, line.data)) event_ref.set_role(role) wit.add_event_ref(event_ref) self.dbase.commit_person(wit, self.trans) @@ -6140,18 +6573,20 @@ class GedcomParser(UpdateCallback): sub_state.mrel = TYPE_BIRTH sub_state.frel = TYPE_BIRTH - self.__parse_level(sub_state, self.parse_person_adopt, - self.__undefined) + self.__parse_level(sub_state, self.parse_person_adopt, self.__undefined) state.msg += sub_state.msg - if (int(sub_state.mrel) == ChildRefType.BIRTH and - int(sub_state.frel) == ChildRefType.BIRTH): + if ( + int(sub_state.mrel) == ChildRefType.BIRTH + and int(sub_state.frel) == ChildRefType.BIRTH + ): sub_state.mrel = sub_state.frel = TYPE_ADOPT state.person.add_parent_family_handle(handle) - reflist = [ref for ref in family.get_child_ref_list() - if ref.ref == state.person.handle] + reflist = [ + ref for ref in family.get_child_ref_list() if ref.ref == state.person.handle + ] if reflist: ref = reflist[0] ref.set_father_relation(sub_state.frel) @@ -6193,8 +6628,9 @@ class GedcomParser(UpdateCallback): frel = mrel = ChildRefType.BIRTH family, _new = self.dbase.find_family_from_handle(handle, self.trans) - reflist = [ref for ref in family.get_child_ref_list() - if ref.ref == state.person.handle] + reflist = [ + ref for ref in family.get_child_ref_list() if ref.ref == state.person.handle + ] if reflist: ref = reflist[0] ref.set_father_relation(frel) @@ -6376,9 +6812,7 @@ class GedcomParser(UpdateCallback): note with styled text so link can be followed in reports etc. """ note = Note() - tags = StyledTextTag(StyledTextTagType.LINK, - line.data, - [(0, len(line.data))]) + tags = StyledTextTag(StyledTextTagType.LINK, line.data, [(0, len(line.data))]) note.set_styledtext(StyledText(line.data, [tags])) gramps_id = self.nid_map[""] note.set_gramps_id(gramps_id) @@ -6500,11 +6934,11 @@ class GedcomParser(UpdateCallback): """ self.__parse_note(line, state.citation, state) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # # SOUR parsing # - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def __parse_source(self, name, level): """ @@ -6532,14 +6966,15 @@ class GedcomParser(UpdateCallback): state = CurrentState() state.source = self.__find_or_create_source(self.sid_map[name]) # SOURce with the given gramps_id had no title - state.source.set_title(_("No title - ID %s") % - state.source.get_gramps_id()) + state.source.set_title(_("No title - ID %s") % state.source.get_gramps_id()) state.level = level self.__parse_level(state, self.source_func, self.__undefined) - self.__check_msgs(_("SOUR (source) Gramps ID %s") % - state.source.get_gramps_id(), - state, state.source) + self.__check_msgs( + _("SOUR (source) Gramps ID %s") % state.source.get_gramps_id(), + state, + state.source, + ) self.dbase.commit_source(state.source, self.trans, state.source.change) def __source_attr(self, line, state): @@ -6580,7 +7015,7 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - if line.data and line.data[0] == '@': + if line.data and line.data[0] == "@": # This deals with the standard GEDCOM # SOURCE_REPOSITORY_CITATION: = # n REPO @@ {1:1} @@ -6589,7 +7024,7 @@ class GedcomParser(UpdateCallback): # +2 MEDI {0:1} gid = self.rid_map[line.data] repo = self.__find_or_create_repository(gid) - elif line.data == '': + elif line.data == "": # This deals with the non-standard GEDCOM format found in Family # Tree Maker for Windows, Broderbund Software, Banner Blue # Division: @@ -6642,12 +7077,11 @@ class GedcomParser(UpdateCallback): @type state: CurrentState """ state.repo_ref.set_call_number(line.data) - #self.__skip_subordinate_levels(state.level + 1, state) + # self.__skip_subordinate_levels(state.level + 1, state) def __repo_ref_medi(self, line, state): name = line.data - mtype = MEDIA_MAP.get(name.lower(), - (SourceMediaType.CUSTOM, name)) + mtype = MEDIA_MAP.get(name.lower(), (SourceMediaType.CUSTOM, name)) state.repo_ref.set_media_type(mtype) def __repo_ref_note(self, line, state): @@ -6724,7 +7158,7 @@ class GedcomParser(UpdateCallback): @param state: The current state @type state: CurrentState """ - state.source.set_title(line.data.replace('\n', ' ')) + state.source.set_title(line.data.replace("\n", " ")) def __source_taxt_peri(self, line, state): """ @@ -6734,13 +7168,13 @@ class GedcomParser(UpdateCallback): @type state: CurrentState """ if state.source.get_title() == "": - state.source.set_title(line.data.replace('\n', ' ')) + state.source.set_title(line.data.replace("\n", " ")) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # # OBJE parsing # - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def __parse_obje(self, line): """ @@ -6787,11 +7221,10 @@ class GedcomParser(UpdateCallback): if value and value[0]: # found from filename state.media.set_mime_type(value[0]) else: # get from OBJE.FILE.FORM - if '/' in state.form: # already has expanded mime type + if "/" in state.form: # already has expanded mime type state.media.set_mime_type(state.form) else: - value = mimetypes.types_map.get('.' + state.form, - _('unknown')) + value = mimetypes.types_map.get("." + state.form, _("unknown")) state.media.set_mime_type(value) # Add the default reference if no source has found self.__add_default_source(media) @@ -6799,8 +7232,11 @@ class GedcomParser(UpdateCallback): # Add a default tag if provided self.__add_default_tag(media) - self.__check_msgs(_("OBJE (multi-media object) Gramps ID %s") % - media.get_gramps_id(), state, media) + self.__check_msgs( + _("OBJE (multi-media object) Gramps ID %s") % media.get_gramps_id(), + state, + media, + ) # commit the person to the database self.dbase.commit_media(media, self.trans, media.change) @@ -6823,26 +7259,25 @@ class GedcomParser(UpdateCallback): # The following checks for the odd "feature" of GEDCOM 5.5.1 that # allows multiple files to be attached to a single OBJE; not supported if state.media.get_path() != "": - self.__add_msg(_("Multiple FILE in a single OBJE ignored"), - line, state) + self.__add_msg(_("Multiple FILE in a single OBJE ignored"), line, state) self.__skip_subordinate_levels(state.level + 1, state) return res = urlparse(line.data) - if line.data != '' and (res.scheme == '' or - len(res.scheme) == 1 or res.scheme == 'file'): + if line.data != "" and ( + res.scheme == "" or len(res.scheme) == 1 or res.scheme == "file" + ): (file_ok, filename) = self.__find_file(line.data, self.dir_path) if state.form != "url": # Might not work if FORM doesn't precede FILE if not file_ok: - self.__add_msg(_("Could not import %s") % line.data, line, - state) + self.__add_msg(_("Could not import %s") % line.data, line, state) path = filename else: path = line.data state.media.set_path(path) if not state.media.get_description(): - state.media.set_description(path.replace('\\', '/')) + state.media.set_description(path.replace("\\", "/")) def __obje_title(self, line, state): """ @@ -6853,7 +7288,7 @@ class GedcomParser(UpdateCallback): """ state.media.set_description(line.data) -# FTM non-standard TEXT in OBJE, treat as note. + # FTM non-standard TEXT in OBJE, treat as note. def __obje_text(self, line, state): """ @param line: The current line in GedLine format @@ -6868,7 +7303,7 @@ class GedcomParser(UpdateCallback): self.dbase.commit_note(new_note, self.trans, new_note.change) state.media.add_note(new_note.get_handle()) -# FTM non-standard DATE in OBJE, treat as Media Date. + # FTM non-standard DATE in OBJE, treat as Media Date. def __obje_date(self, line, state): """ @param line: The current line in GedLine format @@ -6919,9 +7354,8 @@ class GedcomParser(UpdateCallback): @type state: CurrentState """ attr = Attribute() - mtype = MEDIA_MAP.get(line.data.lower(), - (SourceMediaType.CUSTOM, line.data)) - attr.set_type(_('Media-Type')) + mtype = MEDIA_MAP.get(line.data.lower(), (SourceMediaType.CUSTOM, line.data)) + attr.set_type(_("Media-Type")) attr.set_value(str(SourceMediaType(mtype))) state.media.attribute_list.append(attr) @@ -6994,11 +7428,11 @@ class GedcomParser(UpdateCallback): """ self.__parse_note(line, state.attr, state) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # # REPO parsing # - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def __parse_repo(self, line): """ @@ -7017,8 +7451,9 @@ class GedcomParser(UpdateCallback): state.level = 1 self.__parse_level(state, self.repo_parse_tbl, self.__ignore) - self.__check_msgs(_("REPO (repository) Gramps ID %s") % - repo.get_gramps_id(), state, repo) + self.__check_msgs( + _("REPO (repository) Gramps ID %s") % repo.get_gramps_id(), state, repo + ) self.dbase.commit_repository(repo, self.trans, repo.change) def __repo_name(self, line, state): @@ -7078,8 +7513,7 @@ class GedcomParser(UpdateCallback): address_list = state.repo.get_address_list() if address_list: if address_list[0].get_phone(): - self.__add_msg(_("Only one phone number supported"), - line, state) + self.__add_msg(_("Only one phone number supported"), line, state) else: address_list[0].set_phone(line.data) @@ -7092,7 +7526,7 @@ class GedcomParser(UpdateCallback): """ url = Url() url.set_path(line.data) - url.set_type(UrlType(_('FAX'))) + url.set_type(UrlType(_("FAX"))) state.repo.add_url(url) def __repo_www(self, line, state): @@ -7220,11 +7654,11 @@ class GedcomParser(UpdateCallback): """ self.__parse_note(line, state.obj, state) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # # HEAD parsing # - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def __parse_header(self): """ @@ -7278,7 +7712,7 @@ class GedcomParser(UpdateCallback): # Some software (e.g. RootsMagic (http://files.rootsmagic.com/PAF- # Book/RootsMagic-for-PAF-Users-Printable.pdf) use the Addr fields for # 'Place Details (address, hospital, cemetary)' - if line.data.strip().lower() in ['rootsmagic']: + if line.data.strip().lower() in ["rootsmagic"]: self.addr_is_detail = True # We will use the approved system ID as the name of the generating # software, in case we do not get the name in the proper place @@ -7289,8 +7723,7 @@ class GedcomParser(UpdateCallback): sattr.set_value("%s" % self.genby) self.def_src.add_attribute(sattr) sub_state = CurrentState(level=state.level + 1) - self.__parse_level(sub_state, self.header_sour_parse_tbl, - self.__undefined) + self.__parse_level(sub_state, self.header_sour_parse_tbl, self.__undefined) state.msg += sub_state.msg # We can't produce the 'Generated by' statement till the end of the # SOUR level, because the name and version may come in any order @@ -7345,16 +7778,15 @@ class GedcomParser(UpdateCallback): state.msg += sub_state.msg if self.use_def_src: - repo.set_name(_("Business that produced the product: %s") % - line.data) + repo.set_name(_("Business that produced the product: %s") % line.data) rtype = RepositoryType() - rtype.set((RepositoryType.CUSTOM, _('GEDCOM data'))) + rtype.set((RepositoryType.CUSTOM, _("GEDCOM data"))) repo.set_type(rtype) self.dbase.add_repository(repo, self.trans) repo_ref = RepoRef() repo_ref.set_reference_handle(repo.handle) mtype = SourceMediaType() - mtype.set((SourceMediaType.UNKNOWN, '')) + mtype.set((SourceMediaType.UNKNOWN, "")) repo_ref.set_media_type(mtype) self.def_src.add_repo_reference(repo_ref) @@ -7371,8 +7803,7 @@ class GedcomParser(UpdateCallback): sattr.set_value(line.data) self.def_src.add_attribute(sattr) sub_state = CurrentState(level=state.level + 1) - self.__parse_level(sub_state, self.header_sour_data, - self.__undefined) + self.__parse_level(sub_state, self.header_sour_data, self.__undefined) state.msg += sub_state.msg def __header_sour_copr(self, line, state): @@ -7413,7 +7844,7 @@ class GedcomParser(UpdateCallback): @type state: CurrentState """ if self.use_def_src: - filename = os.path.basename(line.data).split('\\')[-1] + filename = os.path.basename(line.data).split("\\")[-1] # feature request 2356: avoid genitive form self.def_src.set_title(_("Import from %s") % filename) @@ -7454,7 +7885,7 @@ class GedcomParser(UpdateCallback): """ if self.use_def_src: sattr = SrcAttribute() - sattr.set_type(_('Submission record identifier')) + sattr.set_type(_("Submission record identifier")) sattr.set_value(line.token_text) self.def_src.add_attribute(sattr) @@ -7467,7 +7898,7 @@ class GedcomParser(UpdateCallback): """ if self.use_def_src: sattr = SrcAttribute() - sattr.set_type(_('Language of GEDCOM text')) + sattr.set_type(_("Language of GEDCOM text")) sattr.set_value(line.data) self.def_src.add_attribute(sattr) @@ -7489,10 +7920,13 @@ class GedcomParser(UpdateCallback): if self.genby.upper() == "LEGACY": fname = os.path.basename(self.filename) self.user.warn( - _("Import of GEDCOM file %(filename)s with DEST=%(by)s, " - "could cause errors in the resulting database!") % - {'filename': fname, 'by': self.genby}, - _("Look for nameless events.")) + _( + "Import of GEDCOM file %(filename)s with DEST=%(by)s, " + "could cause errors in the resulting database!" + ) + % {"filename": fname, "by": self.genby}, + _("Look for nameless events."), + ) def __header_char(self, line, state): """ @@ -7515,12 +7949,12 @@ class GedcomParser(UpdateCallback): if self.use_def_src: if version == "": sattr = SrcAttribute() - sattr.set_type(_('Character set')) + sattr.set_type(_("Character set")) sattr.set_value(encoding) self.def_src.add_attribute(sattr) else: sattr = SrcAttribute() - sattr.set_type(_('Character set and version')) + sattr.set_type(_("Character set and version")) sattr.set_value("%s %s" % (encoding, version)) self.def_src.add_attribute(sattr) @@ -7537,11 +7971,10 @@ class GedcomParser(UpdateCallback): break elif line.token == TOKEN_VERS: if (not line.data) or line.data[0] != "5": - self.__add_msg(_("GEDCOM version not supported"), - line, state) + self.__add_msg(_("GEDCOM version not supported"), line, state) if self.use_def_src: sattr = SrcAttribute() - sattr.set_type(_('GEDCOM version')) + sattr.set_type(_("GEDCOM version")) sattr.set_value(line.data) self.def_src.add_attribute(sattr) elif line.token == TOKEN_FORM: @@ -7550,13 +7983,12 @@ class GedcomParser(UpdateCallback): elif line.data.upper() == "LINEAGE-LINKED": # Allow Lineage-Linked etc. though it should be in # uppercase (Note: Gramps is not a validator! prc) - self.__add_msg(_("GEDCOM FORM should be in uppercase"), - line, state) + self.__add_msg(_("GEDCOM FORM should be in uppercase"), line, state) else: self.__add_msg(_("GEDCOM FORM not supported"), line, state) if self.use_def_src: sattr = SrcAttribute() - sattr.set_type(_('GEDCOM form')) + sattr.set_type(_("GEDCOM form")) sattr.set_value(line.data) self.def_src.add_attribute(sattr) @@ -7607,12 +8039,12 @@ class GedcomParser(UpdateCallback): if self.use_def_src: if tx_time == "": sattr = SrcAttribute() - sattr.set_type(_('Creation date of GEDCOM')) + sattr.set_type(_("Creation date of GEDCOM")) sattr.set_value(tx_date) self.def_src.add_attribute(sattr) else: sattr = SrcAttribute() - sattr.set_type(_('Creation date and time of GEDCOM')) + sattr.set_type(_("Creation date and time of GEDCOM")) sattr.set_value("%s %s" % (tx_date, tx_time)) self.def_src.add_attribute(sattr) @@ -7639,16 +8071,17 @@ class GedcomParser(UpdateCallback): def __parse_note(self, line, obj, state): if line.token == TOKEN_RNOTE: # reference to a named note defined elsewhere - #NOTE_STRUCTURE: = + # NOTE_STRUCTURE: = # n NOTE @@ {1:1} # +1 SOUR @@ {0:M} # 5.5 only, not in 5.5.1 handle = self.__find_note_handle(self.nid_map[line.data]) obj.add_note(handle) - self.note_type_map[handle] = OBJ_NOTETYPE.get(type(obj).__name__, - NoteType.GENERAL) + self.note_type_map[handle] = OBJ_NOTETYPE.get( + type(obj).__name__, NoteType.GENERAL + ) else: # Embedded note - #NOTE_STRUCTURE: = + # NOTE_STRUCTURE: = # n NOTE [ | ] {1:1} # +1 [ CONC | CONT ] {0:M} # +1 SOUR @@ {0:M} @@ -7662,23 +8095,23 @@ class GedcomParser(UpdateCallback): sub_state = CurrentState(level=state.level + 1) sub_state.note = new_note - self.__parse_level(sub_state, self.note_parse_tbl, - self.__undefined) + self.__parse_level(sub_state, self.note_parse_tbl, self.__undefined) state.msg += sub_state.msg # Add a default tag if provided self.__add_default_tag(new_note) # Set the type of the note - new_note.set_type(OBJ_NOTETYPE.get(type(obj).__name__, - NoteType.GENERAL)) + new_note.set_type( + OBJ_NOTETYPE.get(type(obj).__name__, NoteType.GENERAL) + ) self.dbase.commit_note(new_note, self.trans, new_note.change) obj.add_note(new_note.get_handle()) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # # NOTE parsing # - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def __parse_inline_note(self, line, level): """ @@ -7693,8 +8126,10 @@ class GedcomParser(UpdateCallback): +1 <> {0:1} """ state = CurrentState(level=1) - if not line.data and \ - self.nid_map.clean(line.token_text) not in self.nid_map.map(): + if ( + not line.data + and self.nid_map.clean(line.token_text) not in self.nid_map.map() + ): self.__add_msg(_("Empty note ignored"), line) self.__skip_subordinate_levels(level, state) else: @@ -7707,13 +8142,13 @@ class GedcomParser(UpdateCallback): new_note.set_type(self.note_type_map[handle]) sub_state = CurrentState(level=state.level) sub_state.note = new_note - self.__parse_level(sub_state, self.note_parse_tbl, - self.__undefined) + self.__parse_level(sub_state, self.note_parse_tbl, self.__undefined) state.msg += sub_state.msg self.dbase.commit_note(new_note, self.trans, new_note.change) - self.__check_msgs(_("NOTE Gramps ID %s") % - new_note.get_gramps_id(), state, None) + self.__check_msgs( + _("NOTE Gramps ID %s") % new_note.get_gramps_id(), state, None + ) def __note_chan(self, line, state): if state.note: @@ -7843,7 +8278,7 @@ class GedcomParser(UpdateCallback): elif line.token == TOKEN_TIME: tstr = line.data elif line.token == TOKEN_DATE: - #Lexer converted already to Date object + # Lexer converted already to Date object dobj = line.data elif line.token == TOKEN_NOTE or line.token == TOKEN_RNOTE: self.__ignore(line, state) @@ -7852,17 +8287,18 @@ class GedcomParser(UpdateCallback): # Attempt to convert the values to a valid change time if dobj: - dstr = "%s %s %s" % (dobj.get_day(), dobj.get_month(), - dobj.get_year()) + dstr = "%s %s %s" % (dobj.get_day(), dobj.get_month(), dobj.get_year()) try: if tstr: try: - tstruct = time.strptime("%s %s" % (dstr, tstr), - "%d %m %Y %H:%M:%S") + tstruct = time.strptime( + "%s %s" % (dstr, tstr), "%d %m %Y %H:%M:%S" + ) except ValueError: - #seconds is optional in GEDCOM - tstruct = time.strptime("%s %s" % (dstr, tstr), - "%d %m %Y %H:%M") + # seconds is optional in GEDCOM + tstruct = time.strptime( + "%s %s" % (dstr, tstr), "%d %m %Y %H:%M" + ) else: tstruct = time.strptime(dstr, "%d %m %Y") val = time.mktime(tstruct) @@ -7886,7 +8322,7 @@ class GedcomParser(UpdateCallback): @type obj: Gramps primary object """ attr = Attribute() - attr.set_type(line.token_text) # Atrribute : REFN + attr.set_type(line.token_text) # Atrribute : REFN attr.set_value(line.data) # if there is a subsequent TYPE, we add it as a note to the attribute line = self.__chk_subordinate(state.level + 1, state, TOKEN_TYPE) @@ -7894,7 +8330,7 @@ class GedcomParser(UpdateCallback): new_note = Note(line.data) new_note.set_gramps_id(self.nid_map[""]) new_note.set_handle(create_id()) - new_note.set_type('REFN-TYPE') + new_note.set_type("REFN-TYPE") self.dbase.commit_note(new_note, self.trans, new_note.change) attr.add_note(new_note.get_handle()) obj.attribute_list.append(attr) @@ -7917,7 +8353,7 @@ class GedcomParser(UpdateCallback): event.set_gramps_id(self.emapper.find_next()) event.set_type(event_type) - if description and description != 'Y': + if description and description != "Y": event.set_description(description) self.dbase.add_event(event, self.trans) @@ -7929,8 +8365,12 @@ class GedcomParser(UpdateCallback): sub_state.pf = self.place_parser self.__parse_level(sub_state, event_map, self.__undefined) - if(description == 'Y' and event.date.is_empty() and - event.type == EventType.BIRTH and not event.place): + if ( + description == "Y" + and event.date.is_empty() + and event.type == EventType.BIRTH + and not event.place + ): event.set_description(_("No Date Information")) state.msg += sub_state.msg @@ -7941,13 +8381,12 @@ class GedcomParser(UpdateCallback): event_ref.set_reference_handle(event.handle) return event_ref - def __build_family_event_pair(self, state, event_type, event_map, - description): + def __build_family_event_pair(self, state, event_type, event_map, description): event = Event() event_ref = EventRef() event.set_gramps_id(self.emapper.find_next()) event.set_type(event_type) - if description and description != 'Y': + if description and description != "Y": event.set_description(description) self.dbase.add_event(event, self.trans) @@ -7992,7 +8431,7 @@ class GedcomParser(UpdateCallback): This is run after all of the person processing is complete but before committing the person. """ - if state.photo.startswith('@'): + if state.photo.startswith("@"): gramps_id = self.oid_map[state.photo] handle = self.__find_media_handle(gramps_id) elif state.photo: @@ -8009,9 +8448,10 @@ class GedcomParser(UpdateCallback): state.person.media_list.insert(0, mref) def __extract_temple(self, line): - """ Determine the LDS Temple from the input line """ + """Determine the LDS Temple from the input line""" + def get_code(code): - """ get the Temple code """ + """get the Temple code""" if TEMPLES.is_valid_code(code): return code elif TEMPLES.is_valid_name(code): @@ -8109,11 +8549,11 @@ class GedcomParser(UpdateCallback): self.__repo_email(line, state) -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # GedcomStageOne # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class GedcomStageOne: """ The GedcomStageOne parser scans the file quickly, looking for a few things. @@ -8124,9 +8564,12 @@ class GedcomStageOne: 3. Child to family references, since Ancestry.com creates GEDCOM files without the FAMC references. """ - __BAD_UTF16 = _("Your GEDCOM file is corrupted. " - "The file appears to be encoded using the UTF16 " - "character set, but is missing the BOM marker.") + + __BAD_UTF16 = _( + "Your GEDCOM file is corrupted. " + "The file appears to be encoded using the UTF16 " + "character set, but is missing the BOM marker." + ) __EMPTY_GED = _("Your GEDCOM file is empty.") @staticmethod @@ -8135,7 +8578,7 @@ class GedcomStageOne: Return True if value is in the form of a XREF value. We assume that if we have a leading '@' character, then we are okay. """ - return value and value[0] == '@' + return value and value[0] == "@" def __init__(self, ifile): self.ifile = ifile @@ -8160,21 +8603,24 @@ class GedcomStageOne: if line == b"\xef\xbb": input_file.read(1) self.enc = "utf_8_sig" - return TextIOWrapper(input_file, encoding='utf_8_sig', - errors='replace', newline=None) + return TextIOWrapper( + input_file, encoding="utf_8_sig", errors="replace", newline=None + ) elif line == b"\xff\xfe" or line == b"\xfe\xff": self.enc = "UTF16" input_file.seek(0) - return TextIOWrapper(input_file, encoding='utf_16', - errors='replace', newline=None) + return TextIOWrapper( + input_file, encoding="utf_16", errors="replace", newline=None + ) elif not line: raise GedcomError(self.__EMPTY_GED) elif line == b"\x30\x00" or line == b"\x00\x30": raise GedcomError(self.__BAD_UTF16) else: input_file.seek(0) - return TextIOWrapper(input_file, encoding='utf-8', - errors='replace', newline=None) + return TextIOWrapper( + input_file, encoding="utf-8", errors="replace", newline=None + ) def parse(self): """ @@ -8193,7 +8639,7 @@ class GedcomStageOne: self.lcnt += 1 try: - data = line.split(None, 3) + [''] + data = line.split(None, 3) + [""] (level, key, value) = data[:3] level = int(level) key = key.strip() @@ -8201,17 +8647,16 @@ class GedcomStageOne: except: continue - if level == 0 and key[0] == '@': + if level == 0 and key[0] == "@": if value in ("FAM", "FAMILY"): current_family_id = key.strip()[1:-1] elif value in ("INDI", "INDIVIDUAL"): self.pcnt += 1 - elif key in ("HUSB", "HUSBAND", "WIFE") and \ - self.__is_xref_value(value): + elif key in ("HUSB", "HUSBAND", "WIFE") and self.__is_xref_value(value): self.fams[value[1:-1]].append(current_family_id) elif key in ("CHIL", "CHILD") and self.__is_xref_value(value): self.famc[value[1:-1]].append(current_family_id) - elif key == 'CHAR' and not self.enc: + elif key == "CHAR" and not self.enc: assert isinstance(value, str) self.enc = value LOG.debug("parse pcnt %d", self.pcnt) @@ -8257,11 +8702,11 @@ class GedcomStageOne: return self.lcnt -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # # make_gedcom_date # -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- def make_gedcom_date(subdate, calendar, mode, quality): """ Convert a Gramps date structure into a GEDCOM compatible date. @@ -8307,13 +8752,13 @@ def __build_date_string(day, mon, year, bce, mmap): """ if day == 0: if mon == 0: - retval = '%d%s' % (year, bce) + retval = "%d%s" % (year, bce) elif year == 0: - retval = '(%s)' % mmap[mon] + retval = "(%s)" % mmap[mon] else: retval = "%s %d%s" % (mmap[mon], year, bce) elif mon == 0: - retval = '%d%s' % (year, bce) + retval = "%d%s" % (year, bce) elif year == 0: retval = "(%d %s)" % (day, mmap[mon]) else: