1# -*- coding: utf-8 -*- 2# 3# Gramps - a GTK+/GNOME based genealogy program 4# 5# Copyright (C) 2000-2006 Martin Hawlisch, Donald N. Allingham 6# Copyright (C) 2008 Brian G. Matherly 7# Copyright (C) 2010 Jakim Friant 8# 9# This program is free software; you can redistribute it and/or modify 10# it under the terms of the GNU General Public License as published by 11# the Free Software Foundation; either version 2 of the License, or 12# (at your option) any later version. 13# 14# This program is distributed in the hope that it will be useful, 15# but WITHOUT ANY WARRANTY; without even the implied warranty of 16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17# GNU General Public License for more details. 18# 19# You should have received a copy of the GNU General Public License 20# along with this program; if not, write to the Free Software 21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22# 23 24""" 25Validate localized date parser and displayer. 26 27Tools/Debug/Check Localized Date Parser and Displayer 28""" 29 30#------------------------------------------------------------------------- 31# 32# standard python modules 33# 34#------------------------------------------------------------------------- 35import traceback 36import sys 37from gramps.gen.const import GRAMPS_LOCALE as glocale 38_ = glocale.translation.gettext 39 40#------------------------------------------------------------------------- 41# 42# Gramps modules 43# 44#------------------------------------------------------------------------- 45from gramps.gen.lib import Date, Event, EventRef, EventType, Name, Person, Surname, Tag 46from gramps.gen.db import DbTxn 47from gramps.gui.plug import tool 48from gramps.gui.utils import ProgressMeter 49from gramps.gui.dialog import QuestionDialog 50from gramps.gen.datehandler import parser as _dp 51from gramps.gen.datehandler import displayer as _dd 52 53#------------------------------------------------------------------------- 54# 55# 56# 57#------------------------------------------------------------------------- 58class DateParserDisplayTest(tool.Tool): 59 60 def __init__(self, dbstate, user, options_class, name, callback=None): 61 uistate = user.uistate 62 63 tool.Tool.__init__(self, dbstate, options_class, name) 64 if uistate: 65 # Running with gui -> Show message 66 self.parent_window = uistate.window 67 QuestionDialog(_("Start date test?"), 68 _("This test will create many persons and events " \ 69 "in the current database. Do you really want to " \ 70 "run this test?"), 71 _("Run test"), 72 self.run_tool, 73 parent=self.parent_window) 74 else: 75 self.parent_window = None 76 self.run_tool() 77 78 79 def run_tool(self): 80 self.progress = ProgressMeter(_('Running Date Test'), '', 81 parent=self.parent_window) 82 self.progress.set_pass(_('Generating dates'), 83 4) 84 dates = [] 85 # first some valid dates 86 calendar = Date.CAL_GREGORIAN 87 for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, 88 Date.QUAL_CALCULATED): 89 for modifier in (Date.MOD_NONE, Date.MOD_BEFORE, 90 Date.MOD_AFTER, Date.MOD_ABOUT): 91 for slash1 in (False,True): 92 for month in range(0,13): 93 for day in (0,5,27): 94 if not month and day: 95 continue 96 d = Date() 97 d.set(quality,modifier,calendar,(day,month,1789,slash1),"Text comment") 98 dates.append( d) 99 for modifier in (Date.MOD_RANGE, Date.MOD_SPAN): 100 for slash1 in (False,True): 101 for slash2 in (False,True): 102 for month in range(0,13): 103 for day in (0,5,27): 104 if not month and day: 105 continue 106 107 d = Date() 108 d.set(quality,modifier,calendar,(day,month,1789,slash1,day,month,1876,slash2),"Text comment") 109 dates.append( d) 110 111 if not month: 112 continue 113 114 d = Date() 115 d.set(quality,modifier,calendar,(day,month,1789,slash1,day,13-month,1876,slash2),"Text comment") 116 dates.append( d) 117 118 if not day: 119 continue 120 121 d = Date() 122 d.set(quality,modifier,calendar,(day,month,1789,slash1,32-day,month,1876,slash2),"Text comment") 123 dates.append( d) 124 d = Date() 125 d.set(quality,modifier,calendar,(day,month,1789,slash1,32-day,13-month,1876,slash2),"Text comment") 126 dates.append( d) 127 modifier = Date.MOD_TEXTONLY 128 d = Date() 129 d.set(quality,modifier,calendar,Date.EMPTY, 130 "This is a textual date") 131 dates.append( d) 132 self.progress.step() 133 134 # test invalid dates 135 #dateval = (4,7,1789,False,5,8,1876,False) 136 #for l in range(1,len(dateval)): 137 # d = Date() 138 # try: 139 # d.set(Date.QUAL_NONE,Date.MOD_NONE, 140 # Date.CAL_GREGORIAN,dateval[:l],"Text comment") 141 # dates.append( d) 142 # except DateError, e: 143 # d.set_as_text("Date identified value correctly as invalid.\n%s" % e) 144 # dates.append( d) 145 # except: 146 # d = Date() 147 # d.set_as_text("Date.set Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),)) 148 # dates.append( d) 149 #for l in range(1,len(dateval)): 150 # d = Date() 151 # try: 152 # d.set(Date.QUAL_NONE,Date.MOD_SPAN,Date.CAL_GREGORIAN,dateval[:l],"Text comment") 153 # dates.append( d) 154 # except DateError, e: 155 # d.set_as_text("Date identified value correctly as invalid.\n%s" % e) 156 # dates.append( d) 157 # except: 158 # d = Date() 159 # d.set_as_text("Date.set Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),)) 160 # dates.append( d) 161 #self.progress.step() 162 #d = Date() 163 #d.set(Date.QUAL_NONE,Date.MOD_NONE, 164 # Date.CAL_GREGORIAN,(44,7,1789,False),"Text comment") 165 #dates.append( d) 166 #d = Date() 167 #d.set(Date.QUAL_NONE,Date.MOD_NONE, 168 # Date.CAL_GREGORIAN,(4,77,1789,False),"Text comment") 169 #dates.append( d) 170 #d = Date() 171 #d.set(Date.QUAL_NONE,Date.MOD_SPAN, 172 # Date.CAL_GREGORIAN, 173 # (4,7,1789,False,55,8,1876,False),"Text comment") 174 #dates.append( d) 175 #d = Date() 176 #d.set(Date.QUAL_NONE,Date.MOD_SPAN, 177 # Date.CAL_GREGORIAN, 178 # (4,7,1789,False,5,88,1876,False),"Text comment") 179 #dates.append( d) 180 181 with DbTxn(_("Date Test Plugin"), self.db, batch=True) as self.trans: 182 self.db.disable_signals() 183 self.progress.set_pass(_('Generating dates'), 184 len(dates)) 185 186 # create pass and fail tags 187 pass_handle = self.create_tag(_('Pass'), '#0000FFFF0000') 188 fail_handle = self.create_tag(_('Fail'), '#FFFF00000000') 189 190 # now add them as birth to new persons 191 i = 1 192 for dateval in dates: 193 person = Person() 194 surname = Surname() 195 surname.set_surname("DateTest") 196 name = Name() 197 name.add_surname(surname) 198 name.set_first_name("Test %d" % i) 199 person.set_primary_name(name) 200 self.db.add_person(person, self.trans) 201 bevent = Event() 202 bevent.set_type(EventType.BIRTH) 203 bevent.set_date_object(dateval) 204 bevent.set_description("Date Test %d (source)" % i) 205 bevent_h = self.db.add_event(bevent, self.trans) 206 bevent_ref = EventRef() 207 bevent_ref.set_reference_handle(bevent_h) 208 # for the death event display the date as text and parse it back to a new date 209 ndate = None 210 try: 211 datestr = _dd.display( dateval) 212 try: 213 ndate = _dp.parse( datestr) 214 if not ndate: 215 ndate = Date() 216 ndate.set_as_text("DateParser None") 217 person.add_tag(fail_handle) 218 else: 219 person.add_tag(pass_handle) 220 except: 221 ndate = Date() 222 ndate.set_as_text("DateParser Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),)) 223 person.add_tag(fail_handle) 224 else: 225 person.add_tag(pass_handle) 226 except: 227 ndate = Date() 228 ndate.set_as_text("DateDisplay Exception: %s" % ("".join(traceback.format_exception(*sys.exc_info())),)) 229 person.add_tag(fail_handle) 230 231 if dateval.get_modifier() != Date.MOD_TEXTONLY \ 232 and ndate.get_modifier() == Date.MOD_TEXTONLY: 233 # parser was unable to correctly parse the string 234 ndate.set_as_text( "TEXTONLY: "+ndate.get_text()) 235 person.add_tag(fail_handle) 236 if dateval.get_modifier() == Date.MOD_TEXTONLY \ 237 and dateval.get_text().count("Traceback") \ 238 and pass_handle in person.get_tag_list(): 239 person.add_tag(fail_handle) 240 241 devent = Event() 242 devent.set_type(EventType.DEATH) 243 devent.set_date_object(ndate) 244 devent.set_description("Date Test %d (result)" % i) 245 devent_h = self.db.add_event(devent, self.trans) 246 devent_ref = EventRef() 247 devent_ref.set_reference_handle(devent_h) 248 person.set_birth_ref(bevent_ref) 249 person.set_death_ref(devent_ref) 250 self.db.commit_person(person, self.trans) 251 i = i + 1 252 self.progress.step() 253 self.db.enable_signals() 254 self.db.request_rebuild() 255 self.progress.close() 256 257 def create_tag(self, tag_name, tag_color): 258 """ 259 Create a tag if it doesn't already exist. 260 """ 261 tag = self.db.get_tag_from_name(tag_name) 262 if tag is None: 263 tag = Tag() 264 tag.set_name(tag_name) 265 if tag_color is not None: 266 tag.set_color(tag_color) 267 tag.set_priority(self.db.get_number_of_tags()) 268 tag_handle = self.db.add_tag(tag, self.trans) 269 else: 270 tag_handle = tag.get_handle() 271 return tag_handle 272 273#------------------------------------------------------------------------ 274# 275# DateParserDisplayTestOptions 276# 277#------------------------------------------------------------------------ 278class DateParserDisplayTestOptions(tool.ToolOptions): 279 """ 280 Defines options and provides handling interface. 281 """ 282 def __init__(self, name, person_id=None): 283 """ Initialize the options class """ 284 tool.ToolOptions.__init__(self, name, person_id) 285