8537: Gedcom import crashes; kulath patch

This commit is contained in:
Doug Blank 2015-06-17 07:59:19 -04:00
parent 273a5f986f
commit 5828dd3aa8

View File

@ -2004,6 +2004,7 @@ class GedcomParser(UpdateCallback):
self.default_tag = None self.default_tag = None
self.dir_path = os.path.dirname(filename) self.dir_path = os.path.dirname(filename)
self.is_ftw = False self.is_ftw = False
self.addr_is_detail = False
self.groups = None self.groups = None
self.want_parse_warnings = True self.want_parse_warnings = True
@ -3018,23 +3019,32 @@ class GedcomParser(UpdateCallback):
return place return place
return None return None
def __create_place(self, title, location): def __add_place(self, event, sub_state):
""" """
Create a new place based on the title and primary location. Add a new place to an event if not already present, or update a
place.
@param title: The place title @param event: The event
@type title: string @type event: gen.lib.Event
@param location: The current location @param substate: The sub-state for PLAC or ADDR elements (i.e. parsed by
@type location: gen.lib.Location event_parse_tbl)
@return gen.lib.Place @type sub_state: CurrentState
""" """
place = Place() if sub_state.place:
place.set_title(title) # see whether this place already exists
if location: place = self.__find_place(sub_state.place.get_title(),
place.add_alternate_locations(location) self.__get_first_loc(sub_state.place))
self.dbase.add_place(place, self.trans) if place is None:
self.place_names[title].append(place.get_handle()) place = sub_state.place
return place self.dbase.add_place(place, self.trans)
self.place_names[place.get_title()].append(place.get_handle())
event.set_place_handle(place.get_handle())
else:
place.merge(sub_state.place)
self.dbase.commit_place(place, self.trans)
event.set_place_handle(place.get_handle())
place_title = place_displayer.display(self.dbase, place)
sub_state.pf.load_place(self.place_import, place, place_title)
def __find_file(self, fullname, altpath): def __find_file(self, fullname, altpath):
tries = [] tries = []
@ -3945,10 +3955,13 @@ class GedcomParser(UpdateCallback):
sub_state.level = state.level+1 sub_state.level = state.level+1
sub_state.event = event sub_state.event = event
sub_state.event_ref = event_ref sub_state.event_ref = event_ref
sub_state.pf = self.place_parser
self.__parse_level(sub_state, self.event_parse_tbl, self.__undefined) self.__parse_level(sub_state, self.event_parse_tbl, self.__undefined)
state.msg += sub_state.msg state.msg += sub_state.msg
self.__add_place(event, sub_state)
self.dbase.commit_event(event, self.trans) self.dbase.commit_event(event, self.trans)
event_ref.ref = event.handle event_ref.ref = event.handle
state.person.add_event_ref(event_ref) state.person.add_event_ref(event_ref)
@ -4150,10 +4163,13 @@ class GedcomParser(UpdateCallback):
sub_state.level = state.level+1 sub_state.level = state.level+1
sub_state.event = event sub_state.event = event
sub_state.event_ref = event_ref sub_state.event_ref = event_ref
sub_state.pf = self.place_parser
self.__parse_level(sub_state, self.event_parse_tbl, self.__undefined) self.__parse_level(sub_state, self.event_parse_tbl, self.__undefined)
state.msg += sub_state.msg state.msg += sub_state.msg
self.__add_place(event, sub_state)
self.dbase.add_event(event, self.trans) self.dbase.add_event(event, self.trans)
event_ref.ref = event.handle event_ref.ref = event.handle
state.person.add_event_ref(event_ref) state.person.add_event_ref(event_ref)
@ -4602,11 +4618,14 @@ class GedcomParser(UpdateCallback):
try: try:
title = line.data title = line.data
place = self.__find_place(title, None) place = self.__find_place(title, None)
if place: if place is None:
state.place = place place = Place()
place.set_title(title)
self.dbase.add_place(place, self.trans)
self.place_names[place.get_title()].append(place.get_handle())
else: else:
state.place = self.__create_place(title, None) pass
state.lds_ord.set_place_handle(state.place.handle) state.lds_ord.set_place_handle(place.handle)
except NameError: except NameError:
return return
@ -4970,10 +4989,13 @@ class GedcomParser(UpdateCallback):
sub_state.level = state.level+1 sub_state.level = state.level+1
sub_state.event = event sub_state.event = event
sub_state.event_ref = event_ref sub_state.event_ref = event_ref
sub_state.pf = self.place_parser
self.__parse_level(sub_state, self.event_parse_tbl, self.__undefined) self.__parse_level(sub_state, self.event_parse_tbl, self.__undefined)
state.msg += sub_state.msg state.msg += sub_state.msg
self.__add_place(event, sub_state)
if event.type == EventType.MARRIAGE: if event.type == EventType.MARRIAGE:
descr = event.get_description() descr = event.get_description()
if descr == "Civil Union": if descr == "Civil Union":
@ -5013,9 +5035,12 @@ class GedcomParser(UpdateCallback):
sub_state.level = state.level+1 sub_state.level = state.level+1
sub_state.event = event sub_state.event = event
sub_state.event_ref = event_ref sub_state.event_ref = event_ref
sub_state.pf = self.place_parser
self.__parse_level(sub_state, self.event_parse_tbl, self.__undefined) self.__parse_level(sub_state, self.event_parse_tbl, self.__undefined)
state.msg += sub_state.msg state.msg += sub_state.msg
self.__add_place(event, sub_state)
self.dbase.commit_event(event, self.trans) self.dbase.commit_event(event, self.trans)
event_ref.ref = event.handle event_ref.ref = event.handle
@ -5444,65 +5469,30 @@ class GedcomParser(UpdateCallback):
state.event.set_description(line.data) state.event.set_description(line.data)
else: else:
title = line.data title = line.data
place_handle = state.event.get_place_handle() place = state.place
if place_handle: if place:
# We encounter a PLAC, having previously encountered an ADDR # We encounter a PLAC, having previously encountered an ADDR
old_place = self.dbase.get_place_from_handle(place_handle) if place.get_title() and place.get_title() != "":
old_title = old_place.get_title()
location = self.__get_first_loc(old_place)
if old_title != "":
# We have previously found a PLAC # We have previously found a PLAC
self.__add_msg(_("A second PLAC ignored"), line, state) self.__add_msg(_("A second PLAC ignored"), line, state)
# ignore this second PLAC, and use the old one # ignore this second PLAC, and use the old one
title = old_title
place = old_place
else: else:
# This is the first PLAC # This is the first PLAC
refs = list(self.dbase.find_backlink_handles(place_handle)) place.set_title(line.data)
# We haven't commited the event yet, so the place will not
# be linked to it. If there are any refs they will be from
# other events (etc)
if len(refs) == 0:
place = self.__find_place(title, location)
if place is None:
place = old_place
place.set_title(title)
self.place_names[old_title].remove(place_handle)
self.place_names[title].append(place_handle)
else:
place.merge(old_place)
self.place_import.remove_location(old_place.handle)
self.dbase.remove_place(place_handle, self.trans)
self.place_names[old_title].remove(place_handle)
else:
place = self.__find_place(title, location)
if place is None:
place = self.__create_place(title, location)
else:
pass
else: else:
# The first thing we encounter is PLAC # The first thing we encounter is PLAC
location = None state.place = Place()
place = self.__find_place(title, location) place = state.place
if place is None: place.set_title(line.data)
place = self.__create_place(title, location)
state.event.set_place_handle(place.handle)
sub_state = CurrentState() sub_state = CurrentState()
sub_state.place = place sub_state.place = place
sub_state.level = state.level+1 sub_state.level = state.level+1
sub_state.pf = self.place_parser
self.__parse_level(sub_state, self.event_place_map, self.__parse_level(sub_state, self.event_place_map,
self.__undefined) self.__undefined)
state.msg += sub_state.msg state.msg += sub_state.msg
place_title = place_displayer.display(self.dbase, place)
sub_state.pf.load_place(self.place_import, place, place_title)
self.dbase.commit_place(place, self.trans)
def __event_place_note(self, line, state): def __event_place_note(self, line, state):
""" """
@param line: The current line in GedLine format @param line: The current line in GedLine format
@ -5611,55 +5601,53 @@ class GedcomParser(UpdateCallback):
self.__merge_address(free_form, sub_state.location, line, state) self.__merge_address(free_form, sub_state.location, line, state)
location = sub_state.location location = sub_state.location
place_handle = state.event.get_place_handle()
if place_handle: if self.addr_is_detail and state.place:
# We encounter an ADDR having previously encountered a PLAC # Commit the enclosing place
old_place = self.dbase.get_place_from_handle(place_handle) place = self.__find_place(state.place.get_title(), None)
title = old_place.get_title()
if len(old_place.get_alternate_locations()) != 0 and \
not self.__get_first_loc(old_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)
# ignore this second ADDR, and use the old one
location = self.__get_first_loc(old_place)
place = old_place
else:
# This is the first ADDR
refs = list(self.dbase.find_backlink_handles(place_handle))
# We haven't commited the event yet, so the place will not be
# linked to it. If there are any refs they will be from other
# events (etc)
if len(refs) == 0:
place = self.__find_place(title, location)
if place is None:
place = old_place
self.__add_location(place, location)
else:
place.merge(old_place)
self.place_import.remove_location(old_place.handle)
self.dbase.remove_place(place_handle, self.trans)
self.place_names[title].remove(place_handle)
else:
place = self.__find_place(title, location)
if place is None:
place = self.__create_place(title, location)
else:
pass
else:
# The first thing we encounter is ADDR
title = ""
place = self.__find_place(title, location)
if place is None: if place is None:
place = self.__create_place(title, location) place = state.place
self.dbase.add_place(place, self.trans)
self.place_names[place.get_title()].append(place.get_handle())
else:
place.merge(state.place)
self.dbase.commit_place(place, self.trans)
place_title = place_displayer.display(self.dbase, place)
state.pf.load_place(self.place_import, place, place_title)
# Create the Place Details (it is committed with the event)
place_detail = Place()
place_detail.set_name(location.get_street())
place_detail.set_title(location.get_street())
# For RootsMagic etc. Place Details e.g. address, hospital, cemetary
place_detail.set_type((PlaceType.CUSTOM, _("Detail")))
placeref = PlaceRef()
placeref.ref = place.get_handle()
place_detail.set_placeref_list([placeref])
state.place = place_detail
else:
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():
# We have perviously found an ADDR, or have populated location
# from PLAC title
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
place.add_alternate_locations(location)
else:
# The first thing we encounter is ADDR
state.place = Place()
place = state.place
place.add_alternate_locations(location)
# merge notes etc into place # merge notes etc into place
place.merge(sub_state.place) place.merge(sub_state.place)
state.event.set_place_handle(place.get_handle())
self.dbase.commit_place(place, self.trans)
def __add_location(self, place, location): def __add_location(self, place, location):
""" """
@param place: A place object we have found or created @param place: A place object we have found or created
@ -5691,12 +5679,10 @@ class GedcomParser(UpdateCallback):
@param state: The current state @param state: The current state
@type state: CurrentState @type state: CurrentState
""" """
place_handle = state.event.get_place_handle() place = state.place
if place_handle: if place:
place = self.dbase.get_place_from_handle(place_handle)
codes = [place.get_code(), line.data] codes = [place.get_code(), line.data]
place.set_code(' '.join(code for code in codes if code)) place.set_code(' '.join(code for code in codes if code))
self.dbase.commit_place(place, self.trans)
def __event_privacy(self, line, state): def __event_privacy(self, line, state):
""" """
@ -7008,6 +6994,11 @@ class GedcomParser(UpdateCallback):
self.gedsource = self.gedmap.get_from_source_tag(line.data) self.gedsource = self.gedmap.get_from_source_tag(line.data)
if line.data.strip() in ["FTW", "FTM"]: if line.data.strip() in ["FTW", "FTM"]:
self.is_ftw = True self.is_ftw = True
# 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']:
self.addr_is_detail = True
# We will use the approved system ID as the name of the generating # 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 # software, in case we do not get the name in the proper place
self.genby = line.data self.genby = line.data
@ -7659,9 +7650,13 @@ class GedcomParser(UpdateCallback):
sub_state.event_ref = event_ref sub_state.event_ref = event_ref
sub_state.event = event sub_state.event = event
sub_state.person = state.person sub_state.person = state.person
sub_state.pf = self.place_parser
self.__parse_level(sub_state, event_map, self.__undefined) self.__parse_level(sub_state, event_map, self.__undefined)
state.msg += sub_state.msg state.msg += sub_state.msg
self.__add_place(event, sub_state)
self.dbase.commit_event(event, self.trans) self.dbase.commit_event(event, self.trans)
event_ref.set_reference_handle(event.handle) event_ref.set_reference_handle(event.handle)
@ -7683,10 +7678,13 @@ class GedcomParser(UpdateCallback):
sub_state.level = state.level+1 sub_state.level = state.level+1
sub_state.event = event sub_state.event = event
sub_state.event_ref = event_ref sub_state.event_ref = event_ref
sub_state.pf = self.place_parser
self.__parse_level(sub_state, event_map, self.__undefined) self.__parse_level(sub_state, event_map, self.__undefined)
state.msg += sub_state.msg state.msg += sub_state.msg
self.__add_place(event, sub_state)
self.dbase.commit_event(event, self.trans) self.dbase.commit_event(event, self.trans)
event_ref.set_reference_handle(event.handle) event_ref.set_reference_handle(event.handle)
return event_ref return event_ref