diff --git a/src/GrampsDbUtils/_ReadXML.py b/src/GrampsDbUtils/_ReadXML.py index aef00c24a..3afcd4728 100644 --- a/src/GrampsDbUtils/_ReadXML.py +++ b/src/GrampsDbUtils/_ReadXML.py @@ -30,10 +30,6 @@ import sys from xml.parsers.expat import ExpatError, ParserCreate from gettext import gettext as _ import re -try: - set() -except NameError: - from sets import Set as set #------------------------------------------------------------------------- # @@ -356,16 +352,8 @@ class GrampsParser(UpdateCallback): self.childref_map = {} self.change = change self.dp = DateHandler.parser - self.place_names = set() self.info = ImportInfo() self.all_abs = True - cursor = database.get_place_cursor() - data = cursor.next() - while data: - (handle, val) = data - self.place_names.add(val[2]) - data = cursor.next() - cursor.close() self.ord = None self.objref = None @@ -1898,9 +1886,6 @@ class GrampsParser(UpdateCallback): loc = self.placeobj.get_main_location() self.placeobj.title = build_place_title(loc) - # if self.placeobj.title in self.place_names: - # self.placeobj.title += " [%s]" % self.placeobj.gramps_id - self.db.commit_place(self.placeobj, self.trans, self.placeobj.get_change_time()) self.placeobj = None diff --git a/src/PlaceUtils.py b/src/PlaceUtils.py index 7859626c3..b5e95e117 100644 --- a/src/PlaceUtils.py +++ b/src/PlaceUtils.py @@ -30,6 +30,7 @@ # #------------------------------------------------------------------------- from gettext import gettext as _ +import locale #------------------------------------------------------------------------- @@ -97,6 +98,177 @@ def conv_lat_lon(latitude, longitude, format="D.D4"): and -180 180th meridian """ + #------------------------------------------------------------------------- + # begin internal function testing whether a string is convertable to float + #------------------------------------------------------------------------- + def isFloat(stringValue) : + try : + v = float(stringValue) #decimal notation, now float + return True + except ValueError : + return False; + #------------------------------------------------------------------------- + # end internal function testing whether a string is convertable to float + #------------------------------------------------------------------------- + + #------------------------------------------------------------------------- + # begin internal function which converts a structure to a nice + # representation + #------------------------------------------------------------------------- + def convert_structure_to_float(sign, degs, mins=0.0, secs=0.0) : + v = float(degs) + if mins != None: + v += float(mins) / 60. + if secs != None: + v += secs / 3600. + if sign == "-": + v = v * -1. + + return v + + #------------------------------------------------------------------------- + # end internal function which converts a structure to a nice + # representation + #------------------------------------------------------------------------- + + + #------------------------------------------------------------------------- + # begin internal function that tries to convert the string using the float + # representation + #------------------------------------------------------------------------- + def convert_using_float_representation(stringValue): + if isFloat(stringValue) : + return float(stringValue) #decimal notation, now float + else : + return None + #------------------------------------------------------------------------- + # end internal function that tries to convert the string using the float + # representation + #------------------------------------------------------------------------- + + #------------------------------------------------------------------------- + # begin internal function that tries to convert the string using the colon + # representation + #------------------------------------------------------------------------- + def convert_using_colon_representation(stringValue): + if stringValue.find(r':') == -1 : + return None + + l = stringValue.split(':') + if len(l) < 2 or len(l) > 3: + return None + l[0]=l[0].strip() + if l[0][0] == '-': + sign = '-' + l[0]=l[0][1:] + else: + sign = '+' + try: + degs = int(l[0]) + if degs < 0: + return None + except: + return None + try: + mins = int(l[1]) + if mins < 0 or mins >= 60: + return None + except: + return None + secs=0. + if len(l) == 3: + try: + secs = float(l[2]) + if secs < 0. or secs >= 60.: + return None + except: + return None + + return convert_structure_to_float(sign, degs, mins, secs) + #------------------------------------------------------------------------- + # end internal function that tries to convert the string using the colon + # representation + #------------------------------------------------------------------------- + + #------------------------------------------------------------------------- + # begin internal function that tries to convert the string using the colon + # representation + #------------------------------------------------------------------------- + def convert_using_classic_representation(stringValue, typedeg): + if stringValue.find(r'_') != -1: + return None # not a valid lat or lon + + #exchange some characters + stringValue = stringValue.replace( r'°',r'_') + #allow to input ° as # + stringValue = stringValue.replace( r'#',r'_') + #allow to input " as '' + stringValue = stringValue.replace( r"''",r'"') + #allow some special unicode symbols + stringValue = stringValue.replace( u'\u2033',r'"') + stringValue = stringValue.replace( u'\u2032',r"'") + #ignore white spaces (HACK: use regular expressions instead) + stringValue = stringValue.replace(r' ', r'') + stringValue = stringValue.replace(r'\t', r'') + + # get the degrees, must be present + if stringValue.find(r'_') == -1: + return None + l = stringValue.split('_') + if len(l) != 2: + return None + + try: + degs = int(l[0]) #degrees must be integer value + if degs < 0: + return None + except: + return None + # next: minutes might be present once + l2 = l[1].split(r"'") + l3 = l2 + mins = 0 + if len(l2) > 2: + return None + if len(l2) == 2: + l3 = [l2[1],] + try: + mins = int(l2[0]) #minutes must be integer value + if mins < 0 or mins >= 60: + return None + except: + return None + # next: seconds might be present once + l3 = l3[0].split(r'"') + last = l3[0] + secs = 0. + if len(l3) > 2: + return None + if len(l3) == 2: + last = l3[1] + try: + secs = float(l3[0]) + if secs < 0. or secs >= 60.: + return None + except: + return None + # last entry should be the direction + if typedeg == 'lat': + if last == 'N': + sign = '+' + elif last == 'S': + sign = '-' + else: + return None + if typedeg == 'lon': + if last == 'E': + sign = '+' + elif last == 'W': + sign = '-' + else: + return None + + return convert_structure_to_float(sign, degs, mins, secs) #------------------------------------------------------------------------- # begin internal function converting one input to float #------------------------------------------------------------------------- @@ -107,153 +279,39 @@ def conv_lat_lon(latitude, longitude, format="D.D4"): # In case of degree minutes seconds direction input, # it is checked that degree >0, 0<= minutes <= 60, # 0<= seconds <= 60, direction is in the directions dic. - v = None - sign = None - secs = None - mins = None - degs = None - error = False #change , to . so that , input works in non , localization #this is no problem, as a number like 100,000.20 cannot appear in #lat/lon - try : - test = float('10,11') - except ValueError : - #change 10,11 into 10.11 + pointchar = locale.localeconv()['decimal_point'] + if pointchar == '.' : + #change XX,YY into XX.YY #if point is already present in val, we can do nothing if val.find(r'.') == -1 : val = val.replace( r',',r'.') - try : - test = float('10.11') - except ValueError : - #change 10.11 into 10,11 + elif pointchar == ',' : + #change XX.YY into XX,YY #if comma is already present in val, we can do nothing if val.find(r',') == -1 : val = val.replace( r'.',r',') - - try: - v = float(val) #decimal notation, now float - except ValueError: - # look for : notation - if val.find(r':') != -1 : - l = val.split(':') - if len(l) < 2 or len(l) > 3: - error = True - l[0]=l[0].strip() - if l[0][0] == '-': - sign = '-' - l[0]=l[0][1:] - else: - sign = '+' - try: - degs = int(l[0]) - if degs < 0: - error = True - except: - error = True - try: - mins = int(l[1]) - if mins < 0 or mins >= 60: - error = True - except: - error = True - secs=0. - if len(l) == 3: - try: - secs = float(l[2]) - if secs < 0. or secs >= 60.: - error = True - except: - error = True - - # if nothing found yet, look for classical notation - if val.find(r'_') != -1: - error = True # not a valid lat or lon - val = val.replace( r'°',r'_') - #allow to input ° as # - val = val.replace( r'#',r'_') - #allow to input " as '' - val = val.replace( r"''",r'"') - #allow some special unicode symbols - val = val.replace( u'\u2033',r'"') - val = val.replace( u'\u2032',r"'") - #ignore spaces - val = val.replace(r'\s*', r'') - # get the degrees, must be present - if val.find(r'_') != -1: - l = val.split('_') - if len(l) != 2: - error = True - else: - try: - degs = int(l[0]) #degrees must be integer value - if degs < 0: - error = True - except: - error = True - # next: minutes might be present once - l2 = l[1].split(r"'") - l3 = l2 - mins = 0 - if len(l2) > 2: - error = True - if len(l2) == 2: - l3 = [l2[1],] - try: - mins = int(l2[0]) #minutes must be integer value - if mins < 0 or mins >= 60: - error = True - except: - error = True - # next: seconds might be present once - l3 = l3[0].split(r'"') - last = l3[0] - secs = 0. - if len(l3) > 2: - error = True - if len(l3) == 2: - last = l3[1] - try: - secs = float(l3[0]) - if secs < 0. or secs >= 60.: - error = True - except: - error = True - # last entry should be the direction - last = last.strip() #remove leading/trailing spaces - if typedeg == 'lat': - if last == 'N': - sign = '+' - elif last == 'S': - sign = '-' - else: - error = True - if typedeg == 'lon': - if last == 'E': - sign = '+' - elif last == 'W': - sign = '-' - else: - error = True - # degs should have a value now - if degs == None: - error = True - - if error: - return None + + # format: XX.YYYY + v = convert_using_float_representation(val) if v != None: return v - #we have a degree notation, convert to float - v = float(degs) - if secs != None: - v += secs / 3600. - if mins != None: - v += float(mins) / 60. - if sign =="-": - v = v * -1. - return v + # format: XX:YY:ZZ + v = convert_using_colon_representation(val) + if v != None : + return v + + # format: XX° YY' ZZ" [NSWE] + v = convert_using_classic_representation(val, typedeg) + if v != None : + return v + + # no format succeeded + return None #------------------------------------------------------------------------- # end internal function converting one input to float #-------------------------------------------------------------------------