diff --git a/src/Merge/mergeevent.py b/src/Merge/mergeevent.py index bffd4245b..8992173c5 100644 --- a/src/Merge/mergeevent.py +++ b/src/Merge/mergeevent.py @@ -210,37 +210,37 @@ class MergeEventQuery(object): self.phoenix.merge(self.titanic) - trans = self.database.transaction_begin() - for person in self.database.iter_people(): - if person.has_handle_reference("Event", old_handle): - bri = person.birth_ref_index - dri = person.death_ref_index - person.replace_handle_reference("Event", old_handle, new_handle) - if person.birth_ref_index != bri and person.birth_ref_index==-1: - for index, ref in enumerate(person.get_event_ref_list()): - if ref.ref == new_handle: - event = self.phoenix - else: - event = self.database.get_event_from_handle(ref.ref) - if event.type.is_birth() and ref.role.is_primary(): - person.birth_ref_index = index - break - if person.death_ref_index != dri and person.death_ref_index==-1: - for index, ref in enumerate(person.get_event_ref_list()): - if ref.ref == new_handle: - event = self.phoenix - else: - event = self.database.get_event_from_handle(ref.ref) - if event.type.is_death() and ref.role.is_primary(): - person.death_ref_index = index - break - self.database.commit_person(person, trans) + trans = self.database.transaction_begin(_("Merge Event Objects")) + with self.database.transaction_begin() as trans: + for person in self.database.iter_people(): + if person.has_handle_reference("Event", old_handle): + bri = person.birth_ref_index + dri = person.death_ref_index + person.replace_handle_reference("Event", old_handle, new_handle) + if person.birth_ref_index != bri and person.birth_ref_index==-1: + for index, ref in enumerate(person.get_event_ref_list()): + if ref.ref == new_handle: + event = self.phoenix + else: + event = self.database.get_event_from_handle(ref.ref) + if event.type.is_birth() and ref.role.is_primary(): + person.birth_ref_index = index + break + if person.death_ref_index != dri and person.death_ref_index==-1: + for index, ref in enumerate(person.get_event_ref_list()): + if ref.ref == new_handle: + event = self.phoenix + else: + event = self.database.get_event_from_handle(ref.ref) + if event.type.is_death() and ref.role.is_primary(): + person.death_ref_index = index + break + self.database.commit_person(person, trans) - for family in self.database.iter_families(): - if family.has_handle_reference("Event", old_handle): - family.replace_handle_reference("Event", old_handle, new_handle) - self.database.commit_family(family, trans) - - self.database.remove_event(old_handle, trans) - self.database.commit_event(self.phoenix, trans) - self.database.transaction_commit(trans, _("Merge Event Objects")) + for family in self.database.iter_families(): + if family.has_handle_reference("Event", old_handle): + family.replace_handle_reference("Event", old_handle, new_handle) + self.database.commit_family(family, trans) + + self.database.remove_event(old_handle, trans) + self.database.commit_event(self.phoenix, trans) diff --git a/src/Merge/mergefamily.py b/src/Merge/mergefamily.py index 33e1c6862..f9a78e9cd 100644 --- a/src/Merge/mergefamily.py +++ b/src/Merge/mergefamily.py @@ -60,10 +60,9 @@ class MergeFamilies(ManagedWindow.ManagedWindow): """ def __init__(self, dbstate, uistate, handle1, handle2): ManagedWindow.ManagedWindow.__init__(self, uistate, [], self.__class__) - self.dbstate = dbstate - database = dbstate.db - self.fy1 = database.get_family_from_handle(handle1) - self.fy2 = database.get_family_from_handle(handle2) + self.database = dbstate.db + self.fy1 = self.database.get_family_from_handle(handle1) + self.fy2 = self.database.get_family_from_handle(handle2) self.define_glade('mergefamily', _GLADE_FILE) self.set_window(self._gladeobj.toplevel, @@ -73,34 +72,56 @@ class MergeFamilies(ManagedWindow.ManagedWindow): # Detailed selection widgets father1 = self.fy1.get_father_handle() father2 = self.fy2.get_father_handle() - father1 = database.get_person_from_handle(father1) - father2 = database.get_person_from_handle(father2) - father_id1 = father1.get_gramps_id() - father_id2 = father2.get_gramps_id() + father1 = self.database.get_person_from_handle(father1) + father2 = self.database.get_person_from_handle(father2) + father_id1 = father1.get_gramps_id() if father1 else "" + father_id2 = father2.get_gramps_id() if father2 else "" father1 = name_displayer.display(father1) if father1 else "" father2 = name_displayer.display(father2) if father2 else "" entry1 = self.get_widget("father1") entry2 = self.get_widget("father2") entry1.set_text("%s [%s]" % (father1, father_id1)) entry2.set_text("%s [%s]" % (father2, father_id2)) - if entry1.get_text() == entry2.get_text(): + deactivate = False + if father_id1 == "" and father_id2 == "": + deactivate = True + elif father_id2 == "": + self.get_widget("father_btn1").set_active(True) + deactivate = True + elif father_id1 == "": + self.get_widget("father_btn2").set_active(True) + deactivate = True + elif entry1.get_text() == entry2.get_text(): + deactivate = True + if deactivate: for widget_name in ('father1', 'father2', 'father_btn1', 'father_btn2'): self.get_widget(widget_name).set_sensitive(False) mother1 = self.fy1.get_mother_handle() mother2 = self.fy2.get_mother_handle() - mother1 = database.get_person_from_handle(mother1) - mother2 = database.get_person_from_handle(mother2) - mother_id1 = mother1.get_gramps_id() - mother_id2 = mother2.get_gramps_id() + mother1 = self.database.get_person_from_handle(mother1) + mother2 = self.database.get_person_from_handle(mother2) + mother_id1 = mother1.get_gramps_id() if mother1 else "" + mother_id2 = mother2.get_gramps_id() if mother2 else "" mother1 = name_displayer.display(mother1) if mother1 else "" mother2 = name_displayer.display(mother2) if mother2 else "" entry1 = self.get_widget("mother1") entry2 = self.get_widget("mother2") entry1.set_text("%s [%s]" % (mother1, mother_id1)) entry2.set_text("%s [%s]" % (mother2, mother_id2)) - if entry1.get_text() == entry2.get_text(): + deactivate = False + if mother_id1 == "" and mother_id2 == "": + deactivate = True + elif mother_id1 == "": + self.get_widget("mother_btn2").set_active(True) + deactivate = True + elif mother_id2 == "": + self.get_widget("mother_btn1").set_active(True) + deactivate = True + elif entry1.get_text() == entry2.get_text(): + deactivate = True + if deactivate: for widget_name in ('mother1', 'mother2', 'mother_btn1', 'mother_btn2'): self.get_widget(widget_name).set_sensitive(False) @@ -140,13 +161,25 @@ class MergeFamilies(ManagedWindow.ManagedWindow): def on_handle1_toggled(self, obj): """Preferred family changes""" if obj.get_active(): - self.get_widget("father_btn1").set_active(True) - self.get_widget("mother_btn1").set_active(True) + father1_text = self.get_widget("father1").get_text() + if father1_text != " []" or (father1_text == " []" and + self.get_widget("father2").get_text() == " []"): + self.get_widget("father_btn1").set_active(True) + mother1_text = self.get_widget("mother1").get_text() + if mother1_text != " []" or (mother1_text == " []" and + self.get_widget("mother2").get_text() == " []"): + self.get_widget("mother_btn1").set_active(True) self.get_widget("rel_btn1").set_active(True) self.get_widget("gramps_btn1").set_active(True) else: - self.get_widget("father_btn2").set_active(True) - self.get_widget("mother_btn2").set_active(True) + father2_text = self.get_widget("father2").get_text() + if father2_text != " []" or (father2_text == " []" and + self.get_widget("father1").get_text() == " []"): + self.get_widget("father_btn2").set_active(True) + mother2_text = self.get_widget("mother2").get_text() + if mother2_text != " []" or (mother2_text == " []" and + self.get_widget("mother1").get_text() == " []"): + self.get_widget("mother_btn2").set_active(True) self.get_widget("rel_btn2").set_active(True) self.get_widget("gramps_btn2").set_active(True) @@ -159,8 +192,6 @@ class MergeFamilies(ManagedWindow.ManagedWindow): Perform the merge of the families when the merge button is clicked. """ self.uistate.set_busy_cursor(True) - need_commit = False - database = self.dbstate.db use_handle1 = self.get_widget("handle_btn1").get_active() if use_handle1: phoenix = self.fy1 @@ -171,78 +202,141 @@ class MergeFamilies(ManagedWindow.ManagedWindow): titanic = self.fy1 unselect_path = (0,) - phoenix_father = database.get_person_from_handle( - phoenix.get_father_handle()) - phoenix_mother = database.get_person_from_handle( - phoenix.get_mother_handle()) - titanic_father = database.get_person_from_handle( - titanic.get_father_handle()) - titanic_mother = database.get_person_from_handle( - titanic.get_mother_handle()) + phoenix_fh = phoenix.get_father_handle() + phoenix_mh = phoenix.get_mother_handle() - trans = database.transaction_begin("", True) - - # Use merge persons on father and mother to merge a family; The merge - # person routine also merges families if necessary. Merging is not - # an equal operation, there is one preferred family over the other. - # The preferred family is the first listed in a persons - # family_handle_list. Since the GUI allows users to chose the - # preferred father, mother and family independent of each other, while - # the merge person routine fixes preferred family with respect to - # father and mother, the father and mother need first to be swapped - # into the right family, before the merge person routines can be called. if self.get_widget("father_btn1").get_active() ^ use_handle1: - father_handle = phoenix.get_father_handle() - phoenix.set_father_handle(titanic.get_father_handle()) - titanic.set_father_handle(father_handle) - phoenix_father.replace_handle_reference('Family', - phoenix.get_handle(), titanic.get_handle()) - titanic_father.replace_handle_reference('Family', - titanic.get_handle(), phoenix.get_handle()) - phoenix_father, titanic_father = titanic_father, phoenix_father - database.commit_person(phoenix_father, trans) - database.commit_person(titanic_father, trans) - database.commit_family(phoenix, trans) - database.commit_family(titanic, trans) + phoenix_fh = titanic.get_father_handle() if self.get_widget("mother_btn1").get_active() ^ use_handle1: - mother_handle = phoenix.get_mother_handle() - phoenix.set_mother_handle(titanic.get_mother_handle()) - titanic.set_mother_handle(mother_handle) - phoenix_mother.replace_handle_reference('Family', - phoenix.get_handle(), titanic.get_handle()) - titanic_mother.replace_handle_reference('Family', - titanic.get_handle(), phoenix.get_handle()) - phoenix_mother, titanic_mother = titanic_mother, phoenix_mother - database.commit_person(phoenix_mother, trans) - database.commit_person(titanic_mother, trans) - database.commit_family(phoenix, trans) - database.commit_family(titanic, trans) - + phoenix_mh = titanic.get_mother_handle() if self.get_widget("rel_btn1").get_active() ^ use_handle1: phoenix.set_relationship(titanic.get_relationship()) - need_commit = True if self.get_widget("gramps_btn1").get_active() ^ use_handle1: phoenix.set_gramps_id(titanic.get_gramps_id()) - need_commit = True - if need_commit: - database.commit_family(phoenix, trans) try: - if phoenix_father != titanic_father: - query = MergePersonQuery(self.dbstate, phoenix_father, - titanic_father) - query.execute(trans) - if phoenix_mother != titanic_mother: - query = MergePersonQuery(self.dbstate, phoenix_mother, - titanic_mother) - query.execute(trans) - except MergeError, e: - ErrorDialog( _("Cannot merge people"), str(e)) - # TODO: rollback - else: - database.transaction_commit(trans, _('Merge family')) - database.emit('family-rebuild') + query = MergeFamilyQuery(self.database, phoenix, titanic, + phoenix_fh, phoenix_mh) + query.execute() + except MergeError, err: + ErrorDialog( _("Cannot merge people"), str(err)) self.uistate.viewmanager.active_page.selection.unselect_path( unselect_path) self.uistate.set_busy_cursor(False) self.close() + +class MergeFamilyQuery(object): + """ + Create database query to merge two families. + """ + def __init__(self, database, phoenix, titanic, phoenix_fh, phoenix_mh): + self.database = database + self.phoenix = phoenix + self.titanic = titanic + self.phoenix_fh = phoenix_fh + if self.phoenix.get_father_handle() == self.phoenix_fh: + self.titanic_fh = self.titanic.get_father_handle() + self.father_swapped = False + else: + assert self.phoenix_fh == self.titanic.get_father_handle() + self.titanic_fh = self.phoenix.get_father_handle() + self.father_swapped = True + self.phoenix_mh = phoenix_mh + if self.phoenix.get_mother_handle() == self.phoenix_mh: + self.titanic_mh = self.titanic.get_mother_handle() + self.mother_swapped = False + else: + assert self.phoenix_mh == self.titanic.get_mother_handle() + self.titanic_mh = self.phoenix.get_mother_handle() + self.mother_swapped = True + + def merge_person(self, phoenix_person, titanic_person, parent, trans): + """ + Merge two persons even if they are None; no families are merged! + """ + new_handle = self.phoenix.get_handle() + old_handle = self.titanic.get_handle() + + if parent == 'father': + swapped = self.father_swapped + adjust_family_parent_handle = 'set_father_handle' + elif parent == 'mother': + swapped = self.mother_swapped + adjust_family_parent_handle = 'set_mother_handle' + else: + raise ValueError(_("A parent should be a father or mother.")) + + if phoenix_person is None: + if titanic_person is not None: + raise MergeError(_("""When merging people where one person """ + """doesn't exist, that "person" must be the person that """ + """will be deleted from the database.""")) + return + elif titanic_person is None: + if swapped: + if [childref for childref in self.phoenix.get_child_ref_list() + if childref.get_reference_handle() == + phoenix_person.get_handle()]: + raise MergeError(_("A parent and child cannot be merged. " + "To merge these people, you must first break the " + "relationship between them.")) + phoenix_person.add_family_handle(new_handle) + getattr(self.phoenix, adjust_family_parent_handle)( + phoenix_person.get_handle()) + self.database.commit_family(self.phoenix, trans) + else: + if [childref for childref in self.titanic.get_child_ref_list() + if childref.get_reference_handle() == + phoenix_person.get_handle()]: + raise MergeError(_("A parent and child cannot be merged. " + "To merge these people, you must first break the " + "relationship between them.")) + phoenix_person.add_family_handle(old_handle) + getattr(self.titanic, adjust_family_parent_handle)( + phoenix_person.get_handle()) + self.database.commit_family(self.titanic, trans) + self.database.commit_person(phoenix_person, trans) + else: + query = MergePersonQuery(self.database, phoenix_person, titanic_person) + query.execute(family_merger=False, trans=trans) + + def execute(self): + """ + Merges two families into a single family. + """ + new_handle = self.phoenix.get_handle() + old_handle = self.titanic.get_handle() + + with self.database.transaction_begin(_('Merge Family')) as trans: + + phoenix_father = self.database.get_person_from_handle(self.phoenix_fh) + titanic_father = self.database.get_person_from_handle(self.titanic_fh) + self.merge_person(phoenix_father, titanic_father, 'father', trans) + + phoenix_mother = self.database.get_person_from_handle(self.phoenix_mh) + titanic_mother = self.database.get_person_from_handle(self.titanic_mh) + self.phoenix = self.database.get_family_from_handle(new_handle) + self.titanic = self.database.get_family_from_handle(old_handle) + self.merge_person(phoenix_mother, titanic_mother, 'mother', trans) + + phoenix_father = self.database.get_person_from_handle(self.phoenix_fh) + phoenix_mother = self.database.get_person_from_handle(self.phoenix_mh) + self.phoenix = self.database.get_family_from_handle(new_handle) + self.titanic = self.database.get_family_from_handle(old_handle) + self.phoenix.merge(self.titanic) + for childref in self.titanic.get_child_ref_list(): + child = self.database.get_person_from_handle( + childref.get_reference_handle()) + if new_handle in child.parent_family_list: + child.remove_handle_references('Family', [old_handle]) + else: + child.replace_handle_reference('Family', old_handle, new_handle) + self.database.commit_person(child, trans) + if phoenix_father: + phoenix_father.remove_family_handle(old_handle) + self.database.commit_person(phoenix_father, trans) + if phoenix_mother: + phoenix_mother.remove_family_handle(old_handle) + self.database.commit_person(phoenix_mother, trans) + self.database.remove_family(old_handle, trans) + self.database.commit_family(self.phoenix, trans) diff --git a/src/Merge/mergemedia.py b/src/Merge/mergemedia.py index e46b44203..0ab5cd8cb 100644 --- a/src/Merge/mergemedia.py +++ b/src/Merge/mergemedia.py @@ -184,32 +184,31 @@ class MergeMediaQuery(object): self.phoenix.merge(self.titanic) - trans = self.database.transaction_begin() - for person in self.database.iter_people(): - if person.has_media_reference(old_handle): - person.replace_media_references(old_handle, new_handle) - self.database.commit_person(person, trans) + with self.database.transaction_begin(_("Merge Media Ojbects")) as trans: + for person in self.database.iter_people(): + if person.has_media_reference(old_handle): + person.replace_media_references(old_handle, new_handle) + self.database.commit_person(person, trans) - for family in self.database.iter_families(): - if family.has_media_reference(old_handle): - family.replace_media_references(old_handle, new_handle) - self.database.commit_family(family, trans) + for family in self.database.iter_families(): + if family.has_media_reference(old_handle): + family.replace_media_references(old_handle, new_handle) + self.database.commit_family(family, trans) - for event in self.database.iter_events(): - if event.has_media_reference(old_handle): - event.replace_media_references(old_handle, new_handle) - self.database.commit_event(event, trans) + for event in self.database.iter_events(): + if event.has_media_reference(old_handle): + event.replace_media_references(old_handle, new_handle) + self.database.commit_event(event, trans) - for source in self.database.iter_sources(): - if source.has_media_reference(old_handle): - source.replace_media_references(old_handle, new_handle) - self.database.commit_source(source, trans) + for source in self.database.iter_sources(): + if source.has_media_reference(old_handle): + source.replace_media_references(old_handle, new_handle) + self.database.commit_source(source, trans) - for place in self.database.iter_places(): - if place.has_media_reference(old_handle): - place.replace_media_references(old_handle, new_handle) - self.database.commit_place(place, trans) + for place in self.database.iter_places(): + if place.has_media_reference(old_handle): + place.replace_media_references(old_handle, new_handle) + self.database.commit_place(place, trans) - self.database.remove_object(old_handle, trans) - self.database.commit_media_object(self.phoenix, trans) - self.database.transaction_commit(trans, _("Merge Media Objects")) + self.database.remove_object(old_handle, trans) + self.database.commit_media_object(self.phoenix, trans) diff --git a/src/Merge/mergenote.py b/src/Merge/mergenote.py index 9b7d96690..570167a5b 100644 --- a/src/Merge/mergenote.py +++ b/src/Merge/mergenote.py @@ -196,43 +196,42 @@ class MergeNoteQuery(object): new_handle = self.phoenix.get_handle() old_handle = self.titanic.get_handle() self.phoenix.merge(self.titanic) - trans = self.database.transaction_begin() + with self.database.transaction_begin(_("Merge Notes")) as trans: - for person in self.database.iter_people(): - if person.has_note_reference(old_handle): - person.replace_note_references(old_handle, new_handle) - self.database.commit_person(person, trans) + for person in self.database.iter_people(): + if person.has_note_reference(old_handle): + person.replace_note_references(old_handle, new_handle) + self.database.commit_person(person, trans) - for family in self.database.iter_families(): - if family.has_note_reference(old_handle): - family.replace_note_references(old_handle, new_handle) - self.database.commit_family(family, trans) + for family in self.database.iter_families(): + if family.has_note_reference(old_handle): + family.replace_note_references(old_handle, new_handle) + self.database.commit_family(family, trans) - for event in self.database.iter_events(): - if event.has_note_reference(old_handle): - event.replace_note_references(old_handle, new_handle) - self.database.commit_event(event, trans) + for event in self.database.iter_events(): + if event.has_note_reference(old_handle): + event.replace_note_references(old_handle, new_handle) + self.database.commit_event(event, trans) - for source in self.database.iter_sources(): - if source.has_note_reference(old_handle): - source.replace_note_references(old_handle, new_handle) - self.database.commit_source(source, trans) + for source in self.database.iter_sources(): + if source.has_note_reference(old_handle): + source.replace_note_references(old_handle, new_handle) + self.database.commit_source(source, trans) - for place in self.database.iter_places(): - if place.has_note_reference(old_handle): - place.replace_note_references(old_handle, new_handle) - self.database.commit_place(place, trans) + for place in self.database.iter_places(): + if place.has_note_reference(old_handle): + place.replace_note_references(old_handle, new_handle) + self.database.commit_place(place, trans) - for obj in self.database.iter_media_objects(): - if obj.has_note_reference(old_handle): - obj.replace_note_references(old_handle, new_handle) - self.database.commit_media_object(obj, trans) + for obj in self.database.iter_media_objects(): + if obj.has_note_reference(old_handle): + obj.replace_note_references(old_handle, new_handle) + self.database.commit_media_object(obj, trans) - for repo in self.database.iter_repositories(): - if repo.has_note_reference(old_handle): - repo.replace_note_references(old_handle, new_handle) - self.database.commit_repository(repo, trans) + for repo in self.database.iter_repositories(): + if repo.has_note_reference(old_handle): + repo.replace_note_references(old_handle, new_handle) + self.database.commit_repository(repo, trans) - self.database.remove_note(old_handle, trans) - self.database.commit_note(self.phoenix, trans) - self.database.transaction_commit(trans, _("Merge Notes")) + self.database.remove_note(old_handle, trans) + self.database.commit_note(self.phoenix, trans) diff --git a/src/Merge/mergeperson.py b/src/Merge/mergeperson.py index 9206b79eb..e55e123fd 100644 --- a/src/Merge/mergeperson.py +++ b/src/Merge/mergeperson.py @@ -73,10 +73,9 @@ class MergePeople(ManagedWindow.ManagedWindow): def __init__(self, dbstate, uistate, handle1, handle2, cb_update=None, expand_context_info=False): ManagedWindow.ManagedWindow.__init__(self, uistate, [], self.__class__) - self.dbstate = dbstate - database = dbstate.db - self.pr1 = database.get_person_from_handle(handle1) - self.pr2 = database.get_person_from_handle(handle2) + self.database = dbstate.db + self.pr1 = self.database.get_person_from_handle(handle1) + self.pr2 = self.database.get_person_from_handle(handle2) self.update = cb_update self.define_glade('mergeperson', _GLADE_FILE) @@ -159,7 +158,6 @@ class MergePeople(ManagedWindow.ManagedWindow): def display(self, tobj, person): """Fill text buffer tobj with detailed info on person person.""" - database = self.dbstate.db normal = tobj.create_tag() normal.set_property('indent', 10) normal.set_property('pixels-above-lines', 1) @@ -198,7 +196,7 @@ class MergePeople(ManagedWindow.ManagedWindow): for event_ref in person.get_event_ref_list(): event_handle = event_ref.ref name = str( - database.get_event_from_handle(event_handle).get_type()) + self.database.get_event_from_handle(event_handle).get_type()) self.add(tobj, normal, "%s:\t%s" % (name, self.get_event_info(event_handle))) plist = person.get_parent_family_handle_list() @@ -220,22 +218,22 @@ class MergePeople(ManagedWindow.ManagedWindow): if len(slist) > 0: for fid in slist: (fname, mname, pid) = self.get_parent_info(fid) - family = database.get_family_from_handle(fid) + family = self.database.get_family_from_handle(fid) self.add(tobj, normal, "%s:\t%s" % (_('Family ID'), pid)) spouse_id = ReportUtils.find_spouse(person, family) if spouse_id: - spouse = database.get_person_from_handle(spouse_id) + spouse = self.database.get_person_from_handle(spouse_id) self.add(tobj, indent, "%s:\t%s" % (_('Spouse'), name_of(spouse))) relstr = str(family.get_relationship()) self.add(tobj, indent, "%s:\t%s" % (_('Type'), relstr)) - event = ReportUtils.find_marriage(database, family) + event = ReportUtils.find_marriage(self.database, family) if event: self.add(tobj, indent, "%s:\t%s" % ( _('Marriage'), self.get_event_info(event.get_handle()))) for child_ref in family.get_child_ref_list(): - child = database.get_person_from_handle(child_ref.ref) + child = self.database.get_person_from_handle(child_ref.ref) self.add(tobj, indent, "%s:\t%s" % (_('Child'), name_of(child))) else: @@ -252,17 +250,16 @@ class MergePeople(ManagedWindow.ManagedWindow): def get_parent_info(self, fid): """Return tuple of father name, mother name and family ID""" - database = self.dbstate.db - family = database.get_family_from_handle(fid) + family = self.database.get_family_from_handle(fid) father_id = family.get_father_handle() mother_id = family.get_mother_handle() if father_id: - father = database.get_person_from_handle(father_id) + father = self.database.get_person_from_handle(father_id) fname = name_of(father) else: fname = u"" if mother_id: - mother = database.get_person_from_handle(mother_id) + mother = self.database.get_person_from_handle(mother_id) mname = name_of(mother) else: mname = u"" @@ -273,7 +270,7 @@ class MergePeople(ManagedWindow.ManagedWindow): date = "" place = "" if handle: - event = self.dbstate.db.get_event_from_handle(handle) + event = self.database.db.get_event_from_handle(handle) date = DateHandler.get_date(event) place = self.place_name(event) if date: @@ -287,7 +284,7 @@ class MergePeople(ManagedWindow.ManagedWindow): """Return place name of an event as string.""" place_id = event.get_place_handle() if place_id: - place = self.dbstate.db.get_place_from_handle(place_id) + place = self.database.db.get_place_from_handle(place_id) return place.get_title() else: return "" @@ -323,7 +320,7 @@ class MergePeople(ManagedWindow.ManagedWindow): titanic.set_gramps_id(swapid) try: - query = MergePersonQuery(self.dbstate, phoenix, titanic) + query = MergePersonQuery(self.database, phoenix, titanic) query.execute() except MergeError, err: ErrorDialog( _("Cannot merge people"), str(err)) @@ -338,8 +335,8 @@ class MergePersonQuery(object): """ Create database query to merge two persons. """ - def __init__(self, dbstate, phoenix, titanic): - self.database = dbstate.db + def __init__(self, database, phoenix, titanic): + self.database = database self.phoenix = phoenix self.titanic = titanic if self.check_for_spouse(self.phoenix, self.titanic): @@ -365,7 +362,7 @@ class MergePersonQuery(object): return len(fs1.intersection(fp2)) != 0 or len(fs2.intersection(fp1)) def merge_families(self, main_family_handle, family, trans): - new_handle = self.phoenix.get_handle() + new_handle = self.phoenix.get_handle() if self.phoenix else None family_handle = family.get_handle() main_family = self.database.get_family_from_handle(main_family_handle) main_family.merge(family) @@ -378,17 +375,26 @@ class MergePersonQuery(object): child.replace_handle_reference('Family', family_handle, main_family_handle) self.database.commit_person(child, trans) - self.phoenix.remove_family_handle(family_handle) + if self.phoenix: + self.phoenix.remove_family_handle(family_handle) family_father_handle = family.get_father_handle() spouse_handle = family.get_mother_handle() if \ new_handle == family_father_handle else family_father_handle spouse = self.database.get_person_from_handle(spouse_handle) - spouse.remove_family_handle(family_handle) - self.database.commit_person(spouse, trans) + if spouse: + spouse.remove_family_handle(family_handle) + self.database.commit_person(spouse, trans) self.database.remove_family(family_handle, trans) self.database.commit_family(main_family, trans) - def execute(self, trans=None): + def execute(self, family_merger=True, trans=None): + if trans is None: + with self.database.transaction_begin(_('Merge Person')) as trans: + self.__execute(family_merger, trans) + else: + self.__execute(family_merger, trans) + + def __execute(self, family_merger, trans): """ Merges two persons into a single person. """ @@ -397,32 +403,15 @@ class MergePersonQuery(object): self.phoenix.merge(self.titanic) - # For now use a batch transaction, because merger of persons is - # complicated, thus is done in several steps and the database should - # be updated after each step for the calculation of the next step. - # Normal Gramps transactions only touch the database upon - # transaction_commit, not after each commit_person/commit_family. - # Unfortunately batch transactions are no transactions at all, so there - # is not possibility of rollback in case of trouble. - if trans is None: - need_commit = True - trans = self.database.transaction_begin("", True) - else: - need_commit = False - - commit_persons = [] - for person in self.database.iter_people(): - if person.has_handle_reference('Person', old_handle): - person.replace_handle_reference('Person', old_handle,new_handle) - #self.database.commit_person(person, trans) # DEADLOCK - person_handle = person.get_handle() - if person_handle == new_handle: - self.phoenix.replace_handle_reference('Person', old_handle, - new_handle) - elif person_handle != old_handle: - commit_persons.append(person) - for person in commit_persons: - self.database.commit_person(person, trans) + for (p_dummy, person_handle) in self.database.find_backlink_handles( + old_handle, ['Person']): + person = self.database.get_person_from_handle(person_handle) + assert person.has_handle_reference('Person', old_handle) + person.replace_handle_reference('Person', old_handle, new_handle) + if person_handle != new_handle and person_handle != old_handle: + self.database.commit_person(person, trans) + # phoenix changed and can't be determined from database nor transaction + self.phoenix.replace_handle_reference('Person', old_handle, new_handle) for family_handle in self.phoenix.get_parent_family_handle_list(): family = self.database.get_family_from_handle(family_handle) @@ -430,27 +419,36 @@ class MergePersonQuery(object): family.replace_handle_reference('Person', old_handle,new_handle) self.database.commit_family(family, trans) + family_merge_guard = False parent_list = [] + parent_list_orig = [] family_handle_list = self.phoenix.get_family_handle_list()[:] for family_handle in family_handle_list: family = self.database.get_family_from_handle(family_handle) parents = (family.get_father_handle(), family.get_mother_handle()) + parent_list_orig.append(parents) if family.has_handle_reference('Person', old_handle): + if family_merger and parent_list_orig.count(parents) > 1: + raise MergeError(_("A person with multiple relations with " + "the same spouse is about to be merged. This is beyond " + "the capabilities of the merge routine. The merge is " + "aborted.")) family.replace_handle_reference('Person', old_handle,new_handle) parents = (family.get_father_handle(), family.get_mother_handle()) # prune means merging families in this case. - if parents in parent_list: + if family_merger and parents in parent_list: # also merge when father_handle or mother_handle == None! + if family_merge_guard: + raise MergeError(_("Multiple families get merged. " + "This is unusual, the merge is aborted.")) idx = parent_list.index(parents) main_family_handle = family_handle_list[idx] self.merge_families(main_family_handle, family, trans) + family_merge_guard = True continue self.database.commit_family(family, trans) parent_list.append(parents) self.database.remove_person(old_handle, trans) self.database.commit_person(self.phoenix, trans) - if need_commit: - self.database.transaction_commit(trans, _('Merge Person')) - self.database.emit('person-rebuild') diff --git a/src/Merge/mergeplace.py b/src/Merge/mergeplace.py index 407e3356e..09d89ddc7 100644 --- a/src/Merge/mergeplace.py +++ b/src/Merge/mergeplace.py @@ -210,22 +210,24 @@ class MergePlaceQuery(object): self.phoenix.merge(self.titanic) - trans = self.database.transaction_begin() - for person in self.database.iter_people(): - if person.has_handle_reference('Place', old_handle): - person.replace_handle_reference('Place', old_handle, new_handle) - self.database.commit_person(person, trans) + with self.database.transaction_begin(_("Merge Places")) as trans: + for person in self.database.iter_people(): + if person.has_handle_reference('Place', old_handle): + person.replace_handle_reference('Place', old_handle, + new_handle) + self.database.commit_person(person, trans) - for family in self.database.iter_families(): - if family.has_handle_reference('Place', old_handle): - family.replace_handle_reference('Place', old_handle, new_handle) - self.database.commit_family(family, trans) + for family in self.database.iter_families(): + if family.has_handle_reference('Place', old_handle): + family.replace_handle_reference('Place', old_handle, + new_handle) + self.database.commit_family(family, trans) - for event in self.database.iter_events(): - if event.has_handle_reference('Place', old_handle): - event.replace_handle_reference('Place', old_handle, new_handle) - self.database.commit_event(event, trans) + for event in self.database.iter_events(): + if event.has_handle_reference('Place', old_handle): + event.replace_handle_reference('Place', old_handle, + new_handle) + self.database.commit_event(event, trans) - self.database.remove_place(old_handle, trans) - self.database.commit_place(self.phoenix, trans) - self.database.transaction_commit(trans, _("Merge Places")) + self.database.remove_place(old_handle, trans) + self.database.commit_place(self.phoenix, trans) diff --git a/src/Merge/mergerepository.py b/src/Merge/mergerepository.py index 5bb91916d..a6ddbd05a 100644 --- a/src/Merge/mergerepository.py +++ b/src/Merge/mergerepository.py @@ -171,11 +171,10 @@ class MergeRepoQuery(object): self.phoenix.merge(self.titanic) - trans = self.database.transaction_begin() - for source in self.database.iter_sources(): - if source.has_repo_reference(old_handle): - source.replace_repo_references(old_handle, new_handle) - self.database.commit_source(source, trans) - self.database.remove_repository(old_handle, trans) - self.database.commit_repository(self.phoenix, trans) - self.database.transaction_commit(trans, _("Merge Repositories")) + with self.database.transaction_begin(_("Merge Repositories")) as trans: + for source in self.database.iter_sources(): + if source.has_repo_reference(old_handle): + source.replace_repo_references(old_handle, new_handle) + self.database.commit_source(source, trans) + self.database.remove_repository(old_handle, trans) + self.database.commit_repository(self.phoenix, trans) diff --git a/src/Merge/mergesource.py b/src/Merge/mergesource.py index 89f13cc6e..969f4fe9f 100644 --- a/src/Merge/mergesource.py +++ b/src/Merge/mergesource.py @@ -197,42 +197,41 @@ class MergeSourceQuery(object): self.phoenix.merge(self.titanic) - trans = self.database.transaction_begin() - for person in self.database.iter_people(): - if person.has_source_reference(old_handle): - person.replace_source_references(old_handle, new_handle) - self.database.commit_person(person, trans) + with self.database.transaction_begin(_("Merge Source")) as trans: + for person in self.database.iter_people(): + if person.has_source_reference(old_handle): + person.replace_source_references(old_handle, new_handle) + self.database.commit_person(person, trans) - for family in self.database.iter_families(): - if family.has_source_reference(old_handle): - family.replace_source_references(old_handle, new_handle) - self.database.commit_family(family, trans) + for family in self.database.iter_families(): + if family.has_source_reference(old_handle): + family.replace_source_references(old_handle, new_handle) + self.database.commit_family(family, trans) - for event in self.database.iter_events(): - if event.has_source_reference(old_handle): - event.replace_source_references(old_handle, new_handle) - self.database.commit_event(event, trans) + for event in self.database.iter_events(): + if event.has_source_reference(old_handle): + event.replace_source_references(old_handle, new_handle) + self.database.commit_event(event, trans) - for source in self.database.iter_sources(): - if source.has_source_reference(old_handle): - source.replace_source_references(old_handle, new_handle) - self.database.commit_source(source, trans) + for source in self.database.iter_sources(): + if source.has_source_reference(old_handle): + source.replace_source_references(old_handle, new_handle) + self.database.commit_source(source, trans) - for place in self.database.iter_places(): - if place.has_source_reference(old_handle): - place.replace_source_references(old_handle, new_handle) - self.database.commit_place(place, trans) + for place in self.database.iter_places(): + if place.has_source_reference(old_handle): + place.replace_source_references(old_handle, new_handle) + self.database.commit_place(place, trans) - for obj in self.database.iter_media_objects(): - if obj.has_source_reference(old_handle): - obj.replace_source_references(old_handle, new_handle) - self.database.commit_media_object(obj, trans) + for obj in self.database.iter_media_objects(): + if obj.has_source_reference(old_handle): + obj.replace_source_references(old_handle, new_handle) + self.database.commit_media_object(obj, trans) - for repo in self.database.iter_repositories(): - if repo.has_source_reference(old_handle): - repo.replace_source_references(old_handle, new_handle) - self.database.commit_repository(repo, trans) + for repo in self.database.iter_repositories(): + if repo.has_source_reference(old_handle): + repo.replace_source_references(old_handle, new_handle) + self.database.commit_repository(repo, trans) - self.database.remove_source(old_handle, trans) - self.database.commit_source(self.phoenix, trans) - self.database.transaction_commit(trans, _("Merge Sources")) + self.database.remove_source(old_handle, trans) + self.database.commit_source(self.phoenix, trans) diff --git a/src/Reorder.py b/src/Reorder.py index c34165c4c..13fc5b626 100644 --- a/src/Reorder.py +++ b/src/Reorder.py @@ -134,11 +134,10 @@ class Reorder(ManagedWindow.ManagedWindow): self.close() def ok_clicked(self, obj): - trans = self.dbstate.db.transaction_begin() - self.dbstate.db.commit_person(self.person, trans) name = name_displayer.display(self.person) msg = _("Reorder Relationships: %s") % name - self.dbstate.db.transaction_commit(trans, msg) + with self.dbstate.db.transaction_begin(msg) as trans: + self.dbstate.db.commit_person(self.person, trans) self.close() diff --git a/src/gen/db/base.py b/src/gen/db/base.py index ba19e9c99..c69b0a420 100644 --- a/src/gen/db/base.py +++ b/src/gen/db/base.py @@ -1525,33 +1525,37 @@ class DbWriteBase(object): child.add_parent_family_handle(family.handle) if trans is None: - need_commit = True - trans = self.transaction_begin() + with self.transaction_begin(_('Add child to family')) as trans: + self.commit_family(family, trans) + self.commit_person(child, trans) else: - need_commit = False - - self.commit_family(family,trans) - self.commit_person(child,trans) - - if need_commit: - self.transaction_commit(trans, _('Add child to family') ) - + self.commit_family(family, trans) + self.commit_person(child, trans) + def remove_child_from_family(self, person_handle, family_handle, trans=None): """ Remove a person as a child of the family, deleting the family if it becomes empty. """ + if trans is None: + with self.transaction_begin(_("Remove child from family") + ) as trans: + self.__remove_child_from_family(person_handle, family_handle, + trans) + else: + self.__remove_child_from_family(person_handle, family_handle, trans) + trans.set_description(_("Remove child from family")) + + def __remove_child_from_family(self, person_handle, family_handle, trans): + """ + Remove a person as a child of the family, deleting the family if + it becomes empty; trans is compulsory. + """ person = self.get_person_from_handle(person_handle) family = self.get_family_from_handle(family_handle) person.remove_parent_family_handle(family_handle) family.remove_child_handle(person_handle) - if trans is None: - need_commit = True - trans = self.transaction_begin() - else: - need_commit = False - child_list = family.get_child_ref_list() if (not family.get_father_handle() and not family.get_mother_handle() and len(child_list) <= 1): @@ -1564,9 +1568,6 @@ class DbWriteBase(object): self.commit_family(family, trans) self.commit_person(person, trans) - if need_commit: - self.transaction_commit(trans,_("Remove child from family")) - def delete_person_from_database(self, person, trans): """ Deletes a person from the database, cleaning up all associated references. @@ -1615,13 +1616,18 @@ class DbWriteBase(object): """ Remove a family and its relationships. """ - family = self.get_family_from_handle(family_handle) - if trans is None: - need_commit = True - trans = self.transaction_begin() + with self.transaction_begin(_("Remove Family")) as trans: + self.__remove_family_relationships(family_handle, trans) else: - need_commit = False + self.__remove_family_relationships(family_handle, trans) + trans.set_description(_("Remove Family")) + + def __remove_family_relationships(self, family_handle, trans): + """ + Remove a family and its relationships; trans is compulsory. + """ + family = self.get_family_from_handle(family_handle) for phandle in [ family.get_father_handle(), family.get_mother_handle()]: @@ -1638,23 +1644,30 @@ class DbWriteBase(object): self.remove_family(family_handle, trans) - if need_commit: - self.transaction_commit(trans, _("Remove Family")) - - def remove_parent_from_family(self, person_handle, family_handle, trans=None): + def remove_parent_from_family(self, person_handle, family_handle, + trans=None): """ Remove a person as either the father or mother of a family, deleting the family if it becomes empty. """ + if trans is None: + with self.transaction_begin() as trans: + msg = self.__remove_parent_from_family(person_handle, + family_handle, trans) + trans.set_description(msg) + else: + msg = self.__remove_parent_from_family(person_handle, + family_handle, trans) + trans.set_description(msg) + + def __remove_parent_from_family(self, person_handle, family_handle, trans): + """ + Remove a person as either the father or mother of a family, + deleting the family if it becomes empty; trans is compulsory. + """ person = self.get_person_from_handle(person_handle) family = self.get_family_from_handle(family_handle) - if trans is None: - need_commit = True - trans = self.transaction_begin() - else: - need_commit = False - person.remove_family_handle(family_handle) if family.get_father_handle() == person_handle: family.set_father_handle(None) @@ -1674,10 +1687,8 @@ class DbWriteBase(object): else: self.commit_family(family, trans) self.commit_person(person, trans) - - if need_commit: - self.transaction_commit(trans,msg) - + return msg + def marriage_from_eventref_list(self, eventref_list): """ Get the marriage event from an eventref list. diff --git a/src/gen/db/read.py b/src/gen/db/read.py index ace7a52dc..37169ab9f 100644 --- a/src/gen/db/read.py +++ b/src/gen/db/read.py @@ -475,13 +475,12 @@ class DbBsddbRead(DbReadBase, Callback): self.emit('note-rebuild') self.emit('tag-rebuild') - @staticmethod - def __find_next_gramps_id(prefix, map_index, trans): + def __find_next_gramps_id(self, prefix, map_index, trans): """ Helper function for find_next__gramps_id methods """ index = prefix % map_index - while trans.has_key(str(index)): + while trans.get(str(index), txn=self.txn) is not None: map_index += 1 index = prefix % map_index map_index += 1 @@ -670,8 +669,8 @@ class DbBsddbRead(DbReadBase, Callback): def __get_obj_from_gramps_id(self, val, tbl, class_, prim_tbl): try: - if tbl.has_key(str(val)): - data = tbl.get(str(val), txn=self.txn) + data = tbl.get(str(val), txn=self.txn) + if data is not None: obj = class_() ### FIXME: this is a dirty hack that works without no ### sensible explanation. For some reason, for a readonly @@ -786,6 +785,8 @@ class DbBsddbRead(DbReadBase, Callback): """ Return if a key exists in the name_group table. """ + # The use of has_key seems allright because there is no write lock + # on the name_group table when this is called. return self.name_group.has_key(str(name)) def get_number_of_records(self, table): @@ -1037,7 +1038,7 @@ class DbBsddbRead(DbReadBase, Callback): table = key2table[obj_key] #return str(gramps_id) in table - return table.has_key(str(gramps_id)) + return table.get(str(gramps_id), txn=self.txn) is not None def find_initial_person(self): person = self.get_default_person() diff --git a/src/gen/db/txn.py b/src/gen/db/txn.py index 186bc5d04..382c197bb 100644 --- a/src/gen/db/txn.py +++ b/src/gen/db/txn.py @@ -32,12 +32,6 @@ database. #------------------------------------------------------------------------- from __future__ import with_statement import cPickle as pickle - -import config -if config.get('preferences.use-bsddb3'): - from bsddb3 import dbshelve, db -else: - from bsddb import dbshelve, db import logging from collections import defaultdict @@ -47,12 +41,11 @@ from collections import defaultdict # Gramps modules # #------------------------------------------------------------------------- -from gen.db.dbconst import * -from gen.db import BSDDBTxn -import Errors +from gen.db.dbconst import (DBLOGNAME, TXNADD, TXNUPD, TXNDEL) _LOG = logging.getLogger(DBLOGNAME) + #------------------------------------------------------------------------- # # Gramps transaction class @@ -65,14 +58,8 @@ class DbTxn(defaultdict): database """ - __slots__ = ('msg', 'commitdb', 'db', 'first', - 'last', 'timestamp', 'db_maps') - - def get_db_txn(self, value): - """ - Return a transaction object from the database - """ - raise NotImplementedError + __slots__ = ('msg', 'commitdb', 'db', 'batch', 'first', + 'last', 'timestamp', '__dict__') def __enter__(self): """ @@ -85,10 +72,12 @@ class DbTxn(defaultdict): Context manager exit method """ if exc_type is None: - self.commit() - return exc_type is None + self.db.transaction_commit(self) + else: + self.db.transaction_abort(self) + return False - def __init__(self, msg, commitdb, grampsdb): + def __init__(self, msg, commitdb, grampsdb, batch): """ Create a new transaction. @@ -120,24 +109,11 @@ class DbTxn(defaultdict): self.msg = msg self.commitdb = commitdb self.db = grampsdb + self.batch = batch self.first = None self.last = None self.timestamp = 0 - # Dictionary to enable table-driven logic in the class - self.db_maps = { - PERSON_KEY: (self.db.person_map, 'person'), - FAMILY_KEY: (self.db.family_map, 'family'), - EVENT_KEY: (self.db.event_map, 'event'), - SOURCE_KEY: (self.db.source_map, 'source'), - PLACE_KEY: (self.db.place_map, 'place'), - MEDIA_KEY: (self.db.media_map, 'media'), - REPOSITORY_KEY: (self.db.repository_map, 'repository'), - #REFERENCE_KEY: (self.db.reference_map, 'reference'), - NOTE_KEY: (self.db.note_map, 'note'), - TAG_KEY: (self.db.tag_map, 'tag'), - } - def get_description(self): """ Return the text string that describes the logical operation performed @@ -166,6 +142,7 @@ class DbTxn(defaultdict): self.last = len(self.commitdb) -1 if self.first is None: self.first = self.last + _LOG.debug('added to trans: %d %d %s' % (obj_type, trans_type, handle)) self[(obj_type, trans_type)] += [(handle, new_data)] return @@ -200,133 +177,58 @@ class DbTxn(defaultdict): return 0 return self.last - self.first + 1 - def commit(self, msg=None): - """ - Commit the transaction to the assocated commit database. - """ - if msg is not None: - self.msg = msg - - if not len(self) or self.db.readonly: - return - - # Begin new database transaction - txn = self.get_db_txn(self.db.env) - self.db.txn = txn.begin() - - # Commit all add transactions to the database - db_map = lambda key: self.db_maps[key][0] - for (obj_type, trans_type), data in self.iteritems(): - if trans_type == TXNADD and obj_type in self.db_maps: - for handle, new_data in data: - assert handle == str(handle) - db_map(obj_type).put(handle, new_data, txn=txn.txn) - - # Commit all update transactions to the database - for (obj_type, trans_type), data in self.iteritems(): - if trans_type == TXNUPD and obj_type in self.db_maps: - for handle, new_data in data: - assert handle == str(handle) - db_map(obj_type).put(handle, new_data, txn=txn.txn) - - # Before we commit delete transactions, emit signals as required - - # Loop through the data maps, emitting signals as required - emit = self.__emit - for obj_type, (m_, obj_name) in self.db_maps.iteritems(): - # Do an emit for each object and transaction type as required - emit(obj_type, TXNADD, obj_name, '-add') - emit(obj_type, TXNUPD, obj_name, '-update') - emit(obj_type, TXNDEL, obj_name, '-delete') - - # Commit all delete transactions to the database - for (obj_type, trans_type), data in self.iteritems(): - if trans_type == TXNDEL and obj_type in self.db_maps: - for handle, n_ in data: - assert handle == str(handle) - db_map(obj_type).delete(handle, txn=txn.txn) - - # Add new reference keys as required - db_map = self.db.reference_map - if (REFERENCE_KEY, TXNADD) in self: - for handle, new_data in self[(REFERENCE_KEY, TXNADD)]: - assert handle == str(handle) - db_map.put(handle, new_data, txn=txn.txn) - - # Delete old reference keys as required - if (REFERENCE_KEY, TXNDEL) in self: - for handle, none_ in self[(REFERENCE_KEY, TXNDEL)]: - assert handle == str(handle) - db_map.delete(handle, txn=txn.txn) - - # Commit database transaction - txn.commit() - self.db.txn = None - self.clear() - return - - # Define helper function to do the actual emits - def __emit(self,obj_type, trans_type, obj, suffix): - if (obj_type, trans_type) in self: - handles = [handle for handle, data in - self[(obj_type, trans_type)]] - if handles: - self.db.emit(obj + suffix, (handles, )) - # Test functions def testtxn(): """ Test suite """ - class M(dict): + class FakeMap(dict): """Fake database map with just two methods""" - def put(self, key, data, txn=None): - super(M, self).__setitem__(key, data) - def delete(self, key, txn=None): - super(M, self).__delitem__(key) + def put(self, key, data): + """Set a property""" + super(FakeMap, self).__setitem__(key, data) + def delete(self, key): + """Delete a proptery""" + super(FakeMap, self).__delitem__(key) - class D: + class FakeDb: """Fake gramps database""" def __init__(self): - self.person_map = M() - self.family_map = M() - self.source_map = M() - self.event_map = M() - self.media_map = M() - self.place_map = M() - self.note_map = M() - self.repository_map = M() - self.reference_map = M() + self.person_map = FakeMap() + self.family_map = FakeMap() + self.event_map = FakeMap() + self.reference_map = FakeMap() self.readonly = False self.env = None + self.undodb = FakeCommitDb() + def transaction_commit(self, transaction): + """Commit the transaction to the undo database and cleanup.""" + transaction.clear() + self.undodb.commit(transaction) def emit(self, obj, value): + """send signal""" pass - class C(list): + class FakeCommitDb(list): """ Fake commit database""" - pass - - class G(DbTxn): - """Derived transacton class""" - def get_db_txn(self, env): - return T() - - class T(): - """Fake DBMS transaction class""" - def __init__(self): - self.txn = None - def begin(self): - return self - def commit(self): + def commit(self, transaction): + """commit transaction to undo db""" + pass + def undo(self): + """undo last transaction""" pass - commitdb = C() - grampsdb = D() - trans = G("Test Transaction", commitdb, grampsdb) + grampsdb = FakeDb() + commitdb = grampsdb.undodb + trans = DbTxn("Test Transaction", commitdb, grampsdb, batch=False) + grampsdb.person_map.put('1', "data1") trans.add(0, TXNADD, '1', None, "data1") + grampsdb.person_map.put('2', "data2") trans.add(0, TXNADD, '2', None, "data2") + grampsdb.person_map.put('2', "data3") trans.add(0, TXNUPD, '2', None, "data3") + grampsdb.person_map.delete('1') trans.add(0, TXNDEL, '1', None, None) print trans @@ -337,7 +239,6 @@ def testtxn(): print trans.get_record(i) print list(trans.get_recnos()) print list(trans.get_recnos(reverse=True)) - trans.commit("test") print grampsdb.person_map if __name__ == '__main__': diff --git a/src/gen/db/write.py b/src/gen/db/write.py index e10bbf2d0..b8cdea130 100644 --- a/src/gen/db/write.py +++ b/src/gen/db/write.py @@ -125,6 +125,16 @@ KEY_TO_CLASS_MAP = {PERSON_KEY: Person.__name__, NOTE_KEY: Note.__name__, TAG_KEY: Tag.__name__} +KEY_TO_NAME_MAP = {PERSON_KEY: 'person', + FAMILY_KEY: 'family', + EVENT_KEY: 'event', + SOURCE_KEY: 'source', + PLACE_KEY: 'place', + MEDIA_KEY: 'media', + REPOSITORY_KEY: 'repository', + #REFERENCE_KEY: 'reference', + NOTE_KEY: 'note', + TAG_KEY: 'tag'} #------------------------------------------------------------------------- # # Helper functions @@ -795,27 +805,15 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): # Add references to the reference_map for all primary object referenced # from the primary object 'obj' or any of its secondary objects. handle = obj.handle - update = self.reference_map_primary_map.has_key(str(handle)) - - if update: - # First thing to do is get hold of all rows in the reference_map - # table that hold a reference from this primary obj. This means - # finding all the rows that have this handle somewhere in the - # list of (class_name, handle) pairs. - # The primary_map sec index allows us to look this up quickly. - - existing_references = set() - - primary_cur = self.get_reference_map_primary_cursor() - - try: - ret = primary_cur.set(handle) - except: - ret = None - - while (ret is not None): - (key, data) = ret + existing_references = set() + primary_cur = self.get_reference_map_primary_cursor() + try: + ret = primary_cur.set(handle) + except: + ret = None + while (ret is not None): + (key, data) = ret # data values are of the form: # ((primary_object_class_name, primary_object_handle), # (referenced_object_class_name, referenced_object_handle)) @@ -824,31 +822,20 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): # get_referenced_handles_recursively # secondary DBs are not DBShelf's, so we need to do pickling - # and unpicking ourselves here - existing_reference = pickle.loads(data)[1] - existing_references.add( - (KEY_TO_CLASS_MAP[existing_reference[0]], + # and unpickling ourselves here + existing_reference = pickle.loads(data)[1] + existing_references.add((KEY_TO_CLASS_MAP[existing_reference[0]], existing_reference[1])) - ret = primary_cur.next_dup() + ret = primary_cur.next_dup() + primary_cur.close() - primary_cur.close() - - # Once we have the list of rows that already have a reference - # we need to compare it with the list of objects that are - # still references from the primary object. - - current_references = set(obj.get_referenced_handles_recursively()) - - no_longer_required_references = existing_references.difference( + # Once we have the list of rows that already have a reference + # we need to compare it with the list of objects that are + # still references from the primary object. + current_references = set(obj.get_referenced_handles_recursively()) + no_longer_required_references = existing_references.difference( current_references) - - new_references = current_references.difference(existing_references) - - else: - # No existing refs are found: - # all we have is new, nothing to remove - no_longer_required_references = set() - new_references = set(obj.get_referenced_handles_recursively()) + new_references = current_references.difference(existing_references) # handle addition of new references for (ref_class_name, ref_handle) in new_references: @@ -864,20 +851,19 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): # ignore missing old reference pass - def __remove_reference(self, key, transaction, txn=None): + def __remove_reference(self, key, transaction, txn): """ Remove the reference specified by the key, preserving the change in the passed transaction. """ if not self.readonly: - if transaction.batch: - self.reference_map.delete(str(key), txn=txn) - else: - old_data = self.reference_map.get(str(key), txn=self.txn) + if not transaction.batch: + old_data = self.reference_map.get(str(key), txn=txn) transaction.add(REFERENCE_KEY, TXNDEL, str(key), old_data, None) #transaction.reference_del.append(str(key)) + self.reference_map.delete(str(key), txn=txn) - def __add_reference(self, key, data, transaction, txn=None): + def __add_reference(self, key, data, transaction, txn): """ Add the reference specified by the key and the data, preserving the change in the passed transaction. @@ -886,9 +872,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): if self.readonly or not key: return - if transaction.batch: - self.reference_map.put(str(key), data, txn=txn) - else: + self.reference_map.put(str(key), data, txn=txn) + if not transaction.batch: transaction.add(REFERENCE_KEY, TXNADD, str(key), None, data) #transaction.reference_add.append((str(key), data)) @@ -930,34 +915,34 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): # Make a tuple of the functions and classes that we need for # each of the primary object tables. - transaction = self.transaction_begin(batch=True, no_magic=True) - callback(4) + with self.transaction_begin(_("Rebuild reference map"), batch=True, + no_magic=True) as transaction: + callback(4) - primary_table = ( - (self.get_person_cursor, Person), - (self.get_family_cursor, Family), - (self.get_event_cursor, Event), - (self.get_place_cursor, Place), - (self.get_source_cursor, Source), - (self.get_media_cursor, MediaObject), - (self.get_repository_cursor, Repository), - (self.get_note_cursor, Note), - (self.get_tag_cursor, Tag), - ) + primary_table = ( + (self.get_person_cursor, Person), + (self.get_family_cursor, Family), + (self.get_event_cursor, Event), + (self.get_place_cursor, Place), + (self.get_source_cursor, Source), + (self.get_media_cursor, MediaObject), + (self.get_repository_cursor, Repository), + (self.get_note_cursor, Note), + (self.get_tag_cursor, Tag), + ) - # Now we use the functions and classes defined above - # to loop through each of the primary object tables. + # Now we use the functions and classes defined above + # to loop through each of the primary object tables. - for cursor_func, class_func in primary_table: - with cursor_func() as cursor: - for found_handle, val in cursor: - obj = class_func() - obj.unserialize(val) - with BSDDBTxn(self.env) as txn: - self.update_reference_map(obj, transaction, txn.txn) + for cursor_func, class_func in primary_table: + with cursor_func() as cursor: + for found_handle, val in cursor: + obj = class_func() + obj.unserialize(val) + with BSDDBTxn(self.env) as txn: + self.update_reference_map(obj, transaction, txn.txn) - callback(5) - self.transaction_commit(transaction, _("Rebuild reference map")) + callback(5) self.reference_map_referenced_map = self.__open_db(self.full_name, REF_REF, db.DB_BTREE, db.DB_DUP|db.DB_DUPSORT) @@ -1239,8 +1224,10 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): txn=txn.txn) txn.delete(handle) else: - self.delete_primary_from_reference_map(handle, transaction) + self.delete_primary_from_reference_map(handle, transaction, + txn=self.txn) old_data = data_map.get(handle, txn=self.txn) + data_map.delete(handle, txn=self.txn) transaction.add(key, TXNDEL, handle, old_data, None) #del_list.append(handle) @@ -1252,14 +1239,18 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): if self.readonly or not handle: return - self.delete_primary_from_reference_map(handle, transaction) person = self.get_person_from_handle(handle) self.genderStats.uncount_person (person) self.remove_from_surname_list(person) if transaction.batch: with BSDDBTxn(self.env, self.person_map) as txn: + self.delete_primary_from_reference_map(handle, transaction, + txn=txn.txn) txn.delete(handle) else: + self.delete_primary_from_reference_map(handle, transaction, + txn=self.txn) + self.person_map.delete(str(handle), txn=self.txn) transaction.add(PERSON_KEY, TXNDEL, handle, person.serialize(), None) #transaction.person_del.append(str(handle)) @@ -1405,19 +1396,15 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): obj.change = int(change_time or time.time()) handle = str(obj.handle) - self.update_reference_map(obj, transaction) + self.update_reference_map(obj, transaction, self.txn) - # If this is a batch operation, just write the data - if transaction.batch: - data_map.put(handle, obj.serialize()) - old_data = None - - # Otherwise, this is a non-batch operation, so queue the transaction - else: + new_data = obj.serialize() + old_data = None + if not transaction.batch: old_data = data_map.get(handle, txn=self.txn) - new_data = obj.serialize() op = TXNUPD if old_data else TXNADD transaction.add(key, op, handle, old_data, new_data) + data_map.put(handle, new_data, txn=self.txn) return old_data def commit_person(self, person, transaction, change_time=None): @@ -1639,7 +1626,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): transaction_commit function of the this database object. """ - transaction = BdbTransaction(msg, self.undodb, self, batch, no_magic) + transaction = DbTxn(msg, self.undodb, self, batch) + transaction.no_magic = no_magic if batch: # A batch transaction does not store the commits # Aborting the session completely will become impossible. @@ -1663,10 +1651,19 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): _db.remove(_mkname(self.full_name, REF_REF), REF_REF) except db.DBNoSuchFileError: pass + else: + self.bsddbtxn = BSDDBTxn(self.env) + self.txn = self.bsddbtxn.begin() return transaction @catch_db_error - def transaction_commit(self, transaction, msg): + def transaction_commit(self, transaction, msg=''): + """ + Make the changes to the database final and add the content of the + transaction to the undo database. + """ + if not msg: + msg = transaction.get_description() if self._LOG_ALL: _LOG.debug("%s: Transaction commit '%s'\n" % (self.__class__.__name__, str(msg))) @@ -1674,12 +1671,60 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): if self.readonly: return - transaction.commit(msg) + if self.txn is not None: + assert transaction.get_description() != '' + self.bsddbtxn.commit() + self.bsddbtxn = None + self.txn = None + self.env.log_flush() + if not transaction.batch: + emit = self.__emit + for obj_type, obj_name in KEY_TO_NAME_MAP.iteritems(): + emit(transaction, obj_type, TXNADD, obj_name, '-add') + emit(transaction, obj_type, TXNUPD, obj_name, '-update') + emit(transaction, obj_type, TXNDEL, obj_name, '-delete') + transaction.clear() self.undodb.commit(transaction, msg) - self.__after_commit(transaction, msg) + self.__after_commit(transaction) self.has_changed = True - def __after_commit(self, transaction, msg): + def __emit(self, transaction, obj_type, trans_type, obj, suffix): + """ + Define helper function to do the actual emits + """ + if (obj_type, trans_type) in transaction: + if trans_type == TXNDEL: + handles = [handle for handle, data in + transaction[(obj_type, trans_type)]] + else: + handles = [handle for handle, data in + transaction[(obj_type, trans_type)] + if (handle, None) not in transaction[(obj_type, + TXNDEL)]] + if handles: + self.emit(obj + suffix, (handles, )) + + def transaction_abort(self, transaction): + """ + Revert the changes made to the database. + """ + if self._LOG_ALL: + _LOG.debug("%s: Transaction abort '%s'\n" + % (self.__class__.__name__, str(transaction.get_description()))) + + if self.readonly: + return + + if self.txn is not None: + self.bsddbtxn.abort() + self.bsddbtxn = None + self.txn = None + transaction.clear() + transaction.first = None + transaction.last = None + self.__after_commit(transaction) + + def __after_commit(self, transaction): """ Post-transaction commit processing """ @@ -1800,34 +1845,6 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): return self.brief_name -#------------------------------------------------------------------------- -# -# BdbTransaction -# -#------------------------------------------------------------------------- -class BdbTransaction(DbTxn): - """ - The batch parameter is set to True for large transactions. For such - transactions, the list of changes is not maintained, and no undo - is possible. - - The no_magic parameter is ignored for non-batch transactions, and - is also of no importance for DB backends other than BSD DB. For - the BSDDB, when this paramter is set to True, some secondary - indices will be removed at the beginning and then rebuilt at - the end of such transaction (only if it is batch). - """ - - __slots__ = ('batch', 'no_magic') - - def __init__(self, msg, undodb, grampsdb, batch=False, no_magic=False): - DbTxn.__init__(self, msg, undodb, grampsdb) - self.batch = batch - self.no_magic = no_magic - - def get_db_txn(self, value): - return BSDDBTxn(value) - def _mkname(path, name): return os.path.join(path, name + DBEXT) diff --git a/src/gui/editors/displaytabs/gallerytab.py b/src/gui/editors/displaytabs/gallerytab.py index 2e2c79f2c..6bb5904df 100644 --- a/src/gui/editors/displaytabs/gallerytab.py +++ b/src/gui/editors/displaytabs/gallerytab.py @@ -476,14 +476,13 @@ class GalleryTab(ButtonTab, DbGUIElement): basename = os.path.basename(name) (root, ext) = os.path.splitext(basename) photo.set_description(root) - trans = self.dbstate.db.transaction_begin() - self.dbstate.db.add_object(photo, trans) - oref = gen.lib.MediaRef() - oref.set_reference_handle(photo.get_handle()) - self.get_data().append(oref) - self.changed = True - self.dbstate.db.transaction_commit(trans, - _("Drag Media Object")) + with self.dbstate.db.transaction_begin( + _("Drag Media Object")) as trans: + self.dbstate.db.add_object(photo, trans) + oref = gen.lib.MediaRef() + oref.set_reference_handle(photo.get_handle()) + self.get_data().append(oref) + self.changed = True self.rebuild() def handle_extra_type(self, objtype, obj): diff --git a/src/gui/editors/editevent.py b/src/gui/editors/editevent.py index 80f45b577..8e825175a 100644 --- a/src/gui/editors/editevent.py +++ b/src/gui/editors/editevent.py @@ -253,19 +253,17 @@ class EditEvent(EditPrimary): return if not self.obj.handle: - trans = self.db.transaction_begin() - self.db.add_event(self.obj, trans) - self.db.transaction_commit(trans, - _("Add Event (%s)") % self.obj.get_gramps_id()) + with self.db.transaction_begin(_("Add Event (%s)") % + self.obj.get_gramps_id()) as trans: + self.db.add_event(self.obj, trans) else: orig = self.get_from_handle(self.obj.handle) if cmp(self.obj.serialize(), orig.serialize()): - trans = self.db.transaction_begin() - if not self.obj.get_gramps_id(): - self.obj.set_gramps_id(self.db.find_next_event_gramps_id()) - self.commit_event(self.obj, trans) - self.db.transaction_commit(trans, - _("Edit Event (%s)") % self.obj.get_gramps_id()) + with self.db.transaction_begin(_("Edit Event (%s)") % + self.obj.get_gramps_id()) as trans: + if not self.obj.get_gramps_id(): + self.obj.set_gramps_id(self.db.find_next_event_gramps_id()) + self.commit_event(self.obj, trans) if self.callback: self.callback(self.obj) @@ -333,22 +331,21 @@ class DeleteEventQuery(object): self.family_list = family_list def query_response(self): - trans = self.db.transaction_begin() - self.db.disable_signals() + with self.db.transaction_begin(_("Delete Event (%s)") % + self.event.get_gramps_id()) as trans: + self.db.disable_signals() - ev_handle_list = [self.event.get_handle()] + ev_handle_list = [self.event.get_handle()] - for handle in self.person_list: - person = self.db.get_person_from_handle(handle) - person.remove_handle_references('Event', ev_handle_list) - self.db.commit_person(person, trans) + for handle in self.person_list: + person = self.db.get_person_from_handle(handle) + person.remove_handle_references('Event', ev_handle_list) + self.db.commit_person(person, trans) - for handle in self.family_list: - family = self.db.get_family_from_handle(handle) - family.remove_handle_references('Event', ev_handle_list) - self.db.commit_family(family, trans) + for handle in self.family_list: + family = self.db.get_family_from_handle(handle) + family.remove_handle_references('Event', ev_handle_list) + self.db.commit_family(family, trans) - self.db.enable_signals() - self.db.remove_event(self.event.get_handle(), trans) - self.db.transaction_commit(trans, - _("Delete Event (%s)") % self.event.get_gramps_id()) + self.db.enable_signals() + self.db.remove_event(self.event.get_handle(), trans) diff --git a/src/gui/editors/editeventref.py b/src/gui/editors/editeventref.py index 50d4e3317..92b83a18a 100644 --- a/src/gui/editors/editeventref.py +++ b/src/gui/editors/editeventref.py @@ -236,13 +236,12 @@ class EditEventRef(EditReference): def ok_clicked(self, obj): - trans = self.db.transaction_begin() if self.source.handle: - self.commit_event(self.source,trans) - self.db.transaction_commit(trans,_("Modify Event")) + with self.db.transaction_begin(_("Modify Event")) as trans: + self.commit_event(self.source,trans) else: - self.add_event(self.source,trans) - self.db.transaction_commit(trans,_("Add Event")) + with self.db.transaction_begin(_("Add Event")) as trans: + self.add_event(self.source,trans) self.source_ref.ref = self.source.handle if self.update: diff --git a/src/gui/editors/editfamily.py b/src/gui/editors/editfamily.py index fac592af1..7e52f2393 100644 --- a/src/gui/editors/editfamily.py +++ b/src/gui/editors/editfamily.py @@ -1060,62 +1060,61 @@ class EditFamily(EditPrimary): self._cleanup_callbacks() if not original and not self.object_is_empty(): - trans = self.db.transaction_begin() + with self.db.transaction_begin(_("Add Family")) as trans: - # find the father, add the family handle to the father - handle = self.obj.get_father_handle() - if handle: - parent = self.db.get_person_from_handle(handle) - parent.add_family_handle(self.obj.handle) - self.db.commit_person(parent, trans) + # find the father, add the family handle to the father + handle = self.obj.get_father_handle() + if handle: + parent = self.db.get_person_from_handle(handle) + parent.add_family_handle(self.obj.handle) + self.db.commit_person(parent, trans) - # find the mother, add the family handle to the mother - handle = self.obj.get_mother_handle() - if handle: - parent = self.db.get_person_from_handle(handle) - parent.add_family_handle(self.obj.handle) - self.db.commit_person(parent, trans) + # find the mother, add the family handle to the mother + handle = self.obj.get_mother_handle() + if handle: + parent = self.db.get_person_from_handle(handle) + parent.add_family_handle(self.obj.handle) + self.db.commit_person(parent, trans) - # for each child, add the family handle to the child - for ref in self.obj.get_child_ref_list(): - child = self.db.get_person_from_handle(ref.ref) - # fix - relationships need to be extracted from the list - child.add_parent_family_handle(self.obj.handle) - self.db.commit_person(child, trans) + # for each child, add the family handle to the child + for ref in self.obj.get_child_ref_list(): + child = self.db.get_person_from_handle(ref.ref) + # fix - relationships need to be extracted from the list + child.add_parent_family_handle(self.obj.handle) + self.db.commit_person(child, trans) - self.db.add_family(self.obj, trans) - self.db.transaction_commit(trans, _("Add Family")) + self.db.add_family(self.obj, trans) elif cmp(original.serialize(),self.obj.serialize()): - trans = self.db.transaction_begin() + with self.db.transaction_begin(_("Edit Family")) as trans: - self.fix_parent_handles(original.get_father_handle(), - self.obj.get_father_handle(), trans) - self.fix_parent_handles(original.get_mother_handle(), - self.obj.get_mother_handle(), trans) + self.fix_parent_handles(original.get_father_handle(), + self.obj.get_father_handle(), trans) + self.fix_parent_handles(original.get_mother_handle(), + self.obj.get_mother_handle(), trans) - orig_set = set(original.get_child_ref_list()) - new_set = set(self.obj.get_child_ref_list()) + orig_set = set(original.get_child_ref_list()) + new_set = set(self.obj.get_child_ref_list()) - # remove the family from children which have been removed - for ref in orig_set.difference(new_set): - person = self.db.get_person_from_handle(ref.ref) - person.remove_parent_family_handle(self.obj.handle) - self.db.commit_person(person, trans) + # remove the family from children which have been removed + for ref in orig_set.difference(new_set): + person = self.db.get_person_from_handle(ref.ref) + person.remove_parent_family_handle(self.obj.handle) + self.db.commit_person(person, trans) - # add the family to children which have been added - for ref in new_set.difference(orig_set): - person = self.db.get_person_from_handle(ref.ref) - person.add_parent_family_handle(self.obj.handle) - self.db.commit_person(person, trans) + # add the family to children which have been added + for ref in new_set.difference(orig_set): + person = self.db.get_person_from_handle(ref.ref) + person.add_parent_family_handle(self.obj.handle) + self.db.commit_person(person, trans) - if self.object_is_empty(): - self.db.remove_family(self.obj.handle, trans) - else: - if not self.obj.get_gramps_id(): - self.obj.set_gramps_id(self.db.find_next_family_gramps_id()) - self.db.commit_family(self.obj, trans) - self.db.transaction_commit(trans, _("Edit Family")) + if self.object_is_empty(): + self.db.remove_family(self.obj.handle, trans) + else: + if not self.obj.get_gramps_id(): + self.obj.set_gramps_id( + self.db.find_next_family_gramps_id()) + self.db.commit_family(self.obj, trans) self._do_close() diff --git a/src/gui/editors/editmedia.py b/src/gui/editors/editmedia.py index 489fff53e..ebc3f4359 100644 --- a/src/gui/editors/editmedia.py +++ b/src/gui/editors/editmedia.py @@ -288,18 +288,17 @@ class EditMedia(EditPrimary): self.obj.set_path(Utils.get_unicode_path_from_file_chooser(path)) - trans = self.db.transaction_begin() - if not self.obj.get_handle(): - self.db.add_object(self.obj, trans) - msg = _("Add Media Object (%s)") % self.obj.get_description() - else: - if not self.obj.get_gramps_id(): - self.obj.set_gramps_id(self.db.find_next_object_gramps_id()) - self.db.commit_media_object(self.obj, trans) - msg = _("Edit Media Object (%s)") % self.obj.get_description() - - self.db.transaction_commit(trans, msg) - + with self.db.transaction_begin() as trans: + if not self.obj.get_handle(): + self.db.add_object(self.obj, trans) + msg = _("Add Media Object (%s)") % self.obj.get_description() + else: + if not self.obj.get_gramps_id(): + self.obj.set_gramps_id(self.db.find_next_object_gramps_id()) + self.db.commit_media_object(self.obj, trans) + msg = _("Edit Media Object (%s)") % self.obj.get_description() + trans.set_description(msg) + if self.callback: self.callback(self.obj) self.close() @@ -336,47 +335,46 @@ class DeleteMediaQuery(object): self.the_lists = the_lists def query_response(self): - trans = self.db.transaction_begin() - self.db.disable_signals() + with self.db.transaction_begin(_("Remove Media Object")) as trans: + self.db.disable_signals() - (person_list, family_list, event_list, - place_list,source_list) = self.the_lists + (person_list, family_list, event_list, + place_list, source_list) = self.the_lists - for handle in person_list: - person = self.db.get_person_from_handle(handle) - new_list = [photo for photo in person.get_media_list() - if photo.get_reference_handle() != self.media_handle] - person.set_media_list(new_list) - self.db.commit_person(person, trans) + for handle in person_list: + person = self.db.get_person_from_handle(handle) + new_list = [photo for photo in person.get_media_list() + if photo.get_reference_handle() != self.media_handle] + person.set_media_list(new_list) + self.db.commit_person(person, trans) - for handle in family_list: - family = self.db.get_family_from_handle(handle) - new_list = [photo for photo in family.get_media_list() - if photo.get_reference_handle() != self.media_handle] - family.set_media_list(new_list) - self.db.commit_family(family, trans) + for handle in family_list: + family = self.db.get_family_from_handle(handle) + new_list = [photo for photo in family.get_media_list() + if photo.get_reference_handle() != self.media_handle] + family.set_media_list(new_list) + self.db.commit_family(family, trans) - for handle in event_list: - event = self.db.get_event_from_handle(handle) - new_list = [photo for photo in event.get_media_list() - if photo.get_reference_handle() != self.media_handle] - event.set_media_list(new_list) - self.db.commit_event(event, trans) + for handle in event_list: + event = self.db.get_event_from_handle(handle) + new_list = [photo for photo in event.get_media_list() + if photo.get_reference_handle() != self.media_handle] + event.set_media_list(new_list) + self.db.commit_event(event, trans) - for handle in place_list: - place = self.db.get_place_from_handle(handle) - new_list = [photo for photo in place.get_media_list() - if photo.get_reference_handle() != self.media_handle] - place.set_media_list(new_list) - self.db.commit_place(place, trans) + for handle in place_list: + place = self.db.get_place_from_handle(handle) + new_list = [photo for photo in place.get_media_list() + if photo.get_reference_handle() != self.media_handle] + place.set_media_list(new_list) + self.db.commit_place(place, trans) - for handle in source_list: - source = self.db.get_source_from_handle(handle) - new_list = [photo for photo in source.get_media_list() - if photo.get_reference_handle() != self.media_handle] - source.set_media_list(new_list) - self.db.commit_source(source, trans) + for handle in source_list: + source = self.db.get_source_from_handle(handle) + new_list = [photo for photo in source.get_media_list() + if photo.get_reference_handle() != self.media_handle] + source.set_media_list(new_list) + self.db.commit_source(source, trans) - self.db.enable_signals() - self.db.remove_object(self.media_handle, trans) - self.db.transaction_commit(trans, _("Remove Media Object")) + self.db.enable_signals() + self.db.remove_object(self.media_handle, trans) diff --git a/src/gui/editors/editmediaref.py b/src/gui/editors/editmediaref.py index 95bf5d43f..6ef741b50 100644 --- a/src/gui/editors/editmediaref.py +++ b/src/gui/editors/editmediaref.py @@ -586,15 +586,14 @@ class EditMediaRef(EditReference): def save(self,*obj): #first save primary object - trans = self.db.transaction_begin() if self.source.handle: - self.db.commit_media_object(self.source, trans) - self.db.transaction_commit(trans, _("Edit Media Object (%s)" - ) % self.source.get_description()) + with self.db.transaction_begin(_("Edit Media Object (%s)" + ) % self.source.get_description()) as trans: + self.db.commit_media_object(self.source, trans) else: - self.db.add_object(self.source, trans) - self.db.transaction_commit(trans,_("Add Media Object (%s)" - ) % self.source.get_description()) + with self.db.transaction_begin(_("Add Media Object (%s)" + ) % self.source.get_description()) as trans: + self.db.add_object(self.source, trans) #save reference object in memory coord = ( diff --git a/src/gui/editors/editnote.py b/src/gui/editors/editnote.py index c32788996..145e0af68 100644 --- a/src/gui/editors/editnote.py +++ b/src/gui/editors/editnote.py @@ -317,19 +317,17 @@ class EditNote(EditPrimary): self.ok_button.set_sensitive(True) return - trans = self.db.transaction_begin() - - if not self.obj.get_handle(): - self.db.add_note(self.obj, trans) - msg = _("Add Note") - else: - if not self.obj.get_gramps_id(): - self.obj.set_gramps_id(self.db.find_next_note_gramps_id()) - self.db.commit_note(self.obj, trans) - msg = _("Edit Note") + with self.db.transaction_begin() as trans: + if not self.obj.get_handle(): + self.db.add_note(self.obj, trans) + msg = _("Add Note") + else: + if not self.obj.get_gramps_id(): + self.obj.set_gramps_id(self.db.find_next_note_gramps_id()) + self.db.commit_note(self.obj, trans) + msg = _("Edit Note") + trans.set_description(msg) - self.db.transaction_commit(trans, msg) - if self.callback: self.callback(self.obj.get_handle()) self.close() @@ -342,50 +340,49 @@ class DeleteNoteQuery(object): self.the_lists = the_lists def query_response(self): - trans = self.db.transaction_begin() - self.db.disable_signals() + with self.db.transaction_begin(_("Delete Note (%s)") % + self.note.get_gramps_id()) as trans: + self.db.disable_signals() - (person_list, family_list, event_list, place_list, source_list, - media_list, repo_list) = self.the_lists + (person_list, family_list, event_list, place_list, source_list, + media_list, repo_list) = self.the_lists - note_handle = self.note.get_handle() + note_handle = self.note.get_handle() - for handle in person_list: - person = self.db.get_person_from_handle(handle) - person.remove_note(note_handle) - self.db.commit_person(person, trans) + for handle in person_list: + person = self.db.get_person_from_handle(handle) + person.remove_note(note_handle) + self.db.commit_person(person, trans) - for handle in family_list: - family = self.db.get_family_from_handle(handle) - family.remove_note(note_handle) - self.db.commit_family(family, trans) + for handle in family_list: + family = self.db.get_family_from_handle(handle) + family.remove_note(note_handle) + self.db.commit_family(family, trans) - for handle in event_list: - event = self.db.get_event_from_handle(handle) - event.remove_note(note_handle) - self.db.commit_event(event, trans) + for handle in event_list: + event = self.db.get_event_from_handle(handle) + event.remove_note(note_handle) + self.db.commit_event(event, trans) - for handle in place_list: - place = self.db.get_place_from_handle(handle) - place.remove_note(note_handle) - self.db.commit_place(place, trans) + for handle in place_list: + place = self.db.get_place_from_handle(handle) + place.remove_note(note_handle) + self.db.commit_place(place, trans) - for handle in source_list: - source = self.db.get_source_from_handle(handle) - source.remove_note(note_handle) - self.db.commit_source(source, trans) + for handle in source_list: + source = self.db.get_source_from_handle(handle) + source.remove_note(note_handle) + self.db.commit_source(source, trans) - for handle in media_list: - media = self.db.get_object_from_handle(handle) - media.remove_note(note_handle) - self.db.commit_media_object(media, trans) + for handle in media_list: + media = self.db.get_object_from_handle(handle) + media.remove_note(note_handle) + self.db.commit_media_object(media, trans) - for handle in repo_list: - repo = self.db.get_repository_from_handle(handle) - repo.remove_note(note_handle) - self.db.commit_repository(repo, trans) + for handle in repo_list: + repo = self.db.get_repository_from_handle(handle) + repo.remove_note(note_handle) + self.db.commit_repository(repo, trans) - self.db.enable_signals() - self.db.remove_note(note_handle, trans) - self.db.transaction_commit( - trans,_("Delete Note (%s)") % self.note.get_gramps_id()) + self.db.enable_signals() + self.db.remove_note(note_handle, trans) diff --git a/src/gui/editors/editperson.py b/src/gui/editors/editperson.py index 5baec5372..ef0de00f0 100644 --- a/src/gui/editors/editperson.py +++ b/src/gui/editors/editperson.py @@ -868,21 +868,20 @@ class EditPerson(EditPrimary): self.db.set_birth_death_index(self.obj) - trans = self.db.transaction_begin() + with self.db.transaction_begin() as trans: + self._update_family_ids() + if not self.obj.get_handle(): + self.db.add_person(self.obj, trans) + msg = _("Add Person (%s)") % \ + self.name_displayer.display(self.obj) + else: + if not self.obj.get_gramps_id(): + self.obj.set_gramps_id(self.db.find_next_person_gramps_id()) + self.db.commit_person(self.obj, trans) + msg = _("Edit Person (%s)") % \ + self.name_displayer.display(self.obj) + trans.set_description(msg) - - self._update_family_ids() - - if not self.obj.get_handle(): - self.db.add_person(self.obj, trans) - msg = _("Add Person (%s)") % self.name_displayer.display(self.obj) - else: - if not self.obj.get_gramps_id(): - self.obj.set_gramps_id(self.db.find_next_person_gramps_id()) - self.db.commit_person(self.obj, trans) - msg = _("Edit Person (%s)") % self.name_displayer.display(self.obj) - - self.db.transaction_commit(trans, msg) self.close() if self.callback: self.callback(self.obj) diff --git a/src/gui/editors/editplace.py b/src/gui/editors/editplace.py index 1cc6330d4..9cbc70039 100644 --- a/src/gui/editors/editplace.py +++ b/src/gui/editors/editplace.py @@ -306,16 +306,16 @@ class EditPlace(EditPrimary): self.ok_button.set_sensitive(True) return - trans = self.db.transaction_begin() - if not self.obj.get_handle(): - self.db.add_place(self.obj, trans) - msg = _("Add Place (%s)") % self.obj.get_title() - else: - if not self.obj.get_gramps_id(): - self.obj.set_gramps_id(self.db.find_next_place_gramps_id()) - self.db.commit_place(self.obj, trans) - msg = _("Edit Place (%s)") % self.obj.get_title() - self.db.transaction_commit(trans, msg) + with self.db.transaction_begin() as trans: + if not self.obj.get_handle(): + self.db.add_place(self.obj, trans) + msg = _("Add Place (%s)") % self.obj.get_title() + else: + if not self.obj.get_gramps_id(): + self.obj.set_gramps_id(self.db.find_next_place_gramps_id()) + self.db.commit_place(self.obj, trans) + msg = _("Edit Place (%s)") % self.obj.get_title() + trans.set_description(msg) self.close() if self.callback: @@ -338,27 +338,26 @@ class DeletePlaceQuery(object): self.event_list = event_list def query_response(self): - trans = self.db.transaction_begin() - self.db.disable_signals() + with self.db.transaction_begin(_("Delete Place (%s)") % + self.obj.get_title()) as trans: + self.db.disable_signals() - place_handle = self.obj.get_handle() + place_handle = self.obj.get_handle() - for handle in self.person_list: - person = self.db.get_person_from_handle(handle) - person.remove_handle_references('Place', place_handle) - self.db.commit_person(person, trans) + for handle in self.person_list: + person = self.db.get_person_from_handle(handle) + person.remove_handle_references('Place', place_handle) + self.db.commit_person(person, trans) - for handle in self.family_list: - family = self.db.get_family_from_handle(handle) - family.remove_handle_references('Place', place_handle) - self.db.commit_family(family, trans) + for handle in self.family_list: + family = self.db.get_family_from_handle(handle) + family.remove_handle_references('Place', place_handle) + self.db.commit_family(family, trans) - for handle in self.event_list: - event = self.db.get_event_from_handle(handle) - event.remove_handle_references('Place', place_handle) - self.db.commit_event(event, trans) + for handle in self.event_list: + event = self.db.get_event_from_handle(handle) + event.remove_handle_references('Place', place_handle) + self.db.commit_event(event, trans) - self.db.enable_signals() - self.db.remove_place(place_handle, trans) - self.db.transaction_commit( - trans,_("Delete Place (%s)") % self.obj.get_title()) + self.db.enable_signals() + self.db.remove_place(place_handle, trans) diff --git a/src/gui/editors/editreporef.py b/src/gui/editors/editreporef.py index 51e5c49f7..7605f6460 100644 --- a/src/gui/editors/editreporef.py +++ b/src/gui/editors/editreporef.py @@ -189,13 +189,12 @@ class EditRepoRef(EditReference): def ok_clicked(self, obj): - trans = self.db.transaction_begin() if self.source.handle: - self.db.commit_repository(self.source,trans) - self.db.transaction_commit(trans,_("Modify Repository")) + with self.db.transaction_begin(_("Modify Repository")) as trans: + self.db.commit_repository(self.source,trans) else: - self.db.add_repository(self.source,trans) - self.db.transaction_commit(trans,_("Add Repository")) + with self.db.transaction_begin(_("Add Repository")) as trans: + self.db.add_repository(self.source,trans) self.source_ref.ref = self.source.handle if self.update: diff --git a/src/gui/editors/editrepository.py b/src/gui/editors/editrepository.py index c3afada9e..75016f767 100644 --- a/src/gui/editors/editrepository.py +++ b/src/gui/editors/editrepository.py @@ -177,17 +177,17 @@ class EditRepository(EditPrimary): self.ok_button.set_sensitive(True) return - trans = self.db.transaction_begin() - if not self.obj.get_handle(): - self.db.add_repository(self.obj, trans) - msg = _("Add Repository (%s)") % self.obj.get_name() - else: - if not self.obj.get_gramps_id(): - self.obj.set_gramps_id(self.db.find_next_repository_gramps_id()) - self.db.commit_repository(self.obj, trans) - msg = _("Edit Repository (%s)") % self.obj.get_name() + with self.db.transaction_begin() as trans: + if not self.obj.get_handle(): + self.db.add_repository(self.obj, trans) + msg = _("Add Repository (%s)") % self.obj.get_name() + else: + if not self.obj.get_gramps_id(): + self.obj.set_gramps_id(self.db.find_next_repository_gramps_id()) + self.db.commit_repository(self.obj, trans) + msg = _("Edit Repository (%s)") % self.obj.get_name() + trans.set_description(msg) - self.db.transaction_commit(trans, msg) self.close() class DeleteRepositoryQuery(object): @@ -198,15 +198,14 @@ class DeleteRepositoryQuery(object): self.sources = sources def query_response(self): - trans = self.db.transaction_begin() + with self.db.transaction_begin(_("Delete Repository (%s)") % + self.obj.get_name()) as trans: - repos_handle_list = [self.obj.get_handle()] + repos_handle_list = [self.obj.get_handle()] - for handle in self.sources: - source = self.db.get_source_from_handle(handle) - source.remove_repo_references(repos_handle_list) - self.db.commit_source(source, trans) + for handle in self.sources: + source = self.db.get_source_from_handle(handle) + source.remove_repo_references(repos_handle_list) + self.db.commit_source(source, trans) - self.db.remove_repository(self.obj.get_handle(), trans) - self.db.transaction_commit( - trans, _("Delete Repository (%s)") % self.obj.get_name()) + self.db.remove_repository(self.obj.get_handle(), trans) diff --git a/src/gui/editors/editsource.py b/src/gui/editors/editsource.py index ffa084cd1..710a9d7b8 100644 --- a/src/gui/editors/editsource.py +++ b/src/gui/editors/editsource.py @@ -195,17 +195,17 @@ class EditSource(EditPrimary): self.ok_button.set_sensitive(True) return - trans = self.db.transaction_begin() - if not self.obj.get_handle(): - self.db.add_source(self.obj, trans) - msg = _("Add Source (%s)") % self.obj.get_title() - else: - if not self.obj.get_gramps_id(): - self.obj.set_gramps_id(self.db.find_next_source_gramps_id()) - self.db.commit_source(self.obj, trans) - msg = _("Edit Source (%s)") % self.obj.get_title() + with self.db.transaction_begin() as trans: + if not self.obj.get_handle(): + self.db.add_source(self.obj, trans) + msg = _("Add Source (%s)") % self.obj.get_title() + else: + if not self.obj.get_gramps_id(): + self.obj.set_gramps_id(self.db.find_next_source_gramps_id()) + self.db.commit_source(self.obj, trans) + msg = _("Edit Source (%s)") % self.obj.get_title() + trans.set_description(msg) - self.db.transaction_commit(trans, msg) self.close() class DeleteSrcQuery(object): @@ -216,50 +216,49 @@ class DeleteSrcQuery(object): self.the_lists = the_lists def query_response(self): - trans = self.db.transaction_begin() - self.db.disable_signals() + with self.db.transaction_begin(_("Delete Source (%s)") % + self.source.get_title()) as trans: + self.db.disable_signals() - (person_list, family_list, event_list, place_list, source_list, - media_list, repo_list) = self.the_lists + (person_list, family_list, event_list, place_list, source_list, + media_list, repo_list) = self.the_lists - src_handle_list = [self.source.get_handle()] + src_handle_list = [self.source.get_handle()] - for handle in person_list: - person = self.db.get_person_from_handle(handle) - person.remove_source_references(src_handle_list) - self.db.commit_person(person, trans) + for handle in person_list: + person = self.db.get_person_from_handle(handle) + person.remove_source_references(src_handle_list) + self.db.commit_person(person, trans) - for handle in family_list: - family = self.db.get_family_from_handle(handle) - family.remove_source_references(src_handle_list) - self.db.commit_family(family, trans) + for handle in family_list: + family = self.db.get_family_from_handle(handle) + family.remove_source_references(src_handle_list) + self.db.commit_family(family, trans) - for handle in event_list: - event = self.db.get_event_from_handle(handle) - event.remove_source_references(src_handle_list) - self.db.commit_event(event, trans) + for handle in event_list: + event = self.db.get_event_from_handle(handle) + event.remove_source_references(src_handle_list) + self.db.commit_event(event, trans) - for handle in place_list: - place = self.db.get_place_from_handle(handle) - place.remove_source_references(src_handle_list) - self.db.commit_place(place, trans) + for handle in place_list: + place = self.db.get_place_from_handle(handle) + place.remove_source_references(src_handle_list) + self.db.commit_place(place, trans) - for handle in source_list: - source = self.db.get_source_from_handle(handle) - source.remove_source_references(src_handle_list) - self.db.commit_source(source, trans) + for handle in source_list: + source = self.db.get_source_from_handle(handle) + source.remove_source_references(src_handle_list) + self.db.commit_source(source, trans) - for handle in media_list: - media = self.db.get_object_from_handle(handle) - media.remove_source_references(src_handle_list) - self.db.commit_media_object(media, trans) + for handle in media_list: + media = self.db.get_object_from_handle(handle) + media.remove_source_references(src_handle_list) + self.db.commit_media_object(media, trans) - for handle in repo_list: - repo = self.db.get_repository_from_handle(handle) - repo.remove_source_references(src_handle_list) - self.db.commit_repository(repo, trans) + for handle in repo_list: + repo = self.db.get_repository_from_handle(handle) + repo.remove_source_references(src_handle_list) + self.db.commit_repository(repo, trans) - self.db.enable_signals() - self.db.remove_source(self.source.get_handle(), trans) - self.db.transaction_commit( - trans, _("Delete Source (%s)") % self.source.get_title()) + self.db.enable_signals() + self.db.remove_source(self.source.get_handle(), trans) diff --git a/src/gui/editors/editsourceref.py b/src/gui/editors/editsourceref.py index 5095d878a..231594791 100644 --- a/src/gui/editors/editsourceref.py +++ b/src/gui/editors/editsourceref.py @@ -205,13 +205,12 @@ class EditSourceRef(EditReference): def ok_clicked(self, obj): - trans = self.db.transaction_begin() if self.source.handle: - self.db.commit_source(self.source,trans) - self.db.transaction_commit(trans,_("Modify Source")) + with self.db.transaction_begin(_("Modify Source")) as trans: + self.db.commit_source(self.source,trans) else: - self.db.add_source(self.source,trans) - self.db.transaction_commit(trans,_("Add Source")) + with self.db.transaction_begin(_("Add Source")) as trans: + self.db.add_source(self.source,trans) if self.update: self.update(self.source_ref,self.source) diff --git a/src/plugins/import/ImportCsv.py b/src/plugins/import/ImportCsv.py index f139e3015..5b2ba401f 100644 --- a/src/plugins/import/ImportCsv.py +++ b/src/plugins/import/ImportCsv.py @@ -438,88 +438,166 @@ class CSVParser(object): progress.set_pass(_('Reading data...'), 1) data = self.readCSV() progress.set_pass(_('Importing data...'), len(data)) - self.trans = self.db.transaction_begin("",batch=True) - self.db.disable_signals() - t = time.time() - self.lineno = 0 - self.index = 0 - self.fam_count = 0 - self.indi_count = 0 - self.pref = {} # person ref, internal to this sheet - self.fref = {} # family ref, internal to this sheet - header = None - line_number = 0 - for row in data: - progress.step() - line_number += 1 - if "".join(row) == "": # no blanks are allowed inside a table - header = None # clear headers, ready for next "table" - continue - ###################################### - if header is None: - header = [cleanup_column_name(r) for r in row] - col = {} - count = 0 - for key in header: - col[key] = count - count += 1 - continue - # three different kinds of data: person, family, and marriage - if (("marriage" in header) or - ("husband" in header) or - ("wife" in header)): - # marriage, husband, wife - marriage_ref = rd(line_number, row, col, "marriage") - husband = rd(line_number, row, col, "husband") - wife = rd(line_number, row, col, "wife") - marriagedate = rd(line_number, row, col, "date") - marriageplace = rd(line_number, row, col, "place") - marriagesource = rd(line_number, row, col, "source") - note = rd(line_number, row, col, "note") - wife = self.lookup("person", wife) - husband = self.lookup("person", husband) - if husband is None and wife is None: - # might have children, so go ahead and add - LOG.warn("no parents on line %d; adding family anyway" % line_number) - family = self.get_or_create_family(marriage_ref, husband, wife) - # adjust gender, if not already provided - if husband: - # this is just a guess, if unknown - if husband.get_gender() == gen.lib.Person.UNKNOWN: - husband.set_gender(gen.lib.Person.MALE) - self.db.commit_person(husband, self.trans) - if wife: - # this is just a guess, if unknown - if wife.get_gender() == gen.lib.Person.UNKNOWN: - wife.set_gender(gen.lib.Person.FEMALE) - self.db.commit_person(wife, self.trans) - if marriage_ref: - self.storeup("family", marriage_ref.lower(), family) - if marriagesource: - # add, if new - new, marriagesource = self.get_or_create_source(marriagesource) - if marriageplace: - # add, if new - new, marriageplace = self.get_or_create_place(marriageplace) - if marriagedate: - marriagedate = _dp.parse(marriagedate) - if marriagedate or marriageplace or marriagesource or note: - # add, if new; replace, if different - new, marriage = self.get_or_create_event(family, gen.lib.EventType.MARRIAGE, - marriagedate, marriageplace, marriagesource) - if new: - mar_ref = gen.lib.EventRef() - mar_ref.set_reference_handle(marriage.get_handle()) - family.add_event_ref(mar_ref) + with self.db.transaction_begin(_("CSV import"), batch=True + ) as self.trans: + self.db.disable_signals() + t = time.time() + self.lineno = 0 + self.index = 0 + self.fam_count = 0 + self.indi_count = 0 + self.pref = {} # person ref, internal to this sheet + self.fref = {} # family ref, internal to this sheet + header = None + line_number = 0 + for row in data: + progress.step() + line_number += 1 + if "".join(row) == "": # no blanks are allowed inside a table + header = None # clear headers, ready for next "table" + continue + ###################################### + if header is None: + header = [cleanup_column_name(r) for r in row] + col = {} + count = 0 + for key in header: + col[key] = count + count += 1 + continue + # three different kinds of data: person, family, and marriage + if (("marriage" in header) or + ("husband" in header) or + ("wife" in header)): + # marriage, husband, wife + marriage_ref = rd(line_number, row, col, "marriage") + husband = rd(line_number, row, col, "husband") + wife = rd(line_number, row, col, "wife") + marriagedate = rd(line_number, row, col, "date") + marriageplace = rd(line_number, row, col, "place") + marriagesource = rd(line_number, row, col, "source") + note = rd(line_number, row, col, "note") + wife = self.lookup("person", wife) + husband = self.lookup("person", husband) + if husband is None and wife is None: + # might have children, so go ahead and add + LOG.warn("no parents on line %d; adding family anyway" % line_number) + family = self.get_or_create_family(marriage_ref, husband, wife) + # adjust gender, if not already provided + if husband: + # this is just a guess, if unknown + if husband.get_gender() == gen.lib.Person.UNKNOWN: + husband.set_gender(gen.lib.Person.MALE) + self.db.commit_person(husband, self.trans) + if wife: + # this is just a guess, if unknown + if wife.get_gender() == gen.lib.Person.UNKNOWN: + wife.set_gender(gen.lib.Person.FEMALE) + self.db.commit_person(wife, self.trans) + if marriage_ref: + self.storeup("family", marriage_ref.lower(), family) + if marriagesource: + # add, if new + new, marriagesource = self.get_or_create_source(marriagesource) + if marriageplace: + # add, if new + new, marriageplace = self.get_or_create_place(marriageplace) + if marriagedate: + marriagedate = _dp.parse(marriagedate) + if marriagedate or marriageplace or marriagesource or note: + # add, if new; replace, if different + new, marriage = self.get_or_create_event(family, gen.lib.EventType.MARRIAGE, + marriagedate, marriageplace, marriagesource) + if new: + mar_ref = gen.lib.EventRef() + mar_ref.set_reference_handle(marriage.get_handle()) + family.add_event_ref(mar_ref) + self.db.commit_family(family, self.trans) + # only add note to event: + # append notes, if previous notes + if note: + previous_notes_list = marriage.get_note_list() + updated_note = False + for note_handle in previous_notes_list: + previous_note = self.db.get_note_from_handle(note_handle) + if previous_note.type == gen.lib.NoteType.EVENT: + previous_text = previous_note.get() + if note not in previous_text: + note = previous_text + "\n" + note + previous_note.set(note) + self.db.commit_note(previous_note, self.trans) + updated_note = True + break + if not updated_note: + # add new note here + new_note = gen.lib.Note() + new_note.handle = create_id() + new_note.type.set(gen.lib.NoteType.EVENT) + new_note.set(note) + self.db.add_note(new_note, self.trans) + marriage.add_note(new_note.handle) + self.db.commit_event(marriage, self.trans) + elif "family" in header: + # family, child + family_ref = rd(line_number, row, col, "family") + if family_ref is None: + LOG.warn("no family reference found for family on line %d" % line_number) + continue # required + child = rd(line_number, row, col, "child") + source = rd(line_number, row, col, "source") + note = rd(line_number, row, col, "note") + gender = rd(line_number, row, col, "gender") + child = self.lookup("person", child) + family = self.lookup("family", family_ref) + if family is None: + LOG.warn("no matching family reference found for family on line %d" % line_number) + continue + if child is None: + LOG.warn("no matching child reference found for family on line %d" % line_number) + continue + # is this child already in this family? If so, don't add + LOG.debug("children: %s", [ref.ref for ref in family.get_child_ref_list()]) + LOG.debug("looking for: %s", child.get_handle()) + if child.get_handle() not in [ref.ref for ref in family.get_child_ref_list()]: + # add child to family + LOG.debug(" adding child [%s] to family [%s]", child.get_gramps_id(), + family.get_gramps_id()) + childref = gen.lib.ChildRef() + childref.set_reference_handle(child.get_handle()) + family.add_child_ref( childref) self.db.commit_family(family, self.trans) - # only add note to event: - # append notes, if previous notes + child.add_parent_family_handle(family.get_handle()) + if gender: + # replace + gender = gender.lower() + if gender == gender_map[gen.lib.Person.MALE].lower(): + gender = gen.lib.Person.MALE + elif gender == gender_map[gen.lib.Person.FEMALE].lower(): + gender = gen.lib.Person.FEMALE + else: + gender = gen.lib.Person.UNKNOWN + child.set_gender(gender) + if source: + # add, if new + new, source = self.get_or_create_source(source) + source_refs = child.get_source_references() + found = 0 + for ref in source_refs: + LOG.debug("child: %s looking for ref: %s", ref.ref, source.get_handle()) + if ref.ref == source.get_handle(): + found = 1 + if not found: + sref = gen.lib.SourceRef() + sref.set_reference_handle(source.get_handle()) + child.add_source_reference(sref) + # put note on child if note: - previous_notes_list = marriage.get_note_list() + # append notes, if previous notes + previous_notes_list = child.get_note_list() updated_note = False for note_handle in previous_notes_list: previous_note = self.db.get_note_from_handle(note_handle) - if previous_note.type == gen.lib.NoteType.EVENT: + if previous_note.type == gen.lib.NoteType.PERSON: previous_text = previous_note.get() if note not in previous_text: note = previous_text + "\n" + note @@ -531,276 +609,199 @@ class CSVParser(object): # add new note here new_note = gen.lib.Note() new_note.handle = create_id() - new_note.type.set(gen.lib.NoteType.EVENT) + new_note.type.set(gen.lib.NoteType.PERSON) new_note.set(note) self.db.add_note(new_note, self.trans) - marriage.add_note(new_note.handle) - self.db.commit_event(marriage, self.trans) - elif "family" in header: - # family, child - family_ref = rd(line_number, row, col, "family") - if family_ref is None: - LOG.warn("no family reference found for family on line %d" % line_number) - continue # required - child = rd(line_number, row, col, "child") - source = rd(line_number, row, col, "source") - note = rd(line_number, row, col, "note") - gender = rd(line_number, row, col, "gender") - child = self.lookup("person", child) - family = self.lookup("family", family_ref) - if family is None: - LOG.warn("no matching family reference found for family on line %d" % line_number) - continue - if child is None: - LOG.warn("no matching child reference found for family on line %d" % line_number) - continue - # is this child already in this family? If so, don't add - LOG.debug("children: %s", [ref.ref for ref in family.get_child_ref_list()]) - LOG.debug("looking for: %s", child.get_handle()) - if child.get_handle() not in [ref.ref for ref in family.get_child_ref_list()]: - # add child to family - LOG.debug(" adding child [%s] to family [%s]", child.get_gramps_id(), - family.get_gramps_id()) - childref = gen.lib.ChildRef() - childref.set_reference_handle(child.get_handle()) - family.add_child_ref( childref) - self.db.commit_family(family, self.trans) - child.add_parent_family_handle(family.get_handle()) - if gender: + child.add_note(new_note.handle) + self.db.commit_person(child, self.trans) + elif "surname" in header: # person data + # surname, and any of the following + surname = rd(line_number, row, col, "surname") + firstname = rd(line_number, row, col, "firstname", "") + callname = rd(line_number, row, col, "callname") + title = rd(line_number, row, col, "title") + prefix = rd(line_number, row, col, "prefix") + suffix = rd(line_number, row, col, "suffix") + gender = rd(line_number, row, col, "gender") + source = rd(line_number, row, col, "source") + note = rd(line_number, row, col, "note") + birthplace = rd(line_number, row, col, "birthplace") + birthdate = rd(line_number, row, col, "birthdate") + birthsource = rd(line_number, row, col, "birthsource") + baptismplace = rd(line_number, row, col, "baptismplace") + baptismdate = rd(line_number, row, col, "baptismdate") + baptismsource = rd(line_number, row, col, "baptismsource") + burialplace = rd(line_number, row, col, "burialplace") + burialdate = rd(line_number, row, col, "burialdate") + burialsource = rd(line_number, row, col, "burialsource") + deathplace = rd(line_number, row, col, "deathplace") + deathdate = rd(line_number, row, col, "deathdate") + deathsource = rd(line_number, row, col, "deathsource") + deathcause = rd(line_number, row, col, "deathcause") + grampsid = rd(line_number, row, col, "grampsid") + person_ref = rd(line_number, row, col, "person") + ######################################################### + # if this person already exists, don't create them + person = self.lookup("person", person_ref) + if person is None: + if surname is None: + LOG.warn("empty surname for new person on line %d" % line_number) + surname = "" + # new person + person = self.create_person() + name = gen.lib.Name() + name.set_type(gen.lib.NameType(gen.lib.NameType.BIRTH)) + name.set_first_name(firstname) + surname_obj = gen.lib.Surname() + surname_obj.set_surname(surname) + name.add_surname(surname_obj) + person.set_primary_name(name) + else: + name = person.get_primary_name() + ######################################################### + if person_ref is not None: + self.storeup("person", person_ref, person) # replace - gender = gender.lower() - if gender == gender_map[gen.lib.Person.MALE].lower(): - gender = gen.lib.Person.MALE - elif gender == gender_map[gen.lib.Person.FEMALE].lower(): - gender = gen.lib.Person.FEMALE - else: - gender = gen.lib.Person.UNKNOWN - child.set_gender(gender) - if source: - # add, if new - new, source = self.get_or_create_source(source) - source_refs = child.get_source_references() - found = 0 - for ref in source_refs: - LOG.debug("child: %s looking for ref: %s", ref.ref, source.get_handle()) - if ref.ref == source.get_handle(): - found = 1 - if not found: - sref = gen.lib.SourceRef() - sref.set_reference_handle(source.get_handle()) - child.add_source_reference(sref) - # put note on child - if note: - # append notes, if previous notes - previous_notes_list = child.get_note_list() - updated_note = False - for note_handle in previous_notes_list: - previous_note = self.db.get_note_from_handle(note_handle) - if previous_note.type == gen.lib.NoteType.PERSON: - previous_text = previous_note.get() - if note not in previous_text: - note = previous_text + "\n" + note - previous_note.set(note) - self.db.commit_note(previous_note, self.trans) - updated_note = True - break - if not updated_note: - # add new note here - new_note = gen.lib.Note() - new_note.handle = create_id() - new_note.type.set(gen.lib.NoteType.PERSON) - new_note.set(note) - self.db.add_note(new_note, self.trans) - child.add_note(new_note.handle) - self.db.commit_person(child, self.trans) - elif "surname" in header: # person data - # surname, and any of the following - surname = rd(line_number, row, col, "surname") - firstname = rd(line_number, row, col, "firstname", "") - callname = rd(line_number, row, col, "callname") - title = rd(line_number, row, col, "title") - prefix = rd(line_number, row, col, "prefix") - suffix = rd(line_number, row, col, "suffix") - gender = rd(line_number, row, col, "gender") - source = rd(line_number, row, col, "source") - note = rd(line_number, row, col, "note") - birthplace = rd(line_number, row, col, "birthplace") - birthdate = rd(line_number, row, col, "birthdate") - birthsource = rd(line_number, row, col, "birthsource") - baptismplace = rd(line_number, row, col, "baptismplace") - baptismdate = rd(line_number, row, col, "baptismdate") - baptismsource = rd(line_number, row, col, "baptismsource") - burialplace = rd(line_number, row, col, "burialplace") - burialdate = rd(line_number, row, col, "burialdate") - burialsource = rd(line_number, row, col, "burialsource") - deathplace = rd(line_number, row, col, "deathplace") - deathdate = rd(line_number, row, col, "deathdate") - deathsource = rd(line_number, row, col, "deathsource") - deathcause = rd(line_number, row, col, "deathcause") - grampsid = rd(line_number, row, col, "grampsid") - person_ref = rd(line_number, row, col, "person") - ######################################################### - # if this person already exists, don't create them - person = self.lookup("person", person_ref) - if person is None: - if surname is None: - LOG.warn("empty surname for new person on line %d" % line_number) - surname = "" - # new person - person = self.create_person() - name = gen.lib.Name() - name.set_type(gen.lib.NameType(gen.lib.NameType.BIRTH)) - name.set_first_name(firstname) - surname_obj = gen.lib.Surname() - surname_obj.set_surname(surname) - name.add_surname(surname_obj) - person.set_primary_name(name) + if surname is not None: + name.get_primary_surname().set_surname(surname) + if firstname is not None: + name.set_first_name(firstname) + if callname is not None: + name.set_call_name(callname) + if title is not None: + name.set_title(title) + if prefix is not None: + name.get_primary_surname().set_prefix(prefix) + name.group_as = '' # HELP? what should I do here? + if suffix is not None: + name.set_suffix(suffix) + if note is not None: + # append notes, if previous notes + previous_notes_list = person.get_note_list() + updated_note = False + for note_handle in previous_notes_list: + previous_note = self.db.get_note_from_handle(note_handle) + if previous_note.type == gen.lib.NoteType.PERSON: + previous_text = previous_note.get() + if note not in previous_text: + note = previous_text + "\n" + note + previous_note.set(note) + self.db.commit_note(previous_note, self.trans) + updated_note = True + break + if not updated_note: + # add new note here + new_note = gen.lib.Note() + new_note.handle = create_id() + new_note.type.set(gen.lib.NoteType.PERSON) + new_note.set(note) + self.db.add_note(new_note, self.trans) + person.add_note(new_note.handle) + if grampsid is not None: + person.gramps_id = grampsid + elif person_ref is not None: + if person_ref.startswith("[") and person_ref.endswith("]"): + person.gramps_id = person_ref[1:-1] + if person.get_gender() == gen.lib.Person.UNKNOWN and gender is not None: + gender = gender.lower() + if gender == gender_map[gen.lib.Person.MALE].lower(): + gender = gen.lib.Person.MALE + elif gender == gender_map[gen.lib.Person.FEMALE].lower(): + gender = gen.lib.Person.FEMALE + else: + gender = gen.lib.Person.UNKNOWN + person.set_gender(gender) + ######################################################### + # add if new, replace if different + # Birth: + if birthdate is not None: + birthdate = _dp.parse(birthdate) + if birthplace is not None: + new, birthplace = self.get_or_create_place(birthplace) + if birthsource is not None: + new, birthsource = self.get_or_create_source(birthsource) + if birthdate or birthplace or birthsource: + new, birth = self.get_or_create_event(person, + gen.lib.EventType.BIRTH, birthdate, + birthplace, birthsource) + birth_ref = person.get_birth_ref() + if birth_ref is None: + # new + birth_ref = gen.lib.EventRef() + birth_ref.set_reference_handle( birth.get_handle()) + person.set_birth_ref( birth_ref) + # Baptism: + if baptismdate is not None: + baptismdate = _dp.parse(baptismdate) + if baptismplace is not None: + new, baptismplace = self.get_or_create_place(baptismplace) + if baptismsource is not None: + new, baptismsource = self.get_or_create_source(baptismsource) + if baptismdate or baptismplace or baptismsource: + new, baptism = self.get_or_create_event(person, + gen.lib.EventType.BAPTISM, baptismdate, + baptismplace, baptismsource) + baptism_ref = get_primary_event_ref_from_type(self.db, person, "Baptism") + if baptism_ref is None: + # new + baptism_ref = gen.lib.EventRef() + baptism_ref.set_reference_handle( baptism.get_handle()) + person.add_event_ref( baptism_ref) + # Death: + if deathdate is not None: + deathdate = _dp.parse(deathdate) + if deathplace is not None: + new, deathplace = self.get_or_create_place(deathplace) + if deathsource is not None: + new, deathsource = self.get_or_create_source(deathsource) + if deathdate or deathplace or deathsource or deathcause: + new, death = self.get_or_create_event(person, gen.lib.EventType.DEATH, + deathdate, deathplace, deathsource) + if deathcause: + death.set_description(deathcause) + self.db.commit_event(death, self.trans) + death_ref = person.get_death_ref() + if death_ref is None: + # new + death_ref = gen.lib.EventRef() + death_ref.set_reference_handle(death.get_handle()) + person.set_death_ref(death_ref) + # Burial: + if burialdate is not None: + burialdate = _dp.parse(burialdate) + if burialplace is not None: + new, burialplace = self.get_or_create_place(burialplace) + if burialsource is not None: + new, burialsource = self.get_or_create_source(burialsource) + if burialdate or burialplace or burialsource: + new, burial = self.get_or_create_event(person, + gen.lib.EventType.BURIAL, burialdate, + burialplace, burialsource) + burial_ref = get_primary_event_ref_from_type(self.db, person, "Burial") + if burial_ref is None: + # new + burial_ref = gen.lib.EventRef() + burial_ref.set_reference_handle( burial.get_handle()) + person.add_event_ref( burial_ref) + if source: + # add, if new + new, source = self.get_or_create_source(source) + source_refs = person.get_source_references() + found = 0 + for ref in source_refs: + LOG.debug("person: %s looking for ref: %s", ref.ref, source.get_handle()) + if ref.ref == source.get_handle(): + found = 1 + if not found: + sref = gen.lib.SourceRef() + sref.set_reference_handle(source.get_handle()) + person.add_source_reference(sref) + self.db.commit_person(person, self.trans) else: - name = person.get_primary_name() - ######################################################### - if person_ref is not None: - self.storeup("person", person_ref, person) - # replace - if surname is not None: - name.get_primary_surname().set_surname(surname) - if firstname is not None: - name.set_first_name(firstname) - if callname is not None: - name.set_call_name(callname) - if title is not None: - name.set_title(title) - if prefix is not None: - name.get_primary_surname().set_prefix(prefix) - name.group_as = '' # HELP? what should I do here? - if suffix is not None: - name.set_suffix(suffix) - if note is not None: - # append notes, if previous notes - previous_notes_list = person.get_note_list() - updated_note = False - for note_handle in previous_notes_list: - previous_note = self.db.get_note_from_handle(note_handle) - if previous_note.type == gen.lib.NoteType.PERSON: - previous_text = previous_note.get() - if note not in previous_text: - note = previous_text + "\n" + note - previous_note.set(note) - self.db.commit_note(previous_note, self.trans) - updated_note = True - break - if not updated_note: - # add new note here - new_note = gen.lib.Note() - new_note.handle = create_id() - new_note.type.set(gen.lib.NoteType.PERSON) - new_note.set(note) - self.db.add_note(new_note, self.trans) - person.add_note(new_note.handle) - if grampsid is not None: - person.gramps_id = grampsid - elif person_ref is not None: - if person_ref.startswith("[") and person_ref.endswith("]"): - person.gramps_id = person_ref[1:-1] - if person.get_gender() == gen.lib.Person.UNKNOWN and gender is not None: - gender = gender.lower() - if gender == gender_map[gen.lib.Person.MALE].lower(): - gender = gen.lib.Person.MALE - elif gender == gender_map[gen.lib.Person.FEMALE].lower(): - gender = gen.lib.Person.FEMALE - else: - gender = gen.lib.Person.UNKNOWN - person.set_gender(gender) - ######################################################### - # add if new, replace if different - # Birth: - if birthdate is not None: - birthdate = _dp.parse(birthdate) - if birthplace is not None: - new, birthplace = self.get_or_create_place(birthplace) - if birthsource is not None: - new, birthsource = self.get_or_create_source(birthsource) - if birthdate or birthplace or birthsource: - new, birth = self.get_or_create_event(person, - gen.lib.EventType.BIRTH, birthdate, - birthplace, birthsource) - birth_ref = person.get_birth_ref() - if birth_ref is None: - # new - birth_ref = gen.lib.EventRef() - birth_ref.set_reference_handle( birth.get_handle()) - person.set_birth_ref( birth_ref) - # Baptism: - if baptismdate is not None: - baptismdate = _dp.parse(baptismdate) - if baptismplace is not None: - new, baptismplace = self.get_or_create_place(baptismplace) - if baptismsource is not None: - new, baptismsource = self.get_or_create_source(baptismsource) - if baptismdate or baptismplace or baptismsource: - new, baptism = self.get_or_create_event(person, - gen.lib.EventType.BAPTISM, baptismdate, - baptismplace, baptismsource) - baptism_ref = get_primary_event_ref_from_type(self.db, person, "Baptism") - if baptism_ref is None: - # new - baptism_ref = gen.lib.EventRef() - baptism_ref.set_reference_handle( baptism.get_handle()) - person.add_event_ref( baptism_ref) - # Death: - if deathdate is not None: - deathdate = _dp.parse(deathdate) - if deathplace is not None: - new, deathplace = self.get_or_create_place(deathplace) - if deathsource is not None: - new, deathsource = self.get_or_create_source(deathsource) - if deathdate or deathplace or deathsource or deathcause: - new, death = self.get_or_create_event(person, gen.lib.EventType.DEATH, - deathdate, deathplace, deathsource) - if deathcause: - death.set_description(deathcause) - self.db.commit_event(death, self.trans) - death_ref = person.get_death_ref() - if death_ref is None: - # new - death_ref = gen.lib.EventRef() - death_ref.set_reference_handle(death.get_handle()) - person.set_death_ref(death_ref) - # Burial: - if burialdate is not None: - burialdate = _dp.parse(burialdate) - if burialplace is not None: - new, burialplace = self.get_or_create_place(burialplace) - if burialsource is not None: - new, burialsource = self.get_or_create_source(burialsource) - if burialdate or burialplace or burialsource: - new, burial = self.get_or_create_event(person, - gen.lib.EventType.BURIAL, burialdate, - burialplace, burialsource) - burial_ref = get_primary_event_ref_from_type(self.db, person, "Burial") - if burial_ref is None: - # new - burial_ref = gen.lib.EventRef() - burial_ref.set_reference_handle( burial.get_handle()) - person.add_event_ref( burial_ref) - if source: - # add, if new - new, source = self.get_or_create_source(source) - source_refs = person.get_source_references() - found = 0 - for ref in source_refs: - LOG.debug("person: %s looking for ref: %s", ref.ref, source.get_handle()) - if ref.ref == source.get_handle(): - found = 1 - if not found: - sref = gen.lib.SourceRef() - sref.set_reference_handle(source.get_handle()) - person.add_source_reference(sref) - self.db.commit_person(person, self.trans) - else: - LOG.warn("ignoring line %d" % line_number) - t = time.time() - t - msg = ngettext('Import Complete: %d second','Import Complete: %d seconds', t ) % t - self.db.transaction_commit(self.trans,_("CSV import")) + LOG.warn("ignoring line %d" % line_number) + t = time.time() - t + msg = ngettext('Import Complete: %d second','Import Complete: %d seconds', t ) % t + self.db.enable_signals() self.db.request_rebuild() LOG.debug(msg) diff --git a/src/plugins/import/ImportGeneWeb.py b/src/plugins/import/ImportGeneWeb.py index f387d9f73..40c0c3da8 100644 --- a/src/plugins/import/ImportGeneWeb.py +++ b/src/plugins/import/ImportGeneWeb.py @@ -112,73 +112,73 @@ class GeneWebParser(object): return line def parse_geneweb_file(self): - self.trans = self.db.transaction_begin("",batch=True) - self.db.disable_signals() - t = time.time() - self.lineno = 0 - self.index = 0 - self.fam_count = 0 - self.indi_count = 0 + with self.db.transaction_begin(_("GeneWeb import"), batch=True + ) as self.trans: + self.db.disable_signals() + t = time.time() + self.lineno = 0 + self.index = 0 + self.fam_count = 0 + self.indi_count = 0 - self.fkeys = [] - self.ikeys = {} - self.pkeys = {} - self.skeys = {} + self.fkeys = [] + self.ikeys = {} + self.pkeys = {} + self.skeys = {} - self.current_mode = None - self.current_family = None - self.current_husband_handle = None - self.current_child_birthplace_handle = None - self.current_child_source_handle = None - try: - while 1: - line = self.get_next_line() - if line is None: - break - if line == "": - continue + self.current_mode = None + self.current_family = None + self.current_husband_handle = None + self.current_child_birthplace_handle = None + self.current_child_source_handle = None + try: + while 1: + line = self.get_next_line() + if line is None: + break + if line == "": + continue - fields = line.split(" ") + fields = line.split(" ") - LOG.debug("LINE: %s" %line) - if fields[0] == "fam": - self.current_mode = "fam" - self.read_family_line(line,fields) - elif fields[0] == "rel": - self.current_mode = "rel" - self.read_relationship_person(line,fields) - elif fields[0] == "src": - self.read_source_line(line,fields) - elif fields[0] in ("wit", "wit:"): - self.read_witness_line(line,fields) - elif fields[0] == "cbp": - self.read_children_birthplace_line(line,fields) - elif fields[0] == "csrc": - 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) - elif fields[0] == "notes": - self.read_person_notes_lines(line,fields) - elif fields[0] == "notes-db": - self.read_database_notes_lines(line,fields) - elif fields[0] == "end": - self.current_mode = None - elif fields[0] == "encoding:": - self.encoding = fields[1] - else: - LOG.warn("parse_geneweb_file(): Token >%s< unknown. line %d skipped: %s" % - (fields[0],self.lineno,line)) - except Errors.GedcomError, err: - self.errmsg(str(err)) - - t = time.time() - t - msg = ngettext('Import Complete: %d second','Import Complete: %d seconds', t ) % t - - self.db.transaction_commit(self.trans,_("GeneWeb import")) + LOG.debug("LINE: %s" %line) + if fields[0] == "fam": + self.current_mode = "fam" + self.read_family_line(line,fields) + elif fields[0] == "rel": + self.current_mode = "rel" + self.read_relationship_person(line,fields) + elif fields[0] == "src": + self.read_source_line(line,fields) + elif fields[0] in ("wit", "wit:"): + self.read_witness_line(line,fields) + elif fields[0] == "cbp": + self.read_children_birthplace_line(line,fields) + elif fields[0] == "csrc": + 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) + elif fields[0] == "notes": + self.read_person_notes_lines(line,fields) + elif fields[0] == "notes-db": + self.read_database_notes_lines(line,fields) + elif fields[0] == "end": + self.current_mode = None + elif fields[0] == "encoding:": + self.encoding = fields[1] + else: + LOG.warn("parse_geneweb_file(): Token >%s< unknown. line %d skipped: %s" % + (fields[0],self.lineno,line)) + except Errors.GedcomError, err: + self.errmsg(str(err)) + + t = time.time() - t + msg = ngettext('Import Complete: %d second','Import Complete: %d seconds', t ) % t + self.db.enable_signals() self.db.request_rebuild() diff --git a/src/plugins/import/ImportProGen.py b/src/plugins/import/ImportProGen.py index 0c5122abc..b7e9cf55e 100644 --- a/src/plugins/import/ImportProGen.py +++ b/src/plugins/import/ImportProGen.py @@ -495,14 +495,14 @@ class ProgenParser(object): self.pers = _read_recs(self.def_['Table_1'], self.bname) self.rels = _read_recs(self.def_['Table_2'], self.bname) - self.trans = self.db.transaction_begin('', batch=True) - self.db.disable_signals() + with self.db.transaction_begin(_("Pro-Gen import"), batch=True + ) as self.trans: + self.db.disable_signals() - self.create_persons() - self.create_families() - self.add_children() + self.create_persons() + self.create_families() + self.add_children() - self.db.transaction_commit(self.trans, _("Pro-Gen import")) self.db.enable_signals() self.db.request_rebuild() self.progress.close() diff --git a/src/plugins/import/ImportVCard.py b/src/plugins/import/ImportVCard.py index d33b527ba..4ca019552 100644 --- a/src/plugins/import/ImportVCard.py +++ b/src/plugins/import/ImportVCard.py @@ -90,60 +90,60 @@ class VCardParser(object): return line def parse_vCard_file(self): - self.trans = self.db.transaction_begin("",batch=True) - self.db.disable_signals() - t = time.time() - self.person = None + with self.db.transaction_begin(_("vCard import"), batch=True + ) as self.trans: + self.db.disable_signals() + t = time.time() + self.person = None - line_reg = re.compile('^([^:]+)+:(.*)$') - try: - while 1: - line = self.get_next_line() - if line is None: - break - if line == "": - continue - - if line.find(":") == -1: - continue - line_parts = line_reg.match( line) - if not line_parts: - continue - - fields = line_parts.group(1).split(";") - - #for field in line_parts.groups(): - # print " p "+field - #for field in fields: - # print " f "+field + line_reg = re.compile('^([^:]+)+:(.*)$') + try: + while 1: + line = self.get_next_line() + if line is None: + break + if line == "": + continue - if fields[0] == "BEGIN": - self.next_person() - elif fields[0] == "END": - self.finish_person() - elif fields[0] == "FN": - self.set_nick_name(fields, line_parts.group(2)) - elif fields[0] == "N": - self.add_name(fields, line_parts.group(2)) - elif fields[0] == "ADR": - self.add_address(fields, line_parts.group(2)) - elif fields[0] == "TEL": - self.add_phone(fields, line_parts.group(2)) - elif fields[0] == "BDAY": - self.add_birthday(fields, line_parts.group(2)) - elif fields[0] == "TITLE": - self.add_title(fields, line_parts.group(2)) - elif fields[0] == "URL": - self.add_url(fields, line_parts.group(2)) - else: - LOG.warn("Token >%s< unknown. line skipped: %s" % (fields[0],line)) - except Errors.GedcomError, err: - self.errmsg(str(err)) - - t = time.time() - t - msg = ngettext('Import Complete: %d second','Import Complete: %d seconds', t ) % t - - self.db.transaction_commit(self.trans,_("vCard import")) + if line.find(":") == -1: + continue + line_parts = line_reg.match( line) + if not line_parts: + continue + + fields = line_parts.group(1).split(";") + + #for field in line_parts.groups(): + # print " p "+field + #for field in fields: + # print " f "+field + + if fields[0] == "BEGIN": + self.next_person() + elif fields[0] == "END": + self.finish_person() + elif fields[0] == "FN": + self.set_nick_name(fields, line_parts.group(2)) + elif fields[0] == "N": + self.add_name(fields, line_parts.group(2)) + elif fields[0] == "ADR": + self.add_address(fields, line_parts.group(2)) + elif fields[0] == "TEL": + self.add_phone(fields, line_parts.group(2)) + elif fields[0] == "BDAY": + self.add_birthday(fields, line_parts.group(2)) + elif fields[0] == "TITLE": + self.add_title(fields, line_parts.group(2)) + elif fields[0] == "URL": + self.add_url(fields, line_parts.group(2)) + else: + LOG.warn("Token >%s< unknown. line skipped: %s" % (fields[0],line)) + except Errors.GedcomError, err: + self.errmsg(str(err)) + + t = time.time() - t + msg = ngettext('Import Complete: %d second','Import Complete: %d seconds', t ) % t + self.db.enable_signals() self.db.request_rebuild() diff --git a/src/plugins/import/ImportXml.py b/src/plugins/import/ImportXml.py index 976bf75d6..e12f6b5bb 100644 --- a/src/plugins/import/ImportXml.py +++ b/src/plugins/import/ImportXml.py @@ -771,49 +771,49 @@ class GrampsParser(UpdateCallback): no_magic = True else: no_magic = False - self.trans = self.db.transaction_begin("", batch=True, no_magic=no_magic) - self.set_total(linecount) + with self.db.transaction_begin(_("Gramps XML import"), batch=True, + no_magic=no_magic) as self.trans: + self.set_total(linecount) - self.db.disable_signals() + self.db.disable_signals() - self.p = ParserCreate() - self.p.StartElementHandler = self.startElement - self.p.EndElementHandler = self.endElement - self.p.CharacterDataHandler = self.characters - self.p.ParseFile(ifile) + self.p = ParserCreate() + self.p.StartElementHandler = self.startElement + self.p.EndElementHandler = self.endElement + self.p.CharacterDataHandler = self.characters + self.p.ParseFile(ifile) - if len(self.name_formats) > 0: - # add new name formats to the existing table - self.db.name_formats += self.name_formats - # Register new formats - name_displayer.set_name_format(self.db.name_formats) - - self.db.set_researcher(self.owner) - if self.home is not None: - person = self.db.get_person_from_handle(self.home) - self.db.set_default_person_handle(person.handle) - - #set media path, this should really do some parsing to convert eg - # windows path to unix ? - if self.mediapath: - oldpath = self.db.get_mediapath() - if not oldpath: - self.db.set_mediapath(self.mediapath) - elif not oldpath == self.mediapath: - ErrorDialog(_("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 ) - - for key in self.func_map.keys(): - del self.func_map[key] - del self.func_map - del self.func_list - del self.p - self.db.transaction_commit(self.trans, _("Gramps XML import")) + if len(self.name_formats) > 0: + # add new name formats to the existing table + self.db.name_formats += self.name_formats + # Register new formats + name_displayer.set_name_format(self.db.name_formats) + + self.db.set_researcher(self.owner) + if self.home is not None: + person = self.db.get_person_from_handle(self.home) + self.db.set_default_person_handle(person.handle) + + #set media path, this should really do some parsing to convert eg + # windows path to unix ? + if self.mediapath: + oldpath = self.db.get_mediapath() + if not oldpath: + self.db.set_mediapath(self.mediapath) + elif not oldpath == self.mediapath: + ErrorDialog(_("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 ) + + for key in self.func_map.keys(): + del self.func_map[key] + del self.func_map + del self.func_list + del self.p self.db.enable_signals() self.db.request_rebuild() return self.info diff --git a/src/plugins/lib/libgedcom.py b/src/plugins/lib/libgedcom.py index 95490e3fa..edac1e5e4 100644 --- a/src/plugins/lib/libgedcom.py +++ b/src/plugins/lib/libgedcom.py @@ -2281,24 +2281,24 @@ class GedcomParser(UpdateCallback): Parses the opened GEDCOM file. """ no_magic = self.maxpeople < 1000 - self.trans = self.dbase.transaction_begin("", not use_trans, no_magic) + with self.dbase.transaction_begin(_("GEDCOM import"), not use_trans, + no_magic) as self.trans: - self.dbase.disable_signals() - self.__parse_header_head() - self.want_parse_warnings = False - self.__parse_header_source() - self.want_parse_warnings = True - if self.use_def_src: - self.dbase.add_source(self.def_src, self.trans) - self.__parse_record() - self.__parse_trailer() - for title, handle in self.inline_srcs.iteritems(): - src = gen.lib.Source() - src.set_handle(handle) - src.set_title(title) - self.dbase.add_source(src, self.trans) + self.dbase.disable_signals() + self.__parse_header_head() + self.want_parse_warnings = False + self.__parse_header_source() + self.want_parse_warnings = True + if self.use_def_src: + self.dbase.add_source(self.def_src, self.trans) + self.__parse_record() + self.__parse_trailer() + for title, handle in self.inline_srcs.iteritems(): + src = gen.lib.Source() + src.set_handle(handle) + src.set_title(title) + self.dbase.add_source(src, self.trans) - self.dbase.transaction_commit(self.trans, _("GEDCOM import")) self.dbase.enable_signals() self.dbase.request_rebuild() diff --git a/src/plugins/lib/libmixin.py b/src/plugins/lib/libmixin.py index 135fe626a..bbd8556ea 100644 --- a/src/plugins/lib/libmixin.py +++ b/src/plugins/lib/libmixin.py @@ -50,8 +50,9 @@ class DbMixin(object): where "database" is the object name of your instance of the gramps database. """ - def __find_primary_from_handle(self, handle, transaction, class_type, dmap, - add_func): + + def __find_primary_from_handle(self, handle, transaction, class_type, + get_raw_obj_data, add_func): """ Find a primary object of class_type in the database from the passed handle. @@ -65,8 +66,9 @@ class DbMixin(object): obj = class_type() handle = str(handle) new = True - if handle in dmap: - obj.unserialize(dmap.get(handle)) + raw = get_raw_obj_data(handle) + if raw is not None: + obj.unserialize(raw) #references create object with id None before object is really made if obj.gramps_id is not None: new = False @@ -75,8 +77,8 @@ class DbMixin(object): add_func(obj, transaction) return obj, new - def __find_table_from_handle(self, handle, transaction, class_type, dmap, - add_func): + def __find_table_from_handle(self, handle, transaction, class_type, + get_raw_obj_data, add_func): """ Find a table object of class_type in the database from the passed handle. @@ -89,16 +91,17 @@ class DbMixin(object): """ obj = class_type() handle = str(handle) - if handle in dmap: - obj.unserialize(dmap.get(handle)) + raw = get_raw_obj_data(handle) + if raw is not None: + obj.unserialize(raw) return obj, False else: obj.set_handle(handle) add_func(obj, transaction) return obj, True - def __check_primary_from_handle(self, handle, transaction, class_type, dmap, - add_func, set_gid=True): + def __check_primary_from_handle(self, handle, transaction, class_type, + has_handle_func, add_func, set_gid): """ Check whether a primary object of class_type with the passed handle exists in the database. @@ -107,13 +110,13 @@ class DbMixin(object): If set_gid then a new gramps_id is created, if not, None is used. """ handle = str(handle) - if handle not in dmap: + if not has_handle_func(handle): obj = class_type() obj.set_handle(handle) add_func(obj, transaction, set_gid=set_gid) - def __check_table_from_handle(self, handle, transaction, class_type, dmap, - add_func): + def __check_table_from_handle(self, handle, transaction, class_type, + has_handle_func, add_func): """ Check whether a table object of class_type with the passed handle exists in the database. @@ -121,7 +124,7 @@ class DbMixin(object): If no such object exists, a new object is added to the database. """ handle = str(handle) - if handle not in dmap: + if not has_handle_func(handle): obj = class_type() obj.set_handle(handle) add_func(obj, transaction) @@ -137,7 +140,7 @@ class DbMixin(object): @rtype: tuple """ return self.__find_primary_from_handle(handle, transaction, Person, - self.person_map, self.add_person) + self.get_raw_person_data, self.add_person) def find_source_from_handle(self, handle, transaction): """ @@ -150,7 +153,7 @@ class DbMixin(object): @rtype: tuple """ return self.__find_primary_from_handle(handle, transaction, Source, - self.source_map, self.add_source) + self.get_raw_source_data, self.add_source) def find_event_from_handle(self, handle, transaction): """ @@ -163,7 +166,7 @@ class DbMixin(object): @rtype: tuple """ return self.__find_primary_from_handle(handle, transaction, Event, - self.event_map, self.add_event) + self.get_raw_event_data, self.add_event) def find_object_from_handle(self, handle, transaction): """ @@ -175,8 +178,8 @@ class DbMixin(object): if the object is new @rtype: tuple """ - return self.__find_primary_from_handle(handle, transaction, MediaObject, - self.media_map, self.add_object) + return self.__find_primary_from_handle(handle, transaction, MediaObject, + self.get_raw_object_data, self.add_object) def find_place_from_handle(self, handle, transaction): """ @@ -189,7 +192,7 @@ class DbMixin(object): @rtype: tuple """ return self.__find_primary_from_handle(handle, transaction, Place, - self.place_map, self.add_place) + self.get_raw_place_data, self.add_place) def find_family_from_handle(self, handle, transaction): """ @@ -202,7 +205,7 @@ class DbMixin(object): @rtype: tuple """ return self.__find_primary_from_handle(handle, transaction, Family, - self.family_map, self.add_family) + self.get_raw_family_data, self.add_family) def find_repository_from_handle(self, handle, transaction): """ @@ -215,7 +218,7 @@ class DbMixin(object): @rtype: tuple """ return self.__find_primary_from_handle(handle, transaction, Repository, - self.repository_map, self.add_repository) + self.get_raw_repository_data, self.add_repository) def find_note_from_handle(self, handle, transaction): """ @@ -228,7 +231,7 @@ class DbMixin(object): @rtype: tuple """ return self.__find_primary_from_handle(handle, transaction, Note, - self.note_map, self.add_note) + self.get_raw_note_data, self.add_note) def find_tag_from_handle(self, handle, transaction): """ @@ -241,7 +244,7 @@ class DbMixin(object): @rtype: tuple """ return self.__find_table_from_handle(handle, transaction, Tag, - self.tag_map, self.add_tag) + self.get_raw_tag_data, self.add_tag) def check_person_from_handle(self, handle, transaction, set_gid=True): """ @@ -251,7 +254,7 @@ class DbMixin(object): If set_gid then a new gramps_id is created, if not, None is used. """ self.__check_primary_from_handle(handle, transaction, Person, - self.person_map, self.add_person, + self.has_person_handle, self.add_person, set_gid = set_gid) def check_source_from_handle(self, handle, transaction, set_gid=True): @@ -262,7 +265,7 @@ class DbMixin(object): If set_gid then a new gramps_id is created, if not, None is used. """ self.__check_primary_from_handle(handle, transaction, Source, - self.source_map, self.add_source, + self.has_source_handle, self.add_source, set_gid=set_gid) def check_event_from_handle(self, handle, transaction, set_gid=True): @@ -273,7 +276,7 @@ class DbMixin(object): If set_gid then a new gramps_id is created, if not, None is used. """ self.__check_primary_from_handle(handle, transaction, Event, - self.event_map, self.add_event, + self.has_event_handle, self.add_event, set_gid=set_gid) def check_object_from_handle(self, handle, transaction, set_gid=True): @@ -286,7 +289,7 @@ class DbMixin(object): """ self.__check_primary_from_handle(handle, transaction, MediaObject, - self.media_map, self.add_object, + self.has_object_handle, self.add_object, set_gid=set_gid) def check_place_from_handle(self, handle, transaction, set_gid=True): @@ -297,7 +300,7 @@ class DbMixin(object): If set_gid then a new gramps_id is created, if not, None is used. """ self.__check_primary_from_handle(handle, transaction, Place, - self.place_map, self.add_place, + self.has_place_handle, self.add_place, set_gid=set_gid) def check_family_from_handle(self, handle, transaction, set_gid=True): @@ -308,7 +311,7 @@ class DbMixin(object): If set_gid then a new gramps_id is created, if not, None is used. """ self.__check_primary_from_handle(handle, transaction, Family, - self.family_map, self.add_family, + self.has_family_handle, self.add_family, set_gid=set_gid) def check_repository_from_handle(self, handle, transaction, set_gid=True): @@ -320,8 +323,8 @@ class DbMixin(object): If set_gid then a new gramps_id is created, if not, None is used. """ self.__check_primary_from_handle(handle, transaction, Repository, - self.repository_map, self.add_repository, - set_gid=set_gid) + self.has_repository_handle, self.add_repository, + set_gid=set_gid) def check_note_from_handle(self, handle, transaction, set_gid=True): """ @@ -331,7 +334,7 @@ class DbMixin(object): If set_gid then a new gramps_id is created, if not, None is used. """ self.__check_primary_from_handle(handle, transaction, Note, - self.note_map, self.add_note, + self.has_note_handle, self.add_note, set_gid=set_gid) def check_tag_from_handle(self, handle, transaction): @@ -341,4 +344,4 @@ class DbMixin(object): If no such Tag exists, a new Tag is added to the database. """ self.__check_table_from_handle(handle, transaction, Tag, - self.tag_map, self.add_tag) + self.has_tag_handle, self.add_tag) diff --git a/src/plugins/lib/libpersonview.py b/src/plugins/lib/libpersonview.py index cfe68e6b0..a532c9376 100644 --- a/src/plugins/lib/libpersonview.py +++ b/src/plugins/lib/libpersonview.py @@ -305,19 +305,17 @@ class BasePersonView(ListView): self.uistate.set_busy_cursor(True) # create the transaction - trans = self.dbstate.db.transaction_begin() + with self.dbstate.db.transaction_begin() as trans: - # create name to save - person = self.active_person - active_name = _("Delete Person (%s)") % name_displayer.display(person) + # create name to save + person = self.active_person + active_name = _("Delete Person (%s)") % name_displayer.display(person) - # delete the person from the database - # Above will emit person-delete, which removes the person via - # callback to the model, so row delete is signaled - self.dbstate.db.delete_person_from_database(person, trans) - - # commit the transaction - self.dbstate.db.transaction_commit(trans, active_name) + # delete the person from the database + # Above will emit person-delete, which removes the person via + # callback to the model, so row delete is signaled + self.dbstate.db.delete_person_from_database(person, trans) + trans.set_description(active_name) self.uistate.set_busy_cursor(False) diff --git a/src/plugins/tool/ChangeNames.py b/src/plugins/tool/ChangeNames.py index 7226bbf42..e4d81e7e6 100644 --- a/src/plugins/tool/ChangeNames.py +++ b/src/plugins/tool/ChangeNames.py @@ -231,30 +231,30 @@ class ChangeNames(tool.BatchTool, ManagedWindow.ManagedWindow): GrampsDisplay.help(WIKI_HELP_PAGE , WIKI_HELP_SEC) def on_ok_clicked(self, obj): - self.trans = self.db.transaction_begin("",batch=True) - self.db.disable_signals() - changelist = set(self.model.get_value(node,1) - for node in self.iter_list - if self.model.get_value(node,0)) + with self.db.transaction_begin(_("Capitalization changes"),batch=True + ) as self.trans: + self.db.disable_signals() + changelist = set(self.model.get_value(node,1) + for node in self.iter_list + if self.model.get_value(node,0)) - #with self.db.get_person_cursor(update=True, commit=True) as cursor: - # for handle, data in cursor: - for handle in self.db.get_person_handles(False): - person = self.db.get_person_from_handle(handle) - #person = Person(data) - change = False - for name in [person.get_primary_name()] + person.get_alternate_names(): - sname = find_surname_name(handle, name.serialize()) - if sname in changelist: - change = True - for surn in name.get_surname_list(): - sname = self.name_cap(surn.get_surname()) - surn.set_surname(sname) - if change: - #cursor.update(handle, person.serialize()) - self.db.commit_person(person, transaction=self.trans) + #with self.db.get_person_cursor(update=True, commit=True) as cursor: + # for handle, data in cursor: + for handle in self.db.get_person_handles(False): + person = self.db.get_person_from_handle(handle) + #person = Person(data) + change = False + for name in [person.get_primary_name()] + person.get_alternate_names(): + sname = find_surname_name(handle, name.serialize()) + if sname in changelist: + change = True + for surn in name.get_surname_list(): + sname = self.name_cap(surn.get_surname()) + surn.set_surname(sname) + if change: + #cursor.update(handle, person.serialize()) + self.db.commit_person(person, transaction=self.trans) - self.db.transaction_commit(self.trans,_("Capitalization changes")) self.db.enable_signals() self.db.request_rebuild() # FIXME: this probably needs to be removed, and bookmarks diff --git a/src/plugins/tool/ChangeTypes.py b/src/plugins/tool/ChangeTypes.py index 909848ba1..831e9fba2 100644 --- a/src/plugins/tool/ChangeTypes.py +++ b/src/plugins/tool/ChangeTypes.py @@ -110,23 +110,23 @@ class ChangeTypes(tool.BatchTool, ManagedWindow.ManagedWindow): modified = 0 - self.trans = self.db.transaction_begin("",batch=True) - self.db.disable_signals() - if not cli: - progress = ProgressMeter(_('Analyzing Events'),'') - progress.set_pass('',self.db.get_number_of_events()) - - for event_handle in self.db.get_event_handles(): - event = self.db.get_event_from_handle(event_handle) - if event.get_type().xml_str() == fromtype: - event.type.set_from_xml_str(totype) - modified += 1 - self.db.commit_event(event,self.trans) + with self.db.transaction_begin(_('Change types'), batch=True + ) as self.trans: + self.db.disable_signals() if not cli: - progress.step() - if not cli: - progress.close() - self.db.transaction_commit(self.trans,_('Change types')) + progress = ProgressMeter(_('Analyzing Events'),'') + progress.set_pass('',self.db.get_number_of_events()) + + for event_handle in self.db.get_event_handles(): + event = self.db.get_event_from_handle(event_handle) + if event.get_type().xml_str() == fromtype: + event.type.set_from_xml_str(totype) + modified += 1 + self.db.commit_event(event,self.trans) + if not cli: + progress.step() + if not cli: + progress.close() self.db.enable_signals() self.db.request_rebuild() diff --git a/src/plugins/tool/Check.py b/src/plugins/tool/Check.py index b11a896c0..fbe3fd677 100644 --- a/src/plugins/tool/Check.py +++ b/src/plugins/tool/Check.py @@ -174,37 +174,37 @@ class Check(tool.BatchTool): if self.db.__class__.__name__ == 'DbBsddb': low_level(self.db) - trans = self.db.transaction_begin("", batch=True) - self.db.disable_signals() - checker = CheckIntegrity(dbstate, uistate, trans) - checker.fix_encoding() - checker.fix_ctrlchars_in_notes() - checker.cleanup_missing_photos(cli) - checker.cleanup_deleted_name_formats() + with self.db.transaction_begin(_("Check Integrity"), batch=True + ) as trans: + self.db.disable_signals() + checker = CheckIntegrity(dbstate, uistate, trans) + checker.fix_encoding() + checker.fix_ctrlchars_in_notes() + checker.cleanup_missing_photos(cli) + checker.cleanup_deleted_name_formats() - prev_total = -1 - total = 0 + prev_total = -1 + total = 0 - #start with empty objects, broken links can be corrected below then - checker.cleanup_empty_objects() - while prev_total != total: - prev_total = total - - checker.check_for_broken_family_links() - checker.check_parent_relationships() - checker.cleanup_empty_families(cli) - checker.cleanup_duplicate_spouses() + #start with empty objects, broken links can be corrected below then + checker.cleanup_empty_objects() + while prev_total != total: + prev_total = total + + checker.check_for_broken_family_links() + checker.check_parent_relationships() + checker.cleanup_empty_families(cli) + checker.cleanup_duplicate_spouses() + + total = checker.family_errors() - total = checker.family_errors() - - checker.check_events() - checker.check_person_references() - checker.check_place_references() - checker.check_source_references() - checker.check_media_references() - checker.check_repo_references() - checker.check_note_references() - self.db.transaction_commit(trans, _("Check Integrity")) + checker.check_events() + checker.check_person_references() + checker.check_place_references() + checker.check_source_references() + checker.check_media_references() + checker.check_repo_references() + checker.check_note_references() self.db.enable_signals() self.db.request_rebuild() diff --git a/src/plugins/tool/DateParserDisplayTest.py b/src/plugins/tool/DateParserDisplayTest.py index 1a5aa469b..6233f1fc7 100644 --- a/src/plugins/tool/DateParserDisplayTest.py +++ b/src/plugins/tool/DateParserDisplayTest.py @@ -155,70 +155,70 @@ class DateParserDisplayTest(tool.Tool): # (4,7,1789,False,5,88,1876,False),"Text comment") #dates.append( d) - trans = self.db.transaction_begin("",batch=True) - self.db.disable_signals() - self.progress.set_pass(_('Generating dates'), - len(dates)) - # now add them as birth to new persons - i = 1 - for dateval in dates: - person = gen.lib.Person() - name = gen.lib.Name() - name.set_surname("DateTest") - name.set_first_name("Test %d" % i) - person.set_primary_name( name) - self.db.add_person(person,trans) - bevent = gen.lib.Event() - bevent.set_type(gen.lib.EventType.BIRTH) - bevent.set_date_object(dateval) - bevent.set_description("Date Test %d (source)" % i) - bevent_h = self.db.add_event(bevent,trans) - bevent_ref = gen.lib.EventRef() - bevent_ref.set_reference_handle(bevent_h) - # for the death event display the date as text and parse it back to a new date - ndate = None - try: - datestr = _dd.display( dateval) + with self.db.transaction_begin(_("Date Test Plugin"),batch=True + ) as trans: + self.db.disable_signals() + self.progress.set_pass(_('Generating dates'), + len(dates)) + # now add them as birth to new persons + i = 1 + for dateval in dates: + person = gen.lib.Person() + name = gen.lib.Name() + name.set_surname("DateTest") + name.set_first_name("Test %d" % i) + person.set_primary_name( name) + self.db.add_person(person,trans) + bevent = gen.lib.Event() + bevent.set_type(gen.lib.EventType.BIRTH) + bevent.set_date_object(dateval) + bevent.set_description("Date Test %d (source)" % i) + bevent_h = self.db.add_event(bevent,trans) + bevent_ref = gen.lib.EventRef() + bevent_ref.set_reference_handle(bevent_h) + # for the death event display the date as text and parse it back to a new date + ndate = None try: - ndate = _dp.parse( datestr) - if not ndate: + datestr = _dd.display( dateval) + try: + ndate = _dp.parse( datestr) + if not ndate: + ndate = gen.lib.Date() + ndate.set_as_text("DateParser None") + person.set_marker(gen.lib.MarkerType.TODO_TYPE) + else: + person.set_marker(gen.lib.MarkerType.COMPLETE) + except: ndate = gen.lib.Date() - ndate.set_as_text("DateParser None") + ndate.set_as_text("DateParser Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),)) person.set_marker(gen.lib.MarkerType.TODO_TYPE) - else: - person.set_marker(gen.lib.MarkerType.COMPLETE) except: ndate = gen.lib.Date() - ndate.set_as_text("DateParser Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),)) + ndate.set_as_text("DateDisplay Exception: %s" % ("".join(traceback.format_exception(*sys.exc_info())),)) person.set_marker(gen.lib.MarkerType.TODO_TYPE) - except: - ndate = gen.lib.Date() - ndate.set_as_text("DateDisplay Exception: %s" % ("".join(traceback.format_exception(*sys.exc_info())),)) - person.set_marker(gen.lib.MarkerType.TODO_TYPE) - - if dateval.get_modifier() != gen.lib.Date.MOD_TEXTONLY \ - and ndate.get_modifier() == gen.lib.Date.MOD_TEXTONLY: - # parser was unable to correctly parse the string - ndate.set_as_text( "TEXTONLY: "+ndate.get_text()) - person.set_marker(gen.lib.MarkerType.TODO_TYPE) - if dateval.get_modifier() == gen.lib.Date.MOD_TEXTONLY \ - and dateval.get_text().count("Traceback") \ - and person.get_marker() == gen.lib.MarkerType.COMPLETE: - person.set_marker(gen.lib.MarkerType.TODO_TYPE) - - devent = gen.lib.Event() - devent.set_type(gen.lib.EventType.DEATH) - devent.set_date_object(ndate) - devent.set_description("Date Test %d (result)" % i) - devent_h = self.db.add_event(devent,trans) - devent_ref = gen.lib.EventRef() - devent_ref.set_reference_handle(devent_h) - person.set_birth_ref(bevent_ref) - person.set_death_ref(devent_ref) - self.db.commit_person(person,trans) - i = i + 1 - self.progress.step() - self.db.transaction_commit(trans, _("Date Test Plugin")) + + if dateval.get_modifier() != gen.lib.Date.MOD_TEXTONLY \ + and ndate.get_modifier() == gen.lib.Date.MOD_TEXTONLY: + # parser was unable to correctly parse the string + ndate.set_as_text( "TEXTONLY: "+ndate.get_text()) + person.set_marker(gen.lib.MarkerType.TODO_TYPE) + if dateval.get_modifier() == gen.lib.Date.MOD_TEXTONLY \ + and dateval.get_text().count("Traceback") \ + and person.get_marker() == gen.lib.MarkerType.COMPLETE: + person.set_marker(gen.lib.MarkerType.TODO_TYPE) + + devent = gen.lib.Event() + devent.set_type(gen.lib.EventType.DEATH) + devent.set_date_object(ndate) + devent.set_description("Date Test %d (result)" % i) + devent_h = self.db.add_event(devent,trans) + devent_ref = gen.lib.EventRef() + devent_ref.set_reference_handle(devent_h) + person.set_birth_ref(bevent_ref) + person.set_death_ref(devent_ref) + self.db.commit_person(person,trans) + i = i + 1 + self.progress.step() self.db.enable_signals() self.db.request_rebuild() self.progress.close() diff --git a/src/plugins/tool/EventNames.py b/src/plugins/tool/EventNames.py index 825555c1d..ee7df547e 100644 --- a/src/plugins/tool/EventNames.py +++ b/src/plugins/tool/EventNames.py @@ -78,34 +78,34 @@ class EventNames(tool.BatchTool, ManagedWindow.ManagedWindow): """ Perform the actual extraction of information. """ - trans = self.db.transaction_begin("", batch=True) - self.db.disable_signals() - self.change = False - counter = 0 + with self.db.transaction_begin(_("Event name changes"), batch=True + ) as trans: + self.db.disable_signals() + self.change = False + counter = 0 - for person in self.db.iter_people(): - for event_ref in person.get_event_ref_list(): - if event_ref.get_role() == gen.lib.EventRoleType.PRIMARY: - event_handle = event_ref.ref - event = self.db.get_event_from_handle(event_handle) - if event.get_description() == "": - person_event_name(event, person) - self.db.commit_event(event, trans) - self.change = True - counter += 1 + for person in self.db.iter_people(): + for event_ref in person.get_event_ref_list(): + if event_ref.get_role() == gen.lib.EventRoleType.PRIMARY: + event_handle = event_ref.ref + event = self.db.get_event_from_handle(event_handle) + if event.get_description() == "": + person_event_name(event, person) + self.db.commit_event(event, trans) + self.change = True + counter += 1 - for family in self.db.iter_families(): - for event_ref in family.get_event_ref_list(): - if event_ref.get_role() == gen.lib.EventRoleType.FAMILY: - event_handle = event_ref.ref - event = self.db.get_event_from_handle(event_handle) - if event.get_description() == "": - family_event_name(event, family, self.db) - self.db.commit_event(event, trans) - self.change = True - counter += 1 + for family in self.db.iter_families(): + for event_ref in family.get_event_ref_list(): + if event_ref.get_role() == gen.lib.EventRoleType.FAMILY: + event_handle = event_ref.ref + event = self.db.get_event_from_handle(event_handle) + if event.get_description() == "": + family_event_name(event, family, self.db) + self.db.commit_event(event, trans) + self.change = True + counter += 1 - self.db.transaction_commit(trans, _("Event name changes")) self.db.enable_signals() self.db.request_rebuild() diff --git a/src/plugins/tool/ExtractCity.py b/src/plugins/tool/ExtractCity.py index 0c5686795..9d07b0b62 100644 --- a/src/plugins/tool/ExtractCity.py +++ b/src/plugins/tool/ExtractCity.py @@ -591,27 +591,27 @@ class ExtractCity(tool.BatchTool, ManagedWindow.ManagedWindow): GrampsDisplay.help() def on_ok_clicked(self, obj): - self.trans = self.db.transaction_begin("", batch=True) - self.db.disable_signals() - changelist = [node for node in self.iter_list - if self.model.get_value(node, 0)] + with self.db.transaction_begin(_("Extract Place data"), batch=True + ) as self.trans: + self.db.disable_signals() + changelist = [node for node in self.iter_list + if self.model.get_value(node, 0)] - for change in changelist: - row = self.model[change] - place = self.db.get_place_from_handle(row[6]) - (city, state, postal, country) = (row[2], row[3], row[4], row[5]) + for change in changelist: + row = self.model[change] + place = self.db.get_place_from_handle(row[6]) + (city, state, postal, country) = (row[2], row[3], row[4], row[5]) - if city: - place.get_main_location().set_city(city) - if state: - place.get_main_location().set_state(state) - if postal: - place.get_main_location().set_postal_code(postal) - if country: - place.get_main_location().set_country(country) - self.db.commit_place(place, self.trans) + if city: + place.get_main_location().set_city(city) + if state: + place.get_main_location().set_state(state) + if postal: + place.get_main_location().set_postal_code(postal) + if country: + place.get_main_location().set_country(country) + self.db.commit_place(place, self.trans) - self.db.transaction_commit(self.trans, _("Extract Place data")) self.db.enable_signals() self.db.request_rebuild() self.close() diff --git a/src/plugins/tool/MediaManager.py b/src/plugins/tool/MediaManager.py index 9a1bc57f3..6303e37b1 100644 --- a/src/plugins/tool/MediaManager.py +++ b/src/plugins/tool/MediaManager.py @@ -358,27 +358,13 @@ class BatchOp(UpdateCallback): and transactions before and after the running. Should not be overridden without good reasons. """ - self._pre_run() - success = self._run() - self._post_run() - return success - - def _pre_run(self): - """ - Low-level method for starting transaction and disabling signals. - Should not be overridden without good reasons. - """ - self.trans = self.db.transaction_begin("",batch=True) self.db.disable_signals() - - def _post_run(self): - """ - Low-level method for committing transaction and enabling signals. - Should not be overridden without good reasons. - """ - self.db.transaction_commit(self.trans,self.title) + with self.db.transaction_begin("", batch=True) as self.trans: + success = self._run() + trans.set_description(self.title) self.db.enable_signals() self.db.request_rebuild() + return success def _run(self): """ diff --git a/src/plugins/tool/NotRelated.py b/src/plugins/tool/NotRelated.py index 23836fe54..cb684841e 100644 --- a/src/plugins/tool/NotRelated.py +++ b/src/plugins/tool/NotRelated.py @@ -242,47 +242,45 @@ class NotRelated(tool.ActivePersonTool, ManagedWindow.ManagedWindow) : tag_name = self.tagcombo.get_active_text() # start the db transaction - transaction = self.db.transaction_begin() + with self.db.transaction_begin("Tag not related") as transaction: - tag = self.db.get_tag_from_name(tag_name) - if not tag: - # create the tag if it doesn't already exist - tag = Tag() - tag.set_name(tag_name) - tag.set_priority(self.db.get_number_of_tags()) - tag_handle = self.db.add_tag(tag, transaction) - else: - tag_handle = tag.get_handle() + tag = self.db.get_tag_from_name(tag_name) + if not tag: + # create the tag if it doesn't already exist + tag = Tag() + tag.set_name(tag_name) + tag.set_priority(self.db.get_number_of_tags()) + tag_handle = self.db.add_tag(tag, transaction) + else: + tag_handle = tag.get_handle() - # if more than 1 person is selected, use a progress indicator - if rows > 1: - progress = ProgressMeter(self.title,_('Starting')) - #TRANS: no singular form needed, as rows is always > 1 - progress.set_pass(ngettext("Setting tag for %d person", - "Setting tag for %d people", - rows) % rows, rows) + # if more than 1 person is selected, use a progress indicator + if rows > 1: + progress = ProgressMeter(self.title,_('Starting')) + #TRANS: no singular form needed, as rows is always > 1 + progress.set_pass(ngettext("Setting tag for %d person", + "Setting tag for %d people", + rows) % rows, rows) + + # iterate through all of the selected rows + (model, paths) = self.treeSelection.get_selected_rows() - # iterate through all of the selected rows - (model, paths) = self.treeSelection.get_selected_rows() + for path in paths: + if progress: + progress.step() + + # for the current row, get the GID and the person from the database + iter = self.model.get_iter(path) + personGid = self.model.get_value(iter, 1) + person = self.db.get_person_from_gramps_id(personGid) - for path in paths: - if progress: - progress.step() + # add the tag to the person + person.add_tag(tag_handle) - # for the current row, get the GID and the person from the database - iter = self.model.get_iter(path) - personGid = self.model.get_value(iter, 1) - person = self.db.get_person_from_gramps_id(personGid) + # save this change + self.db.commit_person(person, transaction) - # add the tag to the person - person.add_tag(tag_handle) - - # save this change - self.db.commit_person(person, transaction) - - # commit the entire transaction - self.db.transaction_commit(transaction, "Tag not related") # refresh the tags column self.treeView.set_model(None) diff --git a/src/plugins/tool/PatchNames.py b/src/plugins/tool/PatchNames.py index 199be4cf1..b60b18c87 100644 --- a/src/plugins/tool/PatchNames.py +++ b/src/plugins/tool/PatchNames.py @@ -481,63 +481,62 @@ class PatchNames(tool.BatchTool, ManagedWindow.ManagedWindow): GrampsDisplay.help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC) def on_ok_clicked(self, obj): - trans = self.db.transaction_begin("", batch=True) - self.db.disable_signals() + with self.db.transaction_begin(_("Extract information from names"), + batch=True) as trans: + self.db.disable_signals() - for key, data in self.handle_to_action.items(): - p = self.db.get_person_from_handle(key) - if self.nickid in data: - modelhandle = self.nick_hash[key] - val = self.model.get_value(modelhandle, 0) - if val: - given, nick = data[self.nickid] - name = p.get_primary_name() - name.set_first_name(given.strip()) - name.set_nick_name(nick.strip()) + for key, data in self.handle_to_action.items(): + p = self.db.get_person_from_handle(key) + if self.nickid in data: + modelhandle = self.nick_hash[key] + val = self.model.get_value(modelhandle, 0) + if val: + given, nick = data[self.nickid] + name = p.get_primary_name() + name.set_first_name(given.strip()) + name.set_nick_name(nick.strip()) - if self.titleid in data: - modelhandle = self.title_hash[key] - val = self.model.get_value(modelhandle, 0) - if val: - title, given = data[self.titleid] - name = p.get_primary_name() - name.set_first_name(given.strip()) - name.set_title(title.strip()) - - if self.pref1id in data: - modelhandle = self.prefix1_hash[key] - val = self.model.get_value(modelhandle, 0) - if val: - given, prefixtotal, prefix = data[self.pref1id] - name = p.get_primary_name() - name.set_first_name(given.strip()) - oldpref = name.get_surname_list()[0].get_prefix().strip() - if oldpref == '' or oldpref == prefix.strip(): - name.get_surname_list()[0].set_prefix(prefix) - else: - name.get_surname_list()[0].set_prefix('%s %s' % (prefix, oldpref)) - - if self.compid in data: - modelhandle = self.compound_hash[key] - val = self.model.get_value(modelhandle, 0) - if val: - surns, prefs, cons, prims, origs = data[self.compid] - name = p.get_primary_name() - new_surn_list = [] - for surn, pref, con, prim, orig in zip(surns, prefs, cons, - prims, origs): - new_surn_list.append(gen.lib.Surname()) - new_surn_list[-1].set_surname(surn.strip()) - new_surn_list[-1].set_prefix(pref.strip()) - new_surn_list[-1].set_connector(con.strip()) - new_surn_list[-1].set_primary(prim) - new_surn_list[-1].set_origintype(orig) - name.set_surname_list(new_surn_list) + if self.titleid in data: + modelhandle = self.title_hash[key] + val = self.model.get_value(modelhandle, 0) + if val: + title, given = data[self.titleid] + name = p.get_primary_name() + name.set_first_name(given.strip()) + name.set_title(title.strip()) - self.db.commit_person(p, trans) - - self.db.transaction_commit(trans, - _("Extract information from names")) + if self.pref1id in data: + modelhandle = self.prefix1_hash[key] + val = self.model.get_value(modelhandle, 0) + if val: + given, prefixtotal, prefix = data[self.pref1id] + name = p.get_primary_name() + name.set_first_name(given.strip()) + oldpref = name.get_surname_list()[0].get_prefix().strip() + if oldpref == '' or oldpref == prefix.strip(): + name.get_surname_list()[0].set_prefix(prefix) + else: + name.get_surname_list()[0].set_prefix('%s %s' % (prefix, oldpref)) + + if self.compid in data: + modelhandle = self.compound_hash[key] + val = self.model.get_value(modelhandle, 0) + if val: + surns, prefs, cons, prims, origs = data[self.compid] + name = p.get_primary_name() + new_surn_list = [] + for surn, pref, con, prim, orig in zip(surns, prefs, cons, + prims, origs): + new_surn_list.append(gen.lib.Surname()) + new_surn_list[-1].set_surname(surn.strip()) + new_surn_list[-1].set_prefix(pref.strip()) + new_surn_list[-1].set_connector(con.strip()) + new_surn_list[-1].set_primary(prim) + new_surn_list[-1].set_origintype(orig) + name.set_surname_list(new_surn_list) + + self.db.commit_person(p, trans) + self.db.enable_signals() self.db.request_rebuild() self.close() diff --git a/src/plugins/tool/RemoveUnused.py b/src/plugins/tool/RemoveUnused.py index f43e6e07a..b267c5e12 100644 --- a/src/plugins/tool/RemoveUnused.py +++ b/src/plugins/tool/RemoveUnused.py @@ -285,23 +285,23 @@ class RemoveUnused(tool.Tool, ManagedWindow.ManagedWindow, UpdateCallback): self.reset() def do_remove(self, obj): - trans = self.db.transaction_begin("", batch=False) - self.db.disable_signals() + with self.db.transaction_begin(_("Remove unused objects"), + batch=False) as trans: + self.db.disable_signals() - for row_num in range(len(self.real_model)-1, -1, -1): - path = (row_num,) - row = self.real_model[path] - if not row[RemoveUnused.MARK_COL]: - continue + for row_num in range(len(self.real_model)-1, -1, -1): + path = (row_num,) + row = self.real_model[path] + if not row[RemoveUnused.MARK_COL]: + continue - the_type = row[RemoveUnused.OBJ_TYPE_COL] - handle = row[RemoveUnused.OBJ_HANDLE_COL] - remove_func = self.tables[the_type]['remove'] - remove_func(handle, trans) + the_type = row[RemoveUnused.OBJ_TYPE_COL] + handle = row[RemoveUnused.OBJ_HANDLE_COL] + remove_func = self.tables[the_type]['remove'] + remove_func(handle, trans) - self.real_model.remove(row.iter) + self.real_model.remove(row.iter) - self.db.transaction_commit(trans, _("Remove unused objects")) self.db.enable_signals() self.db.request_rebuild() diff --git a/src/plugins/tool/ReorderIds.py b/src/plugins/tool/ReorderIds.py index c834b5478..44cc55cae 100644 --- a/src/plugins/tool/ReorderIds.py +++ b/src/plugins/tool/ReorderIds.py @@ -67,97 +67,97 @@ class ReorderIds(tool.BatchTool): else: print "Reordering Gramps IDs..." - self.trans = db.transaction_begin("", batch=True) - db.disable_signals() + with db.transaction_begin(_("Reorder Gramps IDs"), batch=True + ) as self.trans: + db.disable_signals() - if uistate: - self.progress.set_pass(_('Reordering People IDs'), - db.get_number_of_people()) - self.reorder(gen.lib.Person, - db.get_person_from_gramps_id, - db.get_person_from_handle, - db.find_next_person_gramps_id, - db.person_map, - db.commit_person, - db.person_prefix) + if uistate: + self.progress.set_pass(_('Reordering People IDs'), + db.get_number_of_people()) + self.reorder(gen.lib.Person, + db.get_person_from_gramps_id, + db.get_person_from_handle, + db.find_next_person_gramps_id, + db.person_map, + db.commit_person, + db.person_prefix) - if uistate: - self.progress.set_pass(_('Reordering Family IDs'), - db.get_number_of_families()) - self.reorder(gen.lib.Family, - db.get_family_from_gramps_id, - db.get_family_from_handle, - db.find_next_family_gramps_id, - db.family_map, - db.commit_family, - db.family_prefix) - if uistate: - self.progress.set_pass(_('Reordering Event IDs'), - db.get_number_of_events()) - self.reorder(gen.lib.Event, - db.get_event_from_gramps_id, - db.get_event_from_handle, - db.find_next_event_gramps_id, - db.event_map, - db.commit_event, - db.event_prefix) - if uistate: - self.progress.set_pass(_('Reordering Media Object IDs'), - db.get_number_of_media_objects()) - self.reorder(gen.lib.MediaObject, - db.get_object_from_gramps_id, - db.get_object_from_handle, - db.find_next_object_gramps_id, - db.media_map, - db.commit_media_object, - db.mediaobject_prefix) - if uistate: - self.progress.set_pass(_('Reordering Source IDs'), - db.get_number_of_sources()) - self.reorder(gen.lib.Source, - db.get_source_from_gramps_id, - db.get_source_from_handle, - db.find_next_source_gramps_id, - db.source_map, - db.commit_source, - db.source_prefix) - if uistate: - self.progress.set_pass(_('Reordering Place IDs'), - db.get_number_of_places()) - self.reorder(gen.lib.Place, - db.get_place_from_gramps_id, - db.get_place_from_handle, - db.find_next_place_gramps_id, - db.place_map, - db.commit_place, - db.place_prefix) - if uistate: - self.progress.set_pass(_('Reordering Repository IDs'), - db.get_number_of_repositories()) - self.reorder(gen.lib.Repository, - db.get_repository_from_gramps_id, - db.get_repository_from_handle, - db.find_next_repository_gramps_id, - db.repository_map, - db.commit_repository, - db.repository_prefix) -#add reorder notes ID - if uistate: - self.progress.set_pass(_('Reordering Note IDs'), - db.get_number_of_notes()) - self.reorder(gen.lib.Note, - db.get_note_from_gramps_id, - db.get_note_from_handle, - db.find_next_note_gramps_id, - db.note_map, - db.commit_note, - db.note_prefix) - if uistate: - self.progress.close() - else: - print "Done." - - db.transaction_commit(self.trans, _("Reorder Gramps IDs")) + if uistate: + self.progress.set_pass(_('Reordering Family IDs'), + db.get_number_of_families()) + self.reorder(gen.lib.Family, + db.get_family_from_gramps_id, + db.get_family_from_handle, + db.find_next_family_gramps_id, + db.family_map, + db.commit_family, + db.family_prefix) + if uistate: + self.progress.set_pass(_('Reordering Event IDs'), + db.get_number_of_events()) + self.reorder(gen.lib.Event, + db.get_event_from_gramps_id, + db.get_event_from_handle, + db.find_next_event_gramps_id, + db.event_map, + db.commit_event, + db.event_prefix) + if uistate: + self.progress.set_pass(_('Reordering Media Object IDs'), + db.get_number_of_media_objects()) + self.reorder(gen.lib.MediaObject, + db.get_object_from_gramps_id, + db.get_object_from_handle, + db.find_next_object_gramps_id, + db.media_map, + db.commit_media_object, + db.mediaobject_prefix) + if uistate: + self.progress.set_pass(_('Reordering Source IDs'), + db.get_number_of_sources()) + self.reorder(gen.lib.Source, + db.get_source_from_gramps_id, + db.get_source_from_handle, + db.find_next_source_gramps_id, + db.source_map, + db.commit_source, + db.source_prefix) + if uistate: + self.progress.set_pass(_('Reordering Place IDs'), + db.get_number_of_places()) + self.reorder(gen.lib.Place, + db.get_place_from_gramps_id, + db.get_place_from_handle, + db.find_next_place_gramps_id, + db.place_map, + db.commit_place, + db.place_prefix) + if uistate: + self.progress.set_pass(_('Reordering Repository IDs'), + db.get_number_of_repositories()) + self.reorder(gen.lib.Repository, + db.get_repository_from_gramps_id, + db.get_repository_from_handle, + db.find_next_repository_gramps_id, + db.repository_map, + db.commit_repository, + db.repository_prefix) + #add reorder notes ID + if uistate: + self.progress.set_pass(_('Reordering Note IDs'), + db.get_number_of_notes()) + self.reorder(gen.lib.Note, + db.get_note_from_gramps_id, + db.get_note_from_handle, + db.find_next_note_gramps_id, + db.note_map, + db.commit_note, + db.note_prefix) + if uistate: + self.progress.close() + else: + print "Done." + db.enable_signals() db.request_rebuild() diff --git a/src/plugins/tool/SortEvents.py b/src/plugins/tool/SortEvents.py index 060b1fd91..51fffb27a 100644 --- a/src/plugins/tool/SortEvents.py +++ b/src/plugins/tool/SortEvents.py @@ -95,12 +95,12 @@ class SortEvents(PluginWindows.ToolManagedWindowBatch): self.sort_name = sort_functions[sort_func_num][0] self.sort_func = sort_functions[sort_func_num][1] self.sort = Sort.Sort(self.db) - trans = self.db.transaction_begin("", batch=True) - self.db.disable_signals() - family_handles = self.sort_person_events(trans) - if len(family_handles) > 0: - self.sort_family_events(family_handles, trans) - self.db.transaction_commit(trans, _("Sort event changes")) + with self.db.transaction_begin(_("Sort event changes"), batch=True + ) as trans: + self.db.disable_signals() + family_handles = self.sort_person_events(trans) + if len(family_handles) > 0: + self.sort_family_events(family_handles, trans) self.db.enable_signals() self.db.request_rebuild() diff --git a/src/plugins/tool/TestcaseGenerator.py b/src/plugins/tool/TestcaseGenerator.py index acedc1e2b..a907a8e3f 100644 --- a/src/plugins/tool/TestcaseGenerator.py +++ b/src/plugins/tool/TestcaseGenerator.py @@ -219,7 +219,7 @@ class TestcaseGenerator(tool.BatchTool): self.db.disable_signals() else: batch = False - self.trans = self.db.transaction_begin("") + self.trans = self.db.transaction_begin(_("Testcase generator")) if False and self.options.handler.options_dict['no_trans']: @@ -1324,6 +1324,9 @@ class TestcaseGenerator(tool.BatchTool): return result def commit_transaction(self): + # The way transactions are used in this file is outdated; use a with + # statement so that transaction abort is called on failure. It is too + # much effort to update this file. #if self.options.handler.options_dict['no_trans']: self.db.transaction_commit(self.trans,_("Testcase generator step %d") % self.transaction_count) self.transaction_count += 1 diff --git a/src/plugins/view/mediaview.py b/src/plugins/view/mediaview.py index d29604a8a..677513783 100644 --- a/src/plugins/view/mediaview.py +++ b/src/plugins/view/mediaview.py @@ -206,10 +206,9 @@ class MediaView(ListView): basename = os.path.basename(name) (root, ext) = os.path.splitext(basename) photo.set_description(root) - trans = self.dbstate.db.transaction_begin() - self.dbstate.db.add_object(photo, trans) - self.dbstate.db.transaction_commit(trans, - _("Drag Media Object")) + with self.dbstate.db.transaction_begin(_("Drag Media Object") + ) as trans: + self.dbstate.db.add_object(photo, trans) widget.emit_stop_by_name('drag_data_received') def get_bookmarks(self): diff --git a/src/plugins/view/relview.py b/src/plugins/view/relview.py index dbdcd7f90..38bdb1194 100644 --- a/src/plugins/view/relview.py +++ b/src/plugins/view/relview.py @@ -1500,14 +1500,14 @@ class RelationshipView(NavigationView): family = self.dbstate.db.get_family_from_handle(family_handle) family.add_child_ref(ref) - trans = self.dbstate.db.transaction_begin() - #add parentref to child - person.add_parent_family_handle(family_handle) - #default relationship is used - self.dbstate.db.commit_person(person, trans) - #add child to family - self.dbstate.db.commit_family(family, trans) - self.dbstate.db.transaction_commit(trans, _("Add Child to Family")) + with self.dbstate.db.transaction_begin(_("Add Child to Family") + ) as trans: + #add parentref to child + person.add_parent_family_handle(family_handle) + #default relationship is used + self.dbstate.db.commit_person(person, trans) + #add child to family + self.dbstate.db.commit_family(family, trans) def sel_child_to_fam(self, obj, event, handle, surname=None): if button_activated(event, _LEFT_BUTTON):