diff --git a/src/Merge/test/merge_ref_test.py b/src/Merge/test/merge_ref_test.py
new file mode 100644
index 000000000..acd083cd9
--- /dev/null
+++ b/src/Merge/test/merge_ref_test.py
@@ -0,0 +1,2122 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2011 Michiel D. Nauta
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+# $Id$
+
+"""
+Unittest that tests that part of the merge process that influences other
+objects than the objects merging.
+"""
+
+import unittest
+import time
+import sys
+import os
+sys.path.append(os.curdir)
+sys.path.append(os.path.join(os.curdir, 'plugins', 'lib'))
+import subprocess
+import libxml2
+import libxslt
+
+from libgrampsxml import GRAMPS_XML_VERSION
+from const import ROOT_DIR, VERSION, USER_PLUGINS
+import gen.lib
+from gen.ggettext import sgettext as _
+
+class CopiedDoc(object):
+ """Context manager that creates a deep copy of an libxml-xml document."""
+ def __init__(self, xmldoc):
+ self.xmldoc = xmldoc
+ self.copy = libxml2.readDoc(str(self.xmldoc), '', None,
+ libxml2.XML_PARSE_NONET)
+
+ def __enter__(self):
+ return self.copy
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.copy.freeDoc()
+ return False
+
+class XpathContext(object):
+ """Context manager that creates a libxml2 xpath context that allows
+ evaluation of xpath expressions."""
+ def __init__(self, xmldoc):
+ self.xmldoc = xmldoc
+ self.ctxt = self.xmldoc.xpathNewContext()
+ self.ctxt.xpathRegisterNs('g', 'http://gramps-project.org/xml/%s/' %
+ GRAMPS_XML_VERSION)
+
+ def __enter__(self):
+ return self.ctxt
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.ctxt.xpathFreeContext()
+ return False
+
+class BaseMergeCheck(unittest.TestCase):
+ def base_setup(self):
+ """Set up code needed by all tests."""
+ date = time.localtime(time.time())
+ libxml2.keepBlanksDefault(0)
+ styledoc = libxml2.parseFile(os.path.join(ROOT_DIR,
+ "../data/gramps_canonicalize.xsl"))
+ self.style = libxslt.parseStylesheetDoc(styledoc)
+ self.basedoc = None
+ self.base_str = """
+
+
+
+ """ % (GRAMPS_XML_VERSION, GRAMPS_XML_VERSION, GRAMPS_XML_VERSION,
+ date[0], date[1], date[2], VERSION)
+
+ def tearDown(self):
+ self.style.freeStylesheet()
+ self.basedoc.freeDoc()
+
+ def canonicalize(self, doctxt):
+ """
+ Return a canonicalized string representation
+
+ :param doctxt: the text to bring in canonical form.
+ :type doctxt: either a string or an Xml document.
+ :returns: The text but in canonical form.
+ :rtype: string
+ """
+ result = ''
+ if type(doctxt) == type('string'):
+ doc = libxml2.readDoc(doctxt, '', None, libxml2.XML_PARSE_NONET)
+ elif isinstance(doctxt, libxml2.xmlDoc):
+ doc = doctxt
+ else:
+ raise TypeError
+ param = {}
+ canonical_doc = self.style.applyStylesheet(doc, param)
+ result = self.style.saveResultToString(canonical_doc)
+ canonical_doc.freeDoc()
+ if type(doctxt) == type('string'):
+ doc.freeDoc()
+ return result
+
+ def do_test(self, phoenix_id, titanic_id, input_doc, expect_doc,
+ test_error_str='', debug=False):
+ """Do the merge and "assert" the result."""
+ process = subprocess.Popen('python gramps.py '
+ '--config=preferences.eprefix:DEFAULT '
+ '-i - -f gramps -a tool '
+ '-p "name=climerge,primary=%s,secondary=%s" '
+ '-e - -f gramps' % (phoenix_id, titanic_id),
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE, shell=True)
+ result_str, err_str = process.communicate(str(input_doc))
+ if err_str:
+ if test_error_str:
+ self.assert_(test_error_str in err_str)
+ return
+ if debug:
+ print 'input :', self.canonicalize(input_doc)
+ print 'result:', self.canonicalize(result_str)
+ print 'expect:', self.canonicalize(expect_doc)
+ self.assertEqual(self.canonicalize(result_str),
+ self.canonicalize(expect_doc))
+
+ def do_family_test(self, phoenix_id, titanic_id, father_h, mother_h,
+ input_doc, expect_doc, test_error_str='', debug=False):
+ process = subprocess.Popen('python gramps.py '
+ '--config=preferences.eprefix:DEFAULT '
+ '-i - -f gramps -a tool '
+ '-p "name=climerge,primary=%s,secondary=%s,father_h=%s,mother_h=%s" '
+ '-e - -f gramps' % (phoenix_id, titanic_id, father_h, mother_h),
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, shell=True)
+ result_str, err_str = process.communicate(str(input_doc))
+ if err_str:
+ if test_error_str:
+ self.assert_(test_error_str in err_str)
+ return
+ if debug:
+ print 'input :', self.canonicalize(input_doc)
+ print 'result:', self.canonicalize(result_str)
+ print 'expect:', self.canonicalize(expect_doc)
+ self.assertEqual(self.canonicalize(result_str),
+ self.canonicalize(expect_doc))
+
+ def raw_contains(self, phoenix_id, titanic_id, input_doc, expect_str,
+ debug=False):
+ process = subprocess.Popen('python gramps.py '
+ '--config=preferences.eprefix:DEFAULT '
+ '-i - -f gramps -a tool '
+ '-p "name=climerge,primary=%s,secondary=%s" '
+ '-e - -f raw' % (phoenix_id, titanic_id),
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE, shell=True)
+ result_str, err_str = process.communicate(str(input_doc))
+ if err_str:
+ print err_str
+ if debug:
+ print 'input :', self.canonicalize(input_doc)
+ print 'result:', result_str
+ print 'expect:', expect_str
+ # should I order/canonicalise things?
+ self.assert_(expect_str in result_str)
+#-------------------------------------------------------------------------
+#
+# PersonCheck class
+#
+#-------------------------------------------------------------------------
+class PersonCheck(BaseMergeCheck):
+ """Class that checks what the influence is of merger of other primary
+ objects on persons."""
+ def setUp(self):
+ self.base_setup()
+ base_str = """
+
+
+ Birth
+ Event 0
+
+
+ Birth
+ Event 1
+
+
+
+
+ M
+
+ Person 0
+
+
+
+
+
+
+
+
+ p.10
+
+
+
+ M
+
+ Person 1
+
+
+
+
+
+
+
+
+ p.11
+
+
+
+
+
+
+
+
+
+ Place 0
+
+
+ Place 1
+
+
+
+
+
+
+
+
+ Note 0
+
+
+ Note 1
+
+
+ """
+ self.basedoc = libxml2.readDoc(self.base_str + base_str, '', None,
+ libxml2.XML_PARSE_NONET)
+
+ def test_event_merge(self):
+ """Merge two events"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ eventref = ctxt.xpathEval(
+ "//g:person[@handle='_i0001']/g:eventref")[0]
+ eventref.setProp('hlink', '_e0000')
+ event = ctxt.xpathEval("//g:event[@handle='_e0001']")[0]
+ event.unlinkNode()
+ event.freeNode()
+ self.do_test('E0000', 'E0001', self.basedoc, expect)
+
+ def test_place_merge(self):
+ """Merge two places"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ place = ctxt.xpathEval(
+ "//g:person[@handle='_i0001']/g:lds_ord/g:place")[0]
+ place.setProp('hlink', '_p0000')
+ placeobj = ctxt.xpathEval("//g:placeobj[@handle='_p0001']")[0]
+ placeobj.unlinkNode()
+ placeobj.freeNode()
+ self.do_test('P0000', 'P0001', self.basedoc, expect)
+
+ def test_source_merge(self):
+ """Merge two sources"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ srcref = ctxt.xpathEval(
+ "//g:person[@handle='_i0001']/g:sourceref")[0]
+ srcref.setProp('hlink', '_s0000')
+ source = ctxt.xpathEval("//g:source[@handle='_s0001']")[0]
+ source.unlinkNode()
+ source.freeNode()
+ self.do_test('S0000', 'S0001', self.basedoc, expect)
+
+ def test_media_merge(self):
+ """Merge two media objects"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ objref = ctxt.xpathEval(
+ "//g:person[@handle='_i0001']/g:objref")[0]
+ objref.setProp('hlink', '_o0000')
+ object_ = ctxt.xpathEval("//g:object[@handle='_o0001']")[0]
+ object_.unlinkNode()
+ object_.freeNode()
+ self.do_test('O0000', 'O0001', self.basedoc, expect)
+
+ def test_note_merge(self):
+ """Merge two notes"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ noteref = ctxt.xpathEval(
+ "//g:person[@handle='_i0001']/g:noteref")[0]
+ noteref.setProp('hlink', '_n0000')
+ note = ctxt.xpathEval("//g:note[@handle='_n0001']")[0]
+ note.unlinkNode()
+ note.freeNode()
+ self.do_test('N0000', 'N0001', self.basedoc, expect)
+
+#-------------------------------------------------------------------------
+#
+# FamilyCheck class
+#
+#-------------------------------------------------------------------------
+class FamilyCheck(BaseMergeCheck):
+ """Class that checks what the influence is of merger of other primary
+ objects on families."""
+ def setUp(self):
+ self.base_setup()
+ base_str = """
+
+
+ Birth
+ Event 0
+
+
+ Birth
+ Event 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Place 0
+
+
+ Place 1
+
+
+
+
+
+
+
+
+ Note 0
+
+
+ Note 1
+
+
+ """
+ self.basedoc = libxml2.readDoc(self.base_str + base_str, '', None,
+ libxml2.XML_PARSE_NONET)
+
+ def test_event_merge(self):
+ """Merge two events"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ eventref = ctxt.xpathEval(
+ "//g:family[@handle='_f0001']/g:eventref")[0]
+ eventref.setProp('hlink', '_e0000')
+ event = ctxt.xpathEval("//g:event[@handle='_e0001']")[0]
+ event.unlinkNode()
+ event.freeNode()
+ self.do_test('E0000', 'E0001', self.basedoc, expect)
+
+ def test_place_merge(self):
+ """Merge two places"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ place = ctxt.xpathEval(
+ "//g:family[@handle='_f0001']/g:lds_ord/g:place")[0]
+ place.setProp('hlink', '_p0000')
+ placeobj = ctxt.xpathEval("//g:placeobj[@handle='_p0001']")[0]
+ placeobj.unlinkNode()
+ placeobj.freeNode()
+ self.do_test('P0000', 'P0001', self.basedoc, expect)
+
+ def test_source_merge(self):
+ """Merge two sources"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ srcref = ctxt.xpathEval(
+ "//g:family[@handle='_f0001']/g:sourceref")[0]
+ srcref.setProp('hlink', '_s0000')
+ source = ctxt.xpathEval("//g:source[@handle='_s0001']")[0]
+ source.unlinkNode()
+ source.freeNode()
+ self.do_test('S0000', 'S0001', self.basedoc, expect)
+
+ def test_media_merge(self):
+ """Merge two media objects"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ objref = ctxt.xpathEval(
+ "//g:family[@handle='_f0001']/g:objref")[0]
+ objref.setProp('hlink', '_o0000')
+ object_ = ctxt.xpathEval("//g:object[@handle='_o0001']")[0]
+ object_.unlinkNode()
+ object_.freeNode()
+ self.do_test('O0000', 'O0001', self.basedoc, expect)
+
+ def test_note_merge(self):
+ """Merge two notes"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ noteref = ctxt.xpathEval(
+ "//g:family[@handle='_f0001']/g:noteref")[0]
+ noteref.setProp('hlink', '_n0000')
+ note = ctxt.xpathEval("//g:note[@handle='_n0001']")[0]
+ note.unlinkNode()
+ note.freeNode()
+ self.do_test('N0000', 'N0001', self.basedoc, expect)
+
+#-------------------------------------------------------------------------
+#
+# EventCheck class
+#
+#-------------------------------------------------------------------------
+class EventCheck(BaseMergeCheck):
+ """Class that checks what the influence is of merger of other primary
+ objects on events."""
+ def setUp(self):
+ self.base_setup()
+ base_str = """
+
+
+ Birth
+
+ Event 0
+
+
+
+
+
+ Birth
+
+ Event 1
+
+
+
+
+
+
+
+
+
+
+
+ Place 0
+
+
+ Place 1
+
+
+
+
+
+
+
+
+ Note 0
+
+
+ Note 1
+
+
+ """
+ self.basedoc = libxml2.readDoc(self.base_str + base_str, '', None,
+ libxml2.XML_PARSE_NONET)
+
+ def test_place_merge(self):
+ """Merge two places"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ place = ctxt.xpathEval(
+ "//g:event[@handle='_e0001']/g:place")[0]
+ place.setProp('hlink', '_p0000')
+ placeobj = ctxt.xpathEval("//g:placeobj[@handle='_p0001']")[0]
+ placeobj.unlinkNode()
+ placeobj.freeNode()
+ self.do_test('P0000', 'P0001', self.basedoc, expect)
+
+ def test_source_merge(self):
+ """Merge two sources"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ srcref = ctxt.xpathEval(
+ "//g:event[@handle='_e0001']/g:sourceref")[0]
+ srcref.setProp('hlink', '_s0000')
+ source = ctxt.xpathEval("//g:source[@handle='_s0001']")[0]
+ source.unlinkNode()
+ source.freeNode()
+ self.do_test('S0000', 'S0001', self.basedoc, expect)
+
+ def test_media_merge(self):
+ """Merge two media objects"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ objref = ctxt.xpathEval(
+ "//g:event[@handle='_e0001']/g:objref")[0]
+ objref.setProp('hlink', '_o0000')
+ object_ = ctxt.xpathEval("//g:object[@handle='_o0001']")[0]
+ object_.unlinkNode()
+ object_.freeNode()
+ self.do_test('O0000', 'O0001', self.basedoc, expect)
+
+ def test_note_merge(self):
+ """Merge two notes"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ noteref = ctxt.xpathEval(
+ "//g:event[@handle='_e0001']/g:noteref")[0]
+ noteref.setProp('hlink', '_n0000')
+ note = ctxt.xpathEval("//g:note[@handle='_n0001']")[0]
+ note.unlinkNode()
+ note.freeNode()
+ self.do_test('N0000', 'N0001', self.basedoc, expect)
+
+#-------------------------------------------------------------------------
+#
+# PlaceCheck class
+#
+#-------------------------------------------------------------------------
+class PlaceCheck(BaseMergeCheck):
+ """Class that checks what the influence is of merger of other primary
+ objects on places."""
+ def setUp(self):
+ self.base_setup()
+ base_str = """
+
+
+
+
+
+
+ Place 0
+
+
+
+
+
+ Place 1
+
+
+
+
+
+
+
+
+
+
+
+ Note 0
+
+
+ Note 1
+
+
+ """
+ self.basedoc = libxml2.readDoc(self.base_str + base_str, '', None,
+ libxml2.XML_PARSE_NONET)
+
+ def test_source_merge(self):
+ """Merge two sources"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ srcref = ctxt.xpathEval(
+ "//g:placeobj[@handle='_p0001']/g:sourceref")[0]
+ srcref.setProp('hlink', '_s0000')
+ source = ctxt.xpathEval("//g:source[@handle='_s0001']")[0]
+ source.unlinkNode()
+ source.freeNode()
+ self.do_test('S0000', 'S0001', self.basedoc, expect)
+
+ def test_media_merge(self):
+ """Merge two media objects"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ objref = ctxt.xpathEval(
+ "//g:placeobj[@handle='_p0001']/g:objref")[0]
+ objref.setProp('hlink', '_o0000')
+ object_ = ctxt.xpathEval("//g:object[@handle='_o0001']")[0]
+ object_.unlinkNode()
+ object_.freeNode()
+ self.do_test('O0000', 'O0001', self.basedoc, expect)
+
+ def test_note_merge(self):
+ """Merge two notes"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ noteref = ctxt.xpathEval(
+ "//g:placeobj[@handle='_p0001']/g:noteref")[0]
+ noteref.setProp('hlink', '_n0000')
+ note = ctxt.xpathEval("//g:note[@handle='_n0001']")[0]
+ note.unlinkNode()
+ note.freeNode()
+ self.do_test('N0000', 'N0001', self.basedoc, expect)
+
+#-------------------------------------------------------------------------
+#
+# SourceCheck class
+#
+#-------------------------------------------------------------------------
+class SourceCheck(BaseMergeCheck):
+ """Class that checks what the influence is of merger of other primary
+ objects on sources."""
+ def setUp(self):
+ self.base_setup()
+ base_str = """
+
+
+
+
+
+
+
+
+
+
+ Repo 0
+ Library
+
+
+ Repo 1
+ Library
+
+
+
+
+ Note 0
+
+
+ Note 1
+
+
+ """
+ self.basedoc = libxml2.readDoc(self.base_str + base_str, '', None,
+ libxml2.XML_PARSE_NONET)
+
+ #def test_source_merge(self): SEE special cases.
+
+ def test_repo_merge(self):
+ """Merge two repositories"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ # Adjust the repository reference in expectation.
+ reporef = ctxt.xpathEval(
+ "//g:source[@handle='_s0001']/g:reporef")[0]
+ reporef.setProp('hlink', '_r0000')
+ # Remove one repository in expectation.
+ repo = ctxt.xpathEval("//g:repository[@handle='_r0001']")[0]
+ repo.unlinkNode()
+ repo.freeNode()
+ # Do the actual merger and comparison.
+ self.do_test('R0000', 'R0001', self.basedoc, expect)
+
+ def test_media_merge(self):
+ """Merge two media objects"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ objref = ctxt.xpathEval(
+ "//g:source[@handle='_s0001']/g:objref")[0]
+ objref.setProp('hlink', '_o0000')
+ object_ = ctxt.xpathEval("//g:object[@handle='_o0001']")[0]
+ object_.unlinkNode()
+ object_.freeNode()
+ self.do_test('O0000', 'O0001', self.basedoc, expect)
+
+ def test_note_merge(self):
+ """Merge two notes"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ noteref = ctxt.xpathEval(
+ "//g:source[@handle='_s0001']/g:noteref")[0]
+ noteref.setProp('hlink', '_n0000')
+ note = ctxt.xpathEval("//g:note[@handle='_n0001']")[0]
+ note.unlinkNode()
+ note.freeNode()
+ self.do_test('N0000', 'N0001', self.basedoc, expect)
+
+#-------------------------------------------------------------------------
+#
+# RepoCheck class
+#
+#-------------------------------------------------------------------------
+class RepoCheck(BaseMergeCheck):
+ """Class that checks what the influence is of merger of other primary
+ objects on repositories."""
+ def setUp(self):
+ self.base_setup()
+ base_str = """
+
+
+
+
+
+
+ Repo 0
+ Library
+
+ Amsterdam
+
+
+
+
+
+ Repo 1
+ Library
+
+ Rotterdam
+
+
+
+
+
+
+
+ Note 0
+
+
+ Note 1
+
+
+ """
+ self.basedoc = libxml2.readDoc(self.base_str + base_str, '', None,
+ libxml2.XML_PARSE_NONET)
+
+ def test_source_merge(self):
+ """Merge two sources"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ srcref = ctxt.xpathEval(
+ "//g:repository[@handle='_r0001']/g:address/g:sourceref")[0]
+ srcref.setProp('hlink', '_s0000')
+ source = ctxt.xpathEval("//g:source[@handle='_s0001']")[0]
+ source.unlinkNode()
+ source.freeNode()
+ self.do_test('S0000', 'S0001', self.basedoc, expect)
+
+ def test_note_merge(self):
+ """Merge two notes"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ noteref = ctxt.xpathEval(
+ "//g:repository[@handle='_r0001']/g:noteref")[0]
+ noteref.setProp('hlink', '_n0000')
+ note = ctxt.xpathEval("//g:note[@handle='_n0001']")[0]
+ note.unlinkNode()
+ note.freeNode()
+ self.do_test('N0000', 'N0001', self.basedoc, expect)
+
+#-------------------------------------------------------------------------
+#
+# MediaCheck class
+#
+#-------------------------------------------------------------------------
+class MediaCheck(BaseMergeCheck):
+ """Class that checks what the influence is of merger of other primary
+ objects on media objects."""
+ def setUp(self):
+ self.base_setup()
+ base_str = """
+
+
+
+
+
+
+
+
+
+
+ Note 0
+
+
+ Note 1
+
+
+ """
+ self.basedoc = libxml2.readDoc(self.base_str + base_str, '', None,
+ libxml2.XML_PARSE_NONET)
+
+ def test_source_merge(self):
+ """Merge two sources"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ srcref = ctxt.xpathEval(
+ "//g:object[@handle='_o0001']/g:sourceref")[0]
+ srcref.setProp('hlink', '_s0000')
+ source = ctxt.xpathEval("//g:source[@handle='_s0001']")[0]
+ source.unlinkNode()
+ source.freeNode()
+ self.do_test('S0000', 'S0001', self.basedoc, expect)
+
+ def test_note_merge(self):
+ """Merge two notes"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ noteref = ctxt.xpathEval(
+ "//g:object[@handle='_o0001']/g:noteref")[0]
+ noteref.setProp('hlink', '_n0000')
+ note = ctxt.xpathEval("//g:note[@handle='_n0001']")[0]
+ note.unlinkNode()
+ note.freeNode()
+ self.do_test('N0000', 'N0001', self.basedoc, expect)
+
+#=========================================================================
+#
+# Special cases
+#
+#=========================================================================
+
+class SourceSourceCheck(BaseMergeCheck):
+ def setUp(self):
+ self.base_setup()
+ base_str = """
+
+
+
+
+
+
+
+
+
+
+ """
+ self.basedoc = libxml2.readDoc(self.base_str + base_str, '', None,
+ libxml2.XML_PARSE_NONET)
+
+ def test_source_merge(self):
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ srcrefs = ctxt.xpathEval(
+ "//g:source[@handle='_s0001']/g:objref/g:sourceref")
+ srcrefs[0].setProp('hlink', '_s0002')
+ sources = ctxt.xpathEval("//g:source[@handle='_s0003']")
+ sources[0].unlinkNode()
+ sources[0].freeNode()
+ self.do_test('S0002', 'S0003', self.basedoc, expect)
+
+ def test_source_cross_merge(self):
+ with XpathContext(self.basedoc) as input_ctxt:
+ input_srcrefs = input_ctxt.xpathEval(
+ "//g:source/g:objref/g:sourceref")
+ input_srcrefs[0].setProp('hlink', '_s0001')
+ input_srcrefs[1].setProp('hlink', '_s0000')
+ rmsrc = input_ctxt.xpathEval("//g:source[@handle='_s0002']")
+ rmsrc[0].unlinkNode()
+ rmsrc[0].freeNode()
+ rmsrc = input_ctxt.xpathEval("//g:source[@handle='_s0003']")
+ rmsrc[0].unlinkNode()
+ rmsrc[0].freeNode()
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ srcrefs = ctxt.xpathEval(
+ "//g:source[@handle='_s0000']/g:objref/g:sourceref")
+ srcrefs[0].setProp('hlink', '_s0000')
+ # add objref
+ objref = ctxt.xpathEval("//g:source[@handle='_s0000']/g:objref")
+ objref2 = ctxt.xpathEval("//g:source[@handle='_s0001']/g:objref")
+ objref[0].addNextSibling(objref2[0])
+ # remove source
+ sources = ctxt.xpathEval("//g:source[@handle='_s0001']")
+ sources[0].unlinkNode()
+ sources[0].freeNode()
+ self.do_test('S0000', 'S0001', self.basedoc, expect)
+
+#-------------------------------------------------------------------------
+#
+# BirthCheck class
+#
+#-------------------------------------------------------------------------
+class BirthCheck(BaseMergeCheck):
+ def setUp(self):
+ self.base_setup()
+ base_str = """
+
+
+ Baptism
+ Event 0
+
+
+ Birth
+ Event 1
+
+
+ Death
+ Event 2
+
+
+
+
+ M
+
+ Person 0
+
+
+
+
+
+
+ """
+ self.basedoc = libxml2.readDoc(self.base_str + base_str, '', None,
+ libxml2.XML_PARSE_NONET)
+ surname = gen.lib.Surname()
+ surname.set_surname(u"Person 0")
+ name = gen.lib.Name()
+ name.add_surname(surname)
+ self.expect_str = "person: i0000 ('i0000', 'I0000', 1, %s, [], " % str(
+ name.serialize())
+
+ def test_birth_loss(self):
+ # check that birth_ref_index is -1
+ expect_str = self.expect_str + "1, -1"
+ self.raw_contains('E0000', 'E0001', self.basedoc, expect_str)
+
+ def test_second_birth(self):
+ # check that birth _ref_index is 2
+ with XpathContext(self.basedoc) as ctxt:
+ events = ctxt.xpathEval("//g:events")
+ second_birth = events[0].newChild(None, 'event', None)
+ second_birth.newProp('handle', '_e0003')
+ second_birth.newProp('id', 'E0003')
+ second_birth.newChild(None, 'type', 'Birth')
+ second_birth.newChild(None, 'description', 'Event 3')
+ person = ctxt.xpathEval("//g:person[@handle='_i0000']")
+ eventref = person[0].newChild(None, 'eventref', None)
+ eventref.newProp('hlink', '_e0003')
+ eventref.newProp('role', 'Primary')
+ expect_str = self.expect_str + "1, 2"
+ self.raw_contains('E0000', 'E0001', self.basedoc, expect_str)
+
+ def test_death_merge(self):
+ # check that death_ref_index is -1
+ expect_str = self.expect_str + "-1, 1"
+ self.raw_contains('E0000', 'E0002', self.basedoc, expect_str)
+
+ def test_second_death(self):
+ # check that death _ref_index is 2
+ with XpathContext(self.basedoc) as ctxt:
+ events = ctxt.xpathEval("//g:events")
+ second_death = events[0].newChild(None, 'event', None)
+ second_death.newProp('handle', '_e0003')
+ second_death.newProp('id', 'E0003')
+ second_death.newChild(None, 'type', 'Death')
+ second_death.newChild(None, 'description', 'Event 3')
+ person = ctxt.xpathEval("//g:person[@handle='_i0000']")
+ eventref = person[0].newChild(None, 'eventref', None)
+ eventref.newProp('hlink', '_e0003')
+ eventref.newProp('role', 'Primary')
+ expect_str = self.expect_str + "2, 1"
+ self.raw_contains('E0000', 'E0002', self.basedoc, expect_str)
+
+#-------------------------------------------------------------------------
+#
+# PersonPersonCheck class
+#
+#-------------------------------------------------------------------------
+class PersonPersonCheck(BaseMergeCheck):
+ def setUp(self):
+ self.base_setup()
+ base_str = """
+
+
+ M
+
+ Person 0
+
+
+
+ M
+
+ Person 1
+
+
+
+ """
+ self.basedoc = libxml2.readDoc(self.base_str + base_str, '', None,
+ libxml2.XML_PARSE_NONET)
+
+ def test_person_merge(self):
+ """There is a person not involved in merger that references Titanic."""
+ with XpathContext(self.basedoc) as input_ctxt:
+ people = input_ctxt.xpathEval("//g:people")[0]
+ person = people.newChild(None, 'person', None)
+ person.newProp('handle', '_i0002')
+ person.newProp('id', 'I0002')
+ person.newChild(None, 'gender', 'M')
+ name = person.newChild(None, 'name', None)
+ name.newProp('type', 'Birth Name')
+ name.newChild(None, 'surname', 'Person 2')
+ personref = person.newChild(None, 'personref', None)
+ personref.newProp('hlink', '_i0001')
+ personref.newProp('rel', 'Neighbour')
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ personref = ctxt.xpathEval("//g:personref")[0]
+ personref.setProp('hlink', '_i0000')
+ person = ctxt.xpathEval("//g:person[@handle='_i0000']")[0]
+ altname = person.newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 1')
+ attr = person.newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0001')
+ person = ctxt.xpathEval("//g:person[@handle='_i0001']")[0]
+ person.unlinkNode()
+ person.freeNode()
+ self.do_test('I0000', 'I0001', self.basedoc, expect)
+
+ def test_person_cross(self):
+ """Phoenix has ref to Titanic and vice versa"""
+ with XpathContext(self.basedoc) as input_ctxt:
+ persons = input_ctxt.xpathEval("//g:person")
+ personref = persons[0].newChild(None, 'personref', None)
+ personref.newProp('hlink', '_i0001')
+ personref.newProp('rel','Neighbour East')
+ personref = persons[1].newChild(None, 'personref', None)
+ personref.newProp('hlink', '_i0000')
+ personref.newProp('rel','Neighbour West')
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+
+ personref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:personref")[0]
+ personref.setProp('hlink', '_i0000')
+ person = ctxt.xpathEval("//g:person[@handle='_i0000']")[0]
+ altname = person.newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 1')
+ attr = person.newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0001')
+ attr.addNextSibling(personref) # restore order of elements
+ personref = person.newChild(None, 'personref', None)
+ personref.newProp('hlink', '_i0000')
+ personref.newProp('rel', 'Neighbour West')
+ person = ctxt.xpathEval("//g:person[@handle='_i0001']")[0]
+ person.unlinkNode()
+ person.freeNode()
+ self.do_test('I0000', 'I0001', self.basedoc, expect)
+
+ def test_person_self(self):
+ """Titanic references itself"""
+ with XpathContext(self.basedoc) as input_ctxt:
+ person = input_ctxt.xpathEval("//g:person[@handle='_i0001']")[0]
+ personref = person.newChild(None, 'personref', None)
+ personref.newProp('hlink', '_i0001')
+ personref.newProp('rel', 'Neighbour')
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ person = ctxt.xpathEval("//g:person[@handle='_i0000']")[0]
+ altname = person.newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 1')
+ attr = person.newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0001')
+ personref = person.newChild(None, 'personref', None)
+ personref.newProp('hlink', '_i0000')
+ personref.newProp('rel', 'Neighbour')
+ person = ctxt.xpathEval("//g:person[@handle='_i0001']")[0]
+ person.unlinkNode()
+ person.freeNode()
+ self.do_test('I0000', 'I0001', self.basedoc, expect)
+
+#-------------------------------------------------------------------------
+#
+# ParentFamilyPesronCheck class
+#
+#-------------------------------------------------------------------------
+class ParentFamilyPersonCheck(BaseMergeCheck):
+ def setUp(self):
+ self.base_setup()
+ base_str = """
+
+
+ M
+
+ Person 0
+
+
+
+
+ M
+
+ Person 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """
+ self.basedoc = libxml2.readDoc(self.base_str + base_str, '', None,
+ libxml2.XML_PARSE_NONET)
+
+ def test_person_merge(self):
+ """Merge two persons that are children in some family"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ childref = ctxt.xpathEval("//g:family[@handle='_f0001']/g:childref")[0]
+ childref.setProp('hlink', '_i0000')
+
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[0].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 1')
+ attr = persons[0].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0001')
+ childof = ctxt.xpathEval("//g:person[@handle='_i0000']/g:childof")[0]
+ attr.addNextSibling(childof) # restore order of elements
+ childof = persons[0].newChild(None, 'childof', None)
+ childof.newProp('hlink', '_f0001')
+ persons[1].unlinkNode()
+ persons[1].freeNode()
+ self.do_test('I0000', 'I0001', self.basedoc, expect)
+
+#-------------------------------------------------------------------------
+#
+# FamilyPersonCheck class
+#
+#-------------------------------------------------------------------------
+class FamilyPersonCheck(BaseMergeCheck):
+ """Merge two persons that are parents in families"""
+ def setUp(self):
+ self.base_setup()
+ base_str = """
+
+
+ M
+
+ Person 0
+
+
+
+
+ F
+
+ Person 1
+
+
+
+
+ M
+
+ Person 2
+
+
+
+ F
+
+ Person 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """
+ self.basedoc = libxml2.readDoc(self.base_str + base_str, '', None,
+ libxml2.XML_PARSE_NONET)
+
+ def test_titanic_no_fam(self):
+ "Test merge of two persons where titanic is not a parent in a family"
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[0].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 2')
+ attr = persons[0].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0002')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[2].unlinkNode()
+ persons[2].freeNode()
+ self.do_test('I0000', 'I0002', self.basedoc, expect)
+
+ def test_no_fam_merge(self):
+ """Test merge of two persons, both parents in a family, but such that
+ the families will not merge."""
+ with XpathContext(self.basedoc) as input_ctxt:
+ person = input_ctxt.xpathEval("//g:person[@handle='_i0002']")[0]
+ parentin = person.newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0001')
+ family = input_ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ father = family.newChild(None, 'father', None)
+ father.newProp('hlink', '_i0002')
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[0].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 2')
+ attr = persons[0].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0002')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ parentin = persons[0].newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0001')
+ father = ctxt.xpathEval("//g:family[@handle='_f0001']/g:father")[0]
+ father.setProp('hlink', '_i0000')
+ persons[2].unlinkNode()
+ persons[2].freeNode()
+ self.do_test('I0000', 'I0002', self.basedoc, expect)
+
+ def test_multi_rel(self):
+ """Merge two persons where titanic has multiple family relationships
+ with his partner, this should raise an error."""
+ with XpathContext(self.basedoc) as input_ctxt:
+ persons = input_ctxt.xpathEval("//g:person")
+ parentin = persons[2].newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0001')
+ parentin = persons[3].newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0001')
+ parentin = persons[2].newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0002')
+ parentin = persons[3].newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0002')
+ family = input_ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ father = family.newChild(None, 'father', None)
+ father.newProp('hlink', '_i0002')
+ mother = family.newChild(None, 'mother', None)
+ mother.newProp('hlink', '_i0003')
+ families = input_ctxt.xpathEval("//g:families")[0]
+ family = families.newChild(None, 'family', None)
+ family.newProp('handle', '_f0002')
+ family.newProp('id', 'F0002')
+ rel = family.newChild(None, 'rel', None)
+ rel.newProp('type', 'Married')
+ father = family.newChild(None, 'father', None)
+ father.newProp('hlink', '_i0002')
+ mother = family.newChild(None, 'mother', None)
+ mother.newProp('hlink', '_i0003')
+ with CopiedDoc(self.basedoc) as expect:
+ self.do_test('I0000', 'I0002', self.basedoc, expect,
+ test_error_str=_("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."))
+
+ def test_merge_fam(self):
+ """Merge two persons such that also the families in which they are
+ parents get merged."""
+ with XpathContext(self.basedoc) as input_ctxt:
+ persons = input_ctxt.xpathEval("//g:person")
+ parentin = persons[1].newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0001')
+ parentin = persons[2].newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0001')
+ family = input_ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ father = family.newChild(None, 'father', None)
+ father.newProp('hlink', '_i0002')
+ mother = family.newChild(None, 'mother', None)
+ mother.newProp('hlink', '_i0001')
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[0].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 2')
+ attr = persons[0].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0002')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[2].unlinkNode()
+ persons[2].freeNode()
+ family = ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ family.unlinkNode()
+ family.freeNode()
+ parentin = ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[1]
+ parentin.unlinkNode()
+ parentin.freeNode()
+ self.do_test('I0000', 'I0002', self.basedoc, expect)
+
+ def test_fam_none_merge(self):
+ """Merge two persons, both father in families without mothers."""
+ with XpathContext(self.basedoc) as input_ctxt:
+ parentin = input_ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[0]
+ parentin.unlinkNode()
+ parentin.freeNode()
+ mother = input_ctxt.xpathEval("//g:family[@handle='_f0000']/g:mother")[0]
+ mother.unlinkNode()
+ mother.freeNode()
+ family = input_ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ father = family.newChild(None, 'father', None)
+ father.newProp('hlink', '_i0002')
+ person = input_ctxt.xpathEval("//g:person[@handle='_i0002']")[0]
+ parentin = person.newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0001')
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[0].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 2')
+ attr = persons[0].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0002')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[2].unlinkNode()
+ persons[2].freeNode()
+ family = ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ family.unlinkNode()
+ family.freeNode()
+ self.do_test('I0000', 'I0002', self.basedoc, expect)
+
+ # Can't think of a testcase that would merge multiple families.
+
+ def test_fam_mother_merge(self):
+ """Merge two persons that are mothers in their respective families."""
+ with XpathContext(self.basedoc) as input_ctxt:
+ persons = input_ctxt.xpathEval("//g:person")
+ parentin = persons[0].newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0001')
+ parentin = persons[3].newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0001')
+ family = input_ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ father = family.newChild(None, 'father', None)
+ father.newProp('hlink', '_i0000')
+ mother = family.newChild(None, 'mother', None)
+ mother.newProp('hlink', '_i0003')
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[1].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 3')
+ attr = persons[1].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0003')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[3].unlinkNode()
+ persons[3].freeNode()
+ family = ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ family.unlinkNode()
+ family.freeNode()
+ parentin = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[1]
+ parentin.unlinkNode()
+ parentin.freeNode()
+ self.do_test('I0001', 'I0003', self.basedoc, expect)
+
+ def test_childref_notyet(self):
+ """Merge two people leading to merger of families that have children."""
+ with XpathContext(self.basedoc) as input_ctxt:
+ parentin = input_ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[0]
+ parentin.unlinkNode()
+ parentin.freeNode()
+ mother = input_ctxt.xpathEval("//g:family[@handle='_f0000']/g:mother")[0]
+ mother.unlinkNode()
+ mother.freeNode()
+ persons = input_ctxt.xpathEval("//g:person")
+ childof = persons[1].newChild(None, 'childof', None)
+ childof.newProp('hlink', '_f0000')
+ families = input_ctxt.xpathEval("//g:family")
+ childref = families[0].newChild(None, 'childref', None)
+ childref.newProp('hlink', '_i0001')
+ parentin = persons[2].newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0001')
+ father = families[1].newChild(None, 'father', None)
+ father.newProp('hlink', '_i0002')
+ childof = persons[3].newChild(None, 'childof', None)
+ childof.newProp('hlink', '_f0001')
+ childref = families[1].newChild(None, 'childref', None)
+ childref.newProp('hlink', '_i0003')
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[0].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 2')
+ attr = persons[0].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0002')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[2].unlinkNode()
+ persons[2].freeNode()
+ families = ctxt.xpathEval("//g:family")
+ families[1].unlinkNode()
+ families[1].freeNode()
+ childof = ctxt.xpathEval("//g:person[@handle='_i0003']/g:childof")[0]
+ childof.setProp('hlink', '_f0000')
+ childref = families[0].newChild(None, 'childref', None)
+ childref.newProp('hlink', '_i0003')
+ self.do_test('I0000', 'I0002', self.basedoc, expect)
+
+ def test_childref_already(self):
+ with XpathContext(self.basedoc) as input_ctxt:
+ parentin = input_ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[0]
+ parentin.unlinkNode()
+ parentin.freeNode()
+ mother = input_ctxt.xpathEval("//g:family[@handle='_f0000']/g:mother")[0]
+ mother.unlinkNode()
+ mother.freeNode()
+ persons = input_ctxt.xpathEval("//g:person")
+ childof = persons[1].newChild(None, 'childof', None)
+ childof.newProp('hlink', '_f0000')
+ childof = persons[1].newChild(None, 'childof', None)
+ childof.newProp('hlink', '_f0001')
+ families = input_ctxt.xpathEval("//g:family")
+ childref = families[0].newChild(None, 'childref', None)
+ childref.newProp('hlink', '_i0001')
+ parentin = persons[2].newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0001')
+ father = families[1].newChild(None, 'father', None)
+ father.newProp('hlink', '_i0002')
+ childref = families[1].newChild(None, 'childref', None)
+ childref.newProp('hlink', '_i0001')
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[0].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 2')
+ attr = persons[0].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0002')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[2].unlinkNode()
+ persons[2].freeNode()
+ families = ctxt.xpathEval("//g:family")
+ families[1].unlinkNode()
+ families[1].freeNode()
+ childof = ctxt.xpathEval("//g:person[@handle='_i0001']/g:childof")
+ childof[1].unlinkNode()
+ childof[1].freeNode()
+ self.do_test('I0000', 'I0002', self.basedoc, expect)
+
+ def test_ldsord(self):
+ with XpathContext(self.basedoc) as input_ctxt:
+ parentin = input_ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[0]
+ parentin.unlinkNode()
+ parentin.freeNode()
+ mother = input_ctxt.xpathEval("//g:family[@handle='_f0000']/g:mother")[0]
+ mother.unlinkNode()
+ mother.freeNode()
+ persons = input_ctxt.xpathEval("//g:person")
+ parentin = persons[2].newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0001')
+ family = input_ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ father = family.newChild(None, 'father', None)
+ father.newProp('hlink', '_i0002')
+ ldsord = persons[3].newChild(None, 'lds_ord', None)
+ ldsord.newProp('type', 'sealed_to_parents')
+ sealedto = ldsord.newChild(None, 'sealed_to', None)
+ sealedto.newProp('hlink', '_f0001')
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[0].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 2')
+ attr = persons[0].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0002')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[2].unlinkNode()
+ persons[2].freeNode()
+ families = ctxt.xpathEval("//g:family")
+ families[1].unlinkNode()
+ families[1].freeNode()
+ sealedto = ctxt.xpathEval("//g:sealed_to")[0]
+ sealedto.setProp('hlink', '_f0000')
+ self.do_test('I0000', 'I0002', self.basedoc, expect)
+
+ # This test fails because the assigment of family ids shifts F0000 to F0001
+ # and F0001 to F0002!
+ #def test_ldsord_cross(self):
+ # with XpathContext(self.basedoc) as input_ctxt:
+ # parentin = input_ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[0]
+ # parentin.unlinkNode()
+ # parentin.freeNode()
+ # mother = input_ctxt.xpathEval("//g:family[@handle='_f0000']/g:mother")[0]
+ # mother.unlinkNode()
+ # mother.freeNode()
+ # persons = input_ctxt.xpathEval("//g:person")
+ # parentin = persons[2].newChild(None, 'parentin', None)
+ # parentin.newProp('hlink', '_f0001')
+ # family = input_ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ # father = family.newChild(None, 'father', None)
+ # father.newProp('hlink', '_i0002')
+ # ldsord = persons[0].newChild(None, 'lds_ord', None)
+ # ldsord.newProp('type', 'sealed_to_parents')
+ # sealedto = ldsord.newChild(None, 'sealed_to', None)
+ # sealedto.newProp('hlink', '_f0001')
+ # with CopiedDoc(self.basedoc) as expect:
+ # with XpathContext(expect) as ctxt:
+ # persons = ctxt.xpathEval("//g:person")
+ # altname = persons[0].newChild(None, 'name', None)
+ # altname.newProp('alt', '1')
+ # altname.newProp('type', 'Birth Name')
+ # altname.newChild(None, 'surname', 'Person 2')
+ # ldsord = ctxt.xpathEval("//g:lds_ord")[0]
+ # altname.addNextSibling(ldsord) # restore order of elements
+ # attr = persons[0].newChild(None, 'attribute', None)
+ # attr.newProp('type', 'Merged Gramps ID')
+ # attr.newProp('value', 'I0002')
+ # parentref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ # attr.addNextSibling(parentref) # restore order of elements
+ # persons[2].unlinkNode()
+ # persons[2].freeNode()
+ # families = ctxt.xpathEval("//g:family")
+ # families[1].unlinkNode()
+ # families[1].freeNode()
+ # sealedto = ctxt.xpathEval("//g:sealed_to")[0]
+ # sealedto.setProp('hlink', '_f0000')
+ # self.do_test('I0000', 'I0002', self.basedoc, expect)
+
+ def test_ldsord_self(self):
+ with XpathContext(self.basedoc) as input_ctxt:
+ parentin = input_ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[0]
+ parentin.unlinkNode()
+ parentin.freeNode()
+ mother = input_ctxt.xpathEval("//g:family[@handle='_f0000']/g:mother")[0]
+ mother.unlinkNode()
+ mother.freeNode()
+ persons = input_ctxt.xpathEval("//g:person")
+ parentin = persons[2].newChild(None, 'parentin', None)
+ parentin.newProp('hlink', '_f0001')
+ family = input_ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ father = family.newChild(None, 'father', None)
+ father.newProp('hlink', '_i0002')
+ ldsord = persons[2].newChild(None, 'lds_ord', None)
+ ldsord.newProp('type', 'sealed_to_parents')
+ sealedto = ldsord.newChild(None, 'sealed_to', None)
+ sealedto.newProp('hlink', '_f0001')
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[0].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 2')
+ ldsord = ctxt.xpathEval("//g:lds_ord")[0]
+ altname.addNextSibling(ldsord) # restore order of elements
+ attr = persons[0].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0002')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[2].unlinkNode()
+ persons[2].freeNode()
+ families = ctxt.xpathEval("//g:family")
+ families[1].unlinkNode()
+ families[1].freeNode()
+ sealedto = ctxt.xpathEval("//g:sealed_to")[0]
+ sealedto.setProp('hlink', '_f0000')
+ self.do_test('I0000', 'I0002', self.basedoc, expect)
+
+#-------------------------------------------------------------------------
+#
+# FamilyMergeCheck class
+#
+#-------------------------------------------------------------------------
+class FamilyMergeCheck(BaseMergeCheck):
+ def setUp(self):
+ self.base_setup()
+ base_str = """
+
+
+ M
+
+ Person 0
+
+
+
+
+ F
+
+ Person 1
+
+
+
+
+ M
+
+ Person 2
+
+
+
+
+ F
+
+ Person 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """
+ self.basedoc = libxml2.readDoc(self.base_str + base_str, '', None,
+ libxml2.XML_PARSE_NONET)
+
+ def test_father_son_merge(self):
+ """Merge two families where the fathers have a father-son relationship
+ so that an error is raised."""
+ with XpathContext(self.basedoc) as input_ctxt:
+ person = input_ctxt.xpathEval("//g:person[@handle='_i0002']")[0]
+ childof = person.newChild(None, 'childof', None)
+ childof.newProp('hlink', '_f0000')
+ family = input_ctxt.xpathEval("//g:family[@handle='_f0000']")[0]
+ childref = family.newChild(None, 'childref', None)
+ childref.newProp('hlink', '_i0002')
+ with CopiedDoc(self.basedoc) as expect:
+ self.do_family_test('F0000', 'F0001', 'i0000', 'i0001',
+ self.basedoc, expect, test_error_str=_("A parent and "
+ "child cannot be merged. To merge these people, you "
+ "must first break the relationship between them."))
+
+ def test_child_parent_merge_no_father(self):
+ """Merge two families where the phoenix family has no father and
+ the father of the titanic family is a child of the phoenix family."""
+ with XpathContext(self.basedoc) as input_ctxt:
+ parentin = input_ctxt.xpathEval("//g:person[@handle='_i0002']/g:parentin")[0]
+ parentin.unlinkNode()
+ parentin.freeNode()
+ father = input_ctxt.xpathEval("//g:family[@handle='_f0001']/g:father")[0]
+ father.unlinkNode()
+ father.freeNode()
+ person = input_ctxt.xpathEval("//g:person[@handle='_i0000']")[0]
+ childof = person.newChild(None, 'childof', None)
+ childof.newProp('hlink', '_f0001')
+ family = input_ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ childref = family.newChild(None, 'childref', None)
+ childref.newProp('hlink', '_i0000')
+ with CopiedDoc(self.basedoc) as expect:
+ self.do_family_test('F0000', 'F0001', 'i0000', 'i0001',
+ self.basedoc, expect, test_error_str=_("A parent and "
+ "child cannot be merged. To merge these people, you "
+ "must first break the relationship between them."))
+
+ def test_child_parent_merge_no_father_swapped(self):
+ """Merge two families where the phoenix family has no father and
+ the father of the titanic family, which is the phoenix-father, is a
+ child of the phoenix family."""
+ with XpathContext(self.basedoc) as input_ctxt:
+ parentin = input_ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ parentin.unlinkNode()
+ parentin.freeNode()
+ father = input_ctxt.xpathEval("//g:family[@handle='_f0000']/g:father")[0]
+ father.unlinkNode()
+ father.freeNode()
+ person = input_ctxt.xpathEval("//g:person[@handle='_i0002']")[0]
+ childof = person.newChild(None, 'childof', None)
+ childof.newProp('hlink', '_f0000')
+ family = input_ctxt.xpathEval("//g:family[@handle='_f0000']")[0]
+ childref = family.newChild(None, 'childref', None)
+ childref.newProp('hlink', '_i0002')
+ with CopiedDoc(self.basedoc) as expect:
+ self.do_family_test('F0000', 'F0001', 'i0002', 'i0001',
+ self.basedoc, expect, test_error_str=_("A parent and "
+ "child cannot be merged. To merge these people, you "
+ "must first break the relationship between them."))
+
+ def test_regular_merge(self):
+ """Merge two families succesfully"""
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[0].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 2')
+ attr = persons[0].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0002')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[2].unlinkNode()
+ persons[2].freeNode()
+ altname = persons[1].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 3')
+ attr = persons[1].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0003')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[3].unlinkNode()
+ persons[3].freeNode()
+ family = ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ family.unlinkNode()
+ family.freeNode()
+ self.do_family_test('F0000', 'F0001', 'i0000', 'i0001', self.basedoc, expect)
+
+ def test_father_swapped(self):
+ "Merge two families where the phoenix-father is of the titanic family."
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[2].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 0')
+ attr = persons[2].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0000')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0002']/g:parentin")[0]
+ parentref.setProp('hlink', '_f0000')
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[0].unlinkNode()
+ persons[0].freeNode()
+ altname = persons[1].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 3')
+ attr = persons[1].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0003')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[3].unlinkNode()
+ persons[3].freeNode()
+ family = ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ family.unlinkNode()
+ family.freeNode()
+ father = ctxt.xpathEval("//g:family[@handle='_f0000']/g:father")[0]
+ father.setProp('hlink', '_i0002')
+ self.do_family_test('F0000', 'F0001', 'i0002', 'i0001', self.basedoc, expect)
+
+ #def test_mother_swapped(self):
+
+ def test_no_father(self):
+ """Merge two families, where one family has not father"""
+ with XpathContext(self.basedoc) as input_ctxt:
+ parentin = input_ctxt.xpathEval("//g:person[@handle='_i0002']/g:parentin")[0]
+ parentin.unlinkNode()
+ parentin.freeNode()
+ father = input_ctxt.xpathEval("//g:family[@handle='_f0001']/g:father")[0]
+ father.unlinkNode()
+ father.freeNode()
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[1].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 3')
+ attr = persons[1].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0003')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[3].unlinkNode()
+ persons[3].freeNode()
+ family = ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ family.unlinkNode()
+ family.freeNode()
+ self.do_family_test('F0000', 'F0001', 'i0000', 'i0001',
+ self.basedoc, expect)
+
+ def test_no_mother_swapped(self):
+ """Merge two families where one family has no mother and the
+ phoenix-mother is from the titanic family."""
+ with XpathContext(self.basedoc) as input_ctxt:
+ parentin = input_ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[0]
+ parentin.unlinkNode()
+ parentin.freeNode()
+ mother = input_ctxt.xpathEval("//g:family[@handle='_f0000']/g:mother")[0]
+ mother.unlinkNode()
+ mother.freeNode()
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[0].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 2')
+ attr = persons[0].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0002')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[2].unlinkNode()
+ persons[2].freeNode()
+ parentin = ctxt.xpathEval("//g:person[@handle='_i0003']/g:parentin")[0]
+ parentin.setProp('hlink', '_f0000')
+ family = ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ family.unlinkNode()
+ family.freeNode()
+ family = ctxt.xpathEval("//g:family[@handle='_f0000']")[0]
+ mother = family.newChild(None, 'mother', None)
+ mother.newProp('hlink', '_i0003')
+ self.do_family_test('F0000', 'F0001', 'i0000', 'i0003',
+ self.basedoc, expect)
+
+ #def test_no_parents(self):
+
+ def test_childref_notyet(self):
+ """Merge two families with non-duplicate child references."""
+ with XpathContext(self.basedoc) as input_ctxt:
+ people = input_ctxt.xpathEval("//g:people")[0]
+ person = people.newChild(None, 'person', None)
+ person.newProp('handle', '_i0004')
+ person.newProp('id', '_I0004')
+ person.newChild(None, 'gender', 'M')
+ name = person.newChild(None, 'name', None)
+ name.newProp('type', 'Birth Name')
+ name.newChild(None, 'surname', 'Person 4')
+ childof = person.newChild(None, 'childof', None)
+ childof.newProp('hlink', '_f0001')
+ family = input_ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ childref = family.newChild(None, 'childref', None)
+ childref.newProp('hlink', '_i0004')
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[0].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 2')
+ attr = persons[0].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0002')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[2].unlinkNode()
+ persons[2].freeNode()
+ altname = persons[1].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 3')
+ attr = persons[1].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0003')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[3].unlinkNode()
+ persons[3].freeNode()
+ family = ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ family.unlinkNode()
+ family.freeNode()
+ childof = ctxt.xpathEval("//g:person[@handle='_i0004']/g:childof")[0]
+ childof.setProp('hlink', '_f0000')
+ family = ctxt.xpathEval("//g:family[@handle='_f0000']")[0]
+ childref = family.newChild(None, 'childref', None)
+ childref.newProp('hlink', '_i0004')
+ self.do_family_test('F0000', 'F0001', 'i0000', 'i0001',
+ self.basedoc, expect)
+
+ def test_childref_already(self):
+ """Merge two families with duplicate child references."""
+ with XpathContext(self.basedoc) as input_ctxt:
+ people = input_ctxt.xpathEval("//g:people")[0]
+ person = people.newChild(None, 'person', None)
+ person.newProp('handle', '_i0004')
+ person.newProp('id', '_I0004')
+ person.newChild(None, 'gender', 'M')
+ name = person.newChild(None, 'name', None)
+ name.newProp('type', 'Birth Name')
+ name.newChild(None, 'surname', 'Person 4')
+ childof = person.newChild(None, 'childof', None)
+ childof.newProp('hlink', '_f0000')
+ childof = person.newChild(None, 'childof', None)
+ childof.newProp('hlink', '_f0001')
+ family = input_ctxt.xpathEval("//g:family[@handle='_f0000']")[0]
+ childref = family.newChild(None, 'childref', None)
+ childref.newProp('hlink', '_i0004')
+ family = input_ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ childref = family.newChild(None, 'childref', None)
+ childref.newProp('hlink', '_i0004')
+ with CopiedDoc(self.basedoc) as expect:
+ with XpathContext(expect) as ctxt:
+ persons = ctxt.xpathEval("//g:person")
+ altname = persons[0].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 2')
+ attr = persons[0].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0002')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[2].unlinkNode()
+ persons[2].freeNode()
+ altname = persons[1].newChild(None, 'name', None)
+ altname.newProp('alt', '1')
+ altname.newProp('type', 'Birth Name')
+ altname.newChild(None, 'surname', 'Person 3')
+ attr = persons[1].newChild(None, 'attribute', None)
+ attr.newProp('type', 'Merged Gramps ID')
+ attr.newProp('value', 'I0003')
+ parentref = ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[0]
+ attr.addNextSibling(parentref) # restore order of elements
+ persons[3].unlinkNode()
+ persons[3].freeNode()
+ family = ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ family.unlinkNode()
+ family.freeNode()
+ childof = ctxt.xpathEval("//g:person[@handle='_i0004']/g:childof")[1]
+ childof.unlinkNode()
+ childof.freeNode()
+ self.do_family_test('F0000', 'F0001', 'i0000', 'i0001',
+ self.basedoc, expect)
+
+ # this test fails because the families get IDs F0001 and F0002!
+ #def test_ldsord(self):
+ # """Merge two families where one person has a reference to the
+ # titanic family."""
+ # with XpathContext(self.basedoc) as input_ctxt:
+ # person = input_ctxt.xpathEval("//g:person[@handle='_i0000']")[0]
+ # ldsord = person.newChild(None, 'lds_ord', None)
+ # ldsord.newProp('type', 'sealed_to_parents')
+ # sealedto = ldsord.newChild(None, 'sealed_to', None)
+ # sealedto.newProp('hlink', '_f0001')
+ # parentin = input_ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ # ldsord.addNextSibling(parentin)
+ # with CopiedDoc(self.basedoc) as expect:
+ # with XpathContext(expect) as ctxt:
+ # persons = ctxt.xpathEval("//g:person")
+ # altname = persons[0].newChild(None, 'name', None)
+ # altname.newProp('alt', '1')
+ # altname.newProp('type', 'Birth Name')
+ # altname.newChild(None, 'surname', 'Person 2')
+ # ldsord = ctxt.xpathEval("//g:lds_ord")[0]
+ # altname.addNextSibling(ldsord) # restore order of elements
+ # attr = persons[0].newChild(None, 'attribute', None)
+ # attr.newProp('type', 'Merged Gramps ID')
+ # attr.newProp('value', 'I0002')
+ # parentref = ctxt.xpathEval("//g:person[@handle='_i0000']/g:parentin")[0]
+ # attr.addNextSibling(parentref) # restore order of elements
+ # persons[2].unlinkNode()
+ # persons[2].freeNode()
+ # altname = persons[1].newChild(None, 'name', None)
+ # altname.newProp('alt', '1')
+ # altname.newProp('type', 'Birth Name')
+ # altname.newChild(None, 'surname', 'Person 3')
+ # attr = persons[1].newChild(None, 'attribute', None)
+ # attr.newProp('type', 'Merged Gramps ID')
+ # attr.newProp('value', 'I0003')
+ # parentref = ctxt.xpathEval("//g:person[@handle='_i0001']/g:parentin")[0]
+ # attr.addNextSibling(parentref) # restore order of elements
+ # persons[3].unlinkNode()
+ # persons[3].freeNode()
+ # family = ctxt.xpathEval("//g:family[@handle='_f0001']")[0]
+ # family.unlinkNode()
+ # family.freeNode()
+ # sealedto = ctxt.xpathEval("//g:sealed_to")[0]
+ # sealedto.setProp('hlink', '_f0000')
+ # self.do_family_test('F0000', 'F0001', 'i0000', 'i0001',
+ # self.basedoc, expect)
+
+
+if __name__ == "__main__":
+ if not os.path.isdir(os.path.join(USER_PLUGINS, 'CliMerge')):
+ print >> sys.stderr, 'This program needs the third party "CliMerge" plugin.'
+ sys.exit(1)
+ if not os.path.isdir(os.path.join(USER_PLUGINS, 'ExportRaw')):
+ print >> sys.stderr, 'This program needs the third party "ExportRaw" plugin.'
+ sys.exit(1)
+ unittest.main()
diff --git a/src/gen/lib/test/merge_test.py b/src/gen/lib/test/merge_test.py
new file mode 100644
index 000000000..04ff50934
--- /dev/null
+++ b/src/gen/lib/test/merge_test.py
@@ -0,0 +1,1840 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2011 Michiel D. Nauta
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+# $Id$
+
+""" Unittest that tests the code involved in merging """
+
+import unittest
+import sys
+import os
+sys.path.append(os.curdir)
+
+import gen.lib
+from gen.lib.const import IDENTICAL, EQUAL, DIFFERENT
+
+class PrivacyBaseTest:
+ def test_privacy_merge(self):
+ self.assertEqual(self.phoenix.serialize(), self.titanic.serialize())
+ self.titanic.set_privacy(True)
+ self.ref_obj.set_privacy(True)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+class NoteBaseTest:
+ def test_note_merge(self):
+ note_handle = '123456'
+ self.titanic.add_note(note_handle)
+ self.ref_obj.add_note(note_handle)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+class SourceBaseTest:
+ def test_source_merge(self):
+ srcref = gen.lib.SourceRef()
+ srcref.set_page('p.10')
+ self.titanic.add_source_reference(srcref)
+ self.ref_obj.add_source_reference(srcref)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+class MediaBaseTest:
+ def test_media_merge(self):
+ mediaref = gen.lib.MediaRef()
+ mediaref.set_reference_handle('123456')
+ self.titanic.add_media_reference(mediaref)
+ self.ref_obj.add_media_reference(mediaref)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+class AttrBaseTest:
+ def test_attribute_merge(self):
+ attr = gen.lib.Attribute()
+ attr.set_type(gen.lib.AttributeType.AGE)
+ attr.set_value(10)
+ self.titanic.add_attribute(attr)
+ self.ref_obj.add_attribute(attr)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+class UrlBaseTest:
+ def test_url_merge(self):
+ url = gen.lib.Url()
+ url.set_path('http://example.com')
+ self.titanic.add_url(url)
+ self.ref_obj.add_url(url)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+#===========================================================
+
+class PrivacyCheck(unittest.TestCase):
+ def test_privacy(self):
+ known_values = ( (False, False, False),
+ (True, False, True),
+ (False, True, True),
+ (True, True, True) )
+ phoenix = gen.lib.privacybase.PrivacyBase()
+ titanic = gen.lib.privacybase.PrivacyBase()
+ for value1, value2, value_merge in known_values:
+ phoenix.set_privacy(value1)
+ titanic.set_privacy(value2)
+ phoenix._merge_privacy(titanic)
+ self.assertEqual(phoenix.get_privacy(), value_merge)
+
+class UrlCheck(unittest.TestCase, PrivacyBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.Url()
+ self.phoenix.set_path('http://example1.com')
+ self.phoenix.set_description('hello world')
+ self.phoenix.set_type(gen.lib.UrlType.WEB_HOME)
+ self.titanic = gen.lib.Url(self.phoenix)
+ self.ref_obj = gen.lib.Url(self.phoenix)
+
+ def test_path_equivalence(self):
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), IDENTICAL)
+ self.titanic.set_path('http://example2.com')
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_type_equivalence(self):
+ self.titanic.set_type(gen.lib.UrlType.UNKNOWN)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_desc_equivalence(self):
+ self.titanic.set_description('goodby')
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_privacy_equivalence(self):
+ self.titanic.set_privacy(True)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), EQUAL)
+
+ def test_merge_path(self):
+ self.titanic.set_path('example2.com')
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.is_equal(self.ref_obj), True)
+
+class UrlBaseCheck(unittest.TestCase):
+ def setUp(self):
+ self.phoenix = gen.lib.urlbase.UrlBase()
+ self.titanic = gen.lib.urlbase.UrlBase()
+ url = gen.lib.Url()
+ url.set_path('example.com')
+ self.phoenix.add_url(url)
+
+ def test_identical(self):
+ ref_url_list = gen.lib.urlbase.UrlBase(self.phoenix)
+ url = gen.lib.Url()
+ url.set_path('example.com')
+ self.titanic.add_url(url)
+ self.phoenix._merge_url_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), ref_url_list.serialize())
+
+ def test_equal(self):
+ ref_url_list = gen.lib.urlbase.UrlBase(self.phoenix)
+ ref_url = ref_url_list.get_url_list()[0]
+ ref_url.set_privacy(True)
+ url = gen.lib.Url()
+ url.set_path('example.com')
+ url.set_privacy(True)
+ self.titanic.add_url(url)
+ self.phoenix._merge_url_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), ref_url_list.serialize())
+
+ def test_different(self):
+ ref_url_list = gen.lib.urlbase.UrlBase(self.phoenix)
+ url = gen.lib.Url()
+ url.set_path('other.com')
+ ref_url_list.add_url(url)
+ self.titanic.add_url(url)
+ self.phoenix._merge_url_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), ref_url_list.serialize())
+
+class AddressCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest,
+ SourceBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.Address()
+ self.phoenix.set_city('Amsterdam')
+ self.titanic = gen.lib.Address(self.phoenix)
+ self.ref_obj = gen.lib.Address(self.phoenix)
+
+ def test_location_equivalence(self):
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), IDENTICAL)
+ self.titanic.set_city('Rotterdam')
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_date_equivalence(self):
+ date = gen.lib.Date()
+ date.set_yr_mon_day(1999,12,5)
+ self.titanic.set_date_object(date)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_privacy_equivalence(self):
+ self.titanic.set_privacy(True)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), EQUAL)
+
+ def test_location_merge(self):
+ self.titanic.set_city('Rotterdam')
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.is_equal(self.ref_obj), True)
+
+class AddressBaseCheck(unittest.TestCase):
+ def setUp(self):
+ self.phoenix = gen.lib.addressbase.AddressBase()
+ self.titanic = gen.lib.addressbase.AddressBase()
+ self.ref_list = gen.lib.addressbase.AddressBase()
+ address = gen.lib.Address()
+ address.set_city('Amsterdam')
+ self.phoenix.add_address(address)
+
+ def test_identical(self):
+ address = gen.lib.Address()
+ address.set_city('Amsterdam')
+ self.ref_list.add_address(address)
+ self.titanic.add_address(address)
+ self.phoenix._merge_address_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_equal(self):
+ note_handle = '123456'
+ address = gen.lib.Address()
+ address.set_city('Amsterdam')
+ address.add_note(note_handle)
+ self.titanic.add_address(address)
+ self.ref_list.add_address(address)
+ self.phoenix._merge_address_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_different(self):
+ address = gen.lib.Address()
+ address.set_country('Netherlands')
+ self.titanic.add_address(address)
+ self.ref_list = gen.lib.addressbase.AddressBase(self.phoenix)
+ self.ref_list.add_address(address)
+ self.phoenix._merge_address_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+class AttributeCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest,
+ SourceBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.Attribute()
+ self.phoenix.set_type(gen.lib.AttributeType.AGE)
+ self.phoenix.set_value(10)
+ self.titanic = gen.lib.Attribute(self.phoenix)
+ self.ref_obj = gen.lib.Attribute(self.phoenix)
+
+ def test_type_equivalence(self):
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), IDENTICAL)
+ self.titanic.set_type(gen.lib.AttributeType.MOTHER_AGE)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_value_equivalence(self):
+ self.titanic.set_value(12)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_privacy_equivalence(self):
+ self.titanic.set_privacy(True)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), EQUAL)
+
+ def test_value_merge(self):
+ self.titanic.set_value(12)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.is_equal(self.ref_obj), True)
+
+class AttributeBaseCheck(unittest.TestCase):
+ def setUp(self):
+ self.phoenix = gen.lib.attrbase.AttributeBase()
+ self.titanic = gen.lib.attrbase.AttributeBase()
+ self.ref_list = gen.lib.attrbase.AttributeBase()
+ attr = gen.lib.Attribute()
+ attr.set_type(gen.lib.AttributeType.AGE)
+ attr.set_value(10)
+ self.phoenix.add_attribute(attr)
+
+ def test_identical(self):
+ attr = gen.lib.Attribute()
+ attr.set_type(gen.lib.AttributeType.AGE)
+ attr.set_value(10)
+ self.ref_list.add_attribute(attr)
+ self.titanic.add_attribute(attr)
+ self.phoenix._merge_attribute_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_equal(self):
+ note_handle = '123456'
+ attr = gen.lib.Attribute()
+ attr.set_type(gen.lib.AttributeType.AGE)
+ attr.set_value(10)
+ attr.add_note(note_handle)
+ self.titanic.add_attribute(attr)
+ self.ref_list.add_attribute(attr)
+ self.phoenix._merge_attribute_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_different(self):
+ attr = gen.lib.Attribute()
+ attr.set_type(gen.lib.AttributeType.AGE)
+ attr.set_value(12)
+ self.titanic.add_attribute(attr)
+ self.ref_list = gen.lib.attrbase.AttributeBase(self.phoenix)
+ self.ref_list.add_attribute(attr)
+ self.phoenix._merge_attribute_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+class ChildRefCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest,
+ SourceBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.ChildRef()
+ self.phoenix.set_reference_handle('123456')
+ self.phoenix.set_father_relation(gen.lib.ChildRefType.UNKNOWN)
+ self.phoenix.set_mother_relation(gen.lib.ChildRefType.UNKNOWN)
+ self.titanic = gen.lib.ChildRef()
+ self.titanic.set_reference_handle('123456')
+ self.titanic.set_father_relation(gen.lib.ChildRefType.UNKNOWN)
+ self.titanic.set_mother_relation(gen.lib.ChildRefType.UNKNOWN)
+ self.ref_obj = gen.lib.ChildRef()
+ self.ref_obj.set_reference_handle('123456')
+ self.ref_obj.set_father_relation(gen.lib.ChildRefType.UNKNOWN)
+ self.ref_obj.set_mother_relation(gen.lib.ChildRefType.UNKNOWN)
+
+ def test_handle_equivalence(self):
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), IDENTICAL)
+ self.titanic.set_reference_handle('654321')
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_privacy_equivalence(self):
+ self.titanic.set_privacy(True)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), EQUAL)
+
+ def test_mrel_merge(self):
+ self.titanic.set_mother_relation(gen.lib.ChildRefType.BIRTH)
+ self.ref_obj.set_mother_relation(gen.lib.ChildRefType.BIRTH)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.is_equal(self.ref_obj), True)
+
+ def test_frel_merge(self):
+ self.titanic.set_father_relation(gen.lib.ChildRefType.ADOPTED)
+ self.ref_obj.set_father_relation(gen.lib.ChildRefType.ADOPTED)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.is_equal(self.ref_obj), True)
+
+class EventCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest,
+ SourceBaseTest, MediaBaseTest, AttrBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.Event()
+ self.phoenix.set_description("hello world")
+ self.titanic = gen.lib.Event(self.phoenix)
+ self.ref_obj = gen.lib.Event(self.phoenix)
+
+class EventRefCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest,
+ AttrBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.EventRef()
+ self.phoenix.set_reference_handle('123456')
+ self.titanic = gen.lib.EventRef(self.phoenix)
+ self.ref_obj = gen.lib.EventRef(self.phoenix)
+
+ def test_handle_equivalence(self):
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), IDENTICAL)
+ self.titanic.set_reference_handle('654321')
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_role_equivalence(self):
+ self.titanic.set_role(gen.lib.EventRoleType.WITNESS)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_privacy_equivalence(self):
+ self.titanic.set_privacy(True)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), EQUAL)
+
+ def test_replace(self):
+ attr1 = gen.lib.Attribute()
+ attr1.set_type(gen.lib.AttributeType.AGE)
+ attr1.set_value(10)
+ srcref1 = gen.lib.SourceRef()
+ srcref1.set_reference_handle('123456')
+ srcref1.set_page('p.10')
+ srcref2 = gen.lib.SourceRef()
+ srcref2.set_reference_handle('234567')
+ srcref2.set_page('p.20')
+ attr1.add_source_reference(srcref1)
+ attr1.add_source_reference(srcref2)
+ attr2 = gen.lib.Attribute()
+ attr2.set_type(gen.lib.AttributeType.AGE)
+ attr2.set_value(10)
+ srcref3 = gen.lib.SourceRef()
+ srcref3.set_reference_handle('123456')
+ srcref3.set_page('p.10')
+ srcref4 = gen.lib.SourceRef()
+ srcref4.set_reference_handle('654321')
+ srcref4.set_page('p.20')
+ attr2.add_source_reference(srcref3)
+ attr2.add_source_reference(srcref4)
+ self.phoenix.add_attribute(attr1)
+ self.ref_obj.add_attribute(attr2)
+ self.phoenix.replace_source_references('234567','654321')
+ self.assert_(self.phoenix.is_equal(self.ref_obj))
+
+class FamilyCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest,
+ SourceBaseTest, MediaBaseTest, AttrBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.Family()
+ self.phoenix.set_father_handle('123456')
+ self.phoenix.set_mother_handle('654321')
+ self.phoenix.set_relationship(gen.lib.FamilyRelType.MARRIED)
+ self.titanic = gen.lib.Family()
+ self.titanic.set_father_handle('123456')
+ self.titanic.set_mother_handle('654321')
+ self.titanic.set_relationship(gen.lib.FamilyRelType.MARRIED)
+ self.ref_obj = gen.lib.Family()
+ self.ref_obj.set_father_handle('123456')
+ self.ref_obj.set_mother_handle('654321')
+ self.ref_obj.set_relationship(gen.lib.FamilyRelType.MARRIED)
+
+ def test_relation_merge(self):
+ self.phoenix.set_relationship(gen.lib.FamilyRelType.UNKNOWN)
+ self.titanic.set_relationship(gen.lib.FamilyRelType.UNMARRIED)
+ self.ref_obj.set_relationship(gen.lib.FamilyRelType.UNMARRIED)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_eventref_merge(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_role(gen.lib.EventRoleType.WITNESS)
+ self.titanic.add_event_ref(evtref)
+ self.ref_obj.add_event_ref(evtref)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_ldsord_merge(self):
+ ldsord = gen.lib.LdsOrd()
+ ldsord.set_temple('London')
+ self.titanic.add_lds_ord(ldsord)
+ self.ref_obj.add_lds_ord(ldsord)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_childref_merge(self):
+ childref = gen.lib.ChildRef()
+ childref.set_reference_handle('123456')
+ self.titanic.add_child_ref(childref)
+ self.ref_obj.add_child_ref(childref)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_mergechildref_identical(self):
+ childref1 = gen.lib.ChildRef()
+ childref1.set_reference_handle('123456')
+ childref2 = gen.lib.ChildRef()
+ childref2.set_reference_handle('123456')
+ childref3 = gen.lib.ChildRef()
+ childref3.set_reference_handle('123456')
+ self.phoenix.add_child_ref(childref1)
+ self.titanic.add_child_ref(childref2)
+ self.ref_obj.add_child_ref(childref3)
+ self.phoenix._merge_child_ref_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_mergechildref_equal(self):
+ childref1 = gen.lib.ChildRef()
+ childref1.set_reference_handle('123456')
+ childref2 = gen.lib.ChildRef()
+ childref2.set_reference_handle('123456')
+ childref2.add_note('N1')
+ childref3 = gen.lib.ChildRef()
+ childref3.set_reference_handle('123456')
+ childref3.add_note('N1')
+ self.phoenix.add_child_ref(childref1)
+ self.titanic.add_child_ref(childref2)
+ self.ref_obj.add_child_ref(childref3)
+ self.phoenix._merge_child_ref_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_mergechildref_different(self):
+ childref1 = gen.lib.ChildRef()
+ childref1.set_reference_handle('123456')
+ childref2 = gen.lib.ChildRef()
+ childref2.set_reference_handle('654321')
+ childref3 = gen.lib.ChildRef()
+ childref3.set_reference_handle('123456')
+ childref4 = gen.lib.ChildRef()
+ childref4.set_reference_handle('654321')
+ self.phoenix.add_child_ref(childref1)
+ self.titanic.add_child_ref(childref2)
+ self.ref_obj.add_child_ref(childref3)
+ self.ref_obj.add_child_ref(childref4)
+ self.phoenix._merge_child_ref_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_childref_absent(self):
+ childref1 = gen.lib.ChildRef()
+ childref1.set_reference_handle('234567')
+ childref2 = gen.lib.ChildRef()
+ childref2.set_reference_handle('345678')
+ childref3 = gen.lib.ChildRef()
+ childref3.set_reference_handle('765432')
+ childref4 = gen.lib.ChildRef()
+ childref4.set_reference_handle('345678')
+ self.phoenix.add_child_ref(childref1)
+ self.phoenix.add_child_ref(childref2)
+ self.ref_obj.add_child_ref(childref3)
+ self.ref_obj.add_child_ref(childref4)
+ self.phoenix.replace_handle_reference('Person', '234567', '765432')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_childref_identical(self):
+ childref1 = gen.lib.ChildRef()
+ childref1.set_reference_handle('234567')
+ childref2 = gen.lib.ChildRef()
+ childref2.set_reference_handle('765432')
+ childref3 = gen.lib.ChildRef()
+ childref3.set_reference_handle('765432')
+ self.phoenix.add_child_ref(childref1)
+ self.phoenix.add_child_ref(childref2)
+ self.ref_obj.add_child_ref(childref3)
+ self.phoenix.replace_handle_reference('Person', '234567', '765432')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_childref_equal(self):
+ childref1 = gen.lib.ChildRef()
+ childref1.set_reference_handle('234567')
+ childref1.set_privacy(True)
+ childref2 = gen.lib.ChildRef()
+ childref2.set_reference_handle('765432')
+ childref3 = gen.lib.ChildRef()
+ childref3.set_reference_handle('765432')
+ childref3.set_privacy(True)
+ self.phoenix.add_child_ref(childref1)
+ self.phoenix.add_child_ref(childref2)
+ self.ref_obj.add_child_ref(childref3)
+ self.phoenix.replace_handle_reference('Person', '234567', '765432')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_childref_different(self):
+ # impossible, is_equivalent is only DIFFERENT if handles differ.
+ childref1 = gen.lib.ChildRef()
+ childref1.set_reference_handle('234567')
+ childref1.set_mother_relation('Adopted')
+ childref2 = gen.lib.ChildRef()
+ childref2.set_reference_handle('765432')
+ childref3 = gen.lib.ChildRef()
+ childref3.set_reference_handle('765432')
+ self.phoenix.add_child_ref(childref1)
+ self.phoenix.add_child_ref(childref2)
+ self.ref_obj.add_child_ref(childref3)
+ self.phoenix.replace_handle_reference('Person', '234567', '765432')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_mergeeventref_identical(self):
+ eventref1 = gen.lib.EventRef()
+ eventref1.set_role(gen.lib.EventRoleType.WITNESS)
+ eventref2 = gen.lib.EventRef()
+ eventref2.set_role(gen.lib.EventRoleType.WITNESS)
+ eventref3 = gen.lib.EventRef()
+ eventref3.set_role(gen.lib.EventRoleType.WITNESS)
+ self.phoenix.add_event_ref(eventref1)
+ self.titanic.add_event_ref(eventref2)
+ self.ref_obj.add_event_ref(eventref3)
+ self.phoenix._merge_event_ref_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_mergeeventref_equal(self):
+ eventref1 = gen.lib.EventRef()
+ eventref1.set_role(gen.lib.EventRoleType.WITNESS)
+ eventref2 = gen.lib.EventRef()
+ eventref2.set_role(gen.lib.EventRoleType.WITNESS)
+ eventref2.add_note('N1')
+ eventref3 = gen.lib.EventRef()
+ eventref3.set_role(gen.lib.EventRoleType.WITNESS)
+ eventref3.add_note('N1')
+ self.phoenix.add_event_ref(eventref1)
+ self.titanic.add_event_ref(eventref2)
+ self.ref_obj.add_event_ref(eventref3)
+ self.phoenix._merge_event_ref_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_mergeeventref_different(self):
+ eventref1 = gen.lib.EventRef()
+ eventref1.set_role(gen.lib.EventRoleType.WITNESS)
+ eventref2 = gen.lib.EventRef()
+ eventref2.set_role(gen.lib.EventRoleType.CLERGY)
+ eventref3 = gen.lib.EventRef()
+ eventref3.set_role(gen.lib.EventRoleType.WITNESS)
+ eventref4 = gen.lib.EventRef()
+ eventref4.set_role(gen.lib.EventRoleType.CLERGY)
+ self.phoenix.add_event_ref(eventref1)
+ self.titanic.add_event_ref(eventref2)
+ self.ref_obj.add_event_ref(eventref3)
+ self.ref_obj.add_event_ref(eventref4)
+ self.phoenix._merge_event_ref_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_event_absent(self):
+ eventref1 = gen.lib.EventRef()
+ eventref1.set_reference_handle('123456')
+ eventref2 = gen.lib.EventRef()
+ eventref2.set_reference_handle('234567')
+ eventref3 = gen.lib.EventRef()
+ eventref3.set_reference_handle('654321')
+ eventref4 = gen.lib.EventRef()
+ eventref4.set_reference_handle('234567')
+ self.phoenix.add_event_ref(eventref1)
+ self.phoenix.add_event_ref(eventref2)
+ self.ref_obj.add_event_ref(eventref3)
+ self.ref_obj.add_event_ref(eventref4)
+ self.phoenix.replace_handle_reference('Event', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_event_identical(self):
+ eventref1 = gen.lib.EventRef()
+ eventref1.set_reference_handle('123456')
+ eventref2 = gen.lib.EventRef()
+ eventref2.set_reference_handle('654321')
+ eventref3 = gen.lib.EventRef()
+ eventref3.set_reference_handle('654321')
+ self.phoenix.add_event_ref(eventref1)
+ self.phoenix.add_event_ref(eventref2)
+ self.ref_obj.add_event_ref(eventref3)
+ self.phoenix.replace_handle_reference('Event', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_event_equal(self):
+ eventref1 = gen.lib.EventRef()
+ eventref1.set_reference_handle('123456')
+ eventref1.set_privacy(True)
+ eventref2 = gen.lib.EventRef()
+ eventref2.set_reference_handle('654321')
+ eventref3 = gen.lib.EventRef()
+ eventref3.set_reference_handle('654321')
+ eventref3.set_privacy(True)
+ self.phoenix.add_event_ref(eventref1)
+ self.phoenix.add_event_ref(eventref2)
+ self.ref_obj.add_event_ref(eventref3)
+ self.phoenix.replace_handle_reference('Event', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_event_different(self):
+ eventref1 = gen.lib.EventRef()
+ eventref1.set_reference_handle('123456')
+ eventref1.set_role(gen.lib.EventRoleType.WITNESS)
+ eventref2 = gen.lib.EventRef()
+ eventref2.set_reference_handle('654321')
+ eventref3 = gen.lib.EventRef()
+ eventref3.set_reference_handle('654321')
+ eventref3.set_role(gen.lib.EventRoleType.WITNESS)
+ eventref4 = gen.lib.EventRef()
+ eventref4.set_reference_handle('654321')
+ self.phoenix.add_event_ref(eventref1)
+ self.phoenix.add_event_ref(eventref2)
+ self.ref_obj.add_event_ref(eventref3)
+ self.ref_obj.add_event_ref(eventref4)
+ self.phoenix.replace_handle_reference('Event', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_event_order_first(self):
+ eventref1 = gen.lib.EventRef()
+ eventref1.set_reference_handle('123456')
+ eventref2 = gen.lib.EventRef()
+ eventref2.set_reference_handle('234567')
+ eventref3 = gen.lib.EventRef()
+ eventref3.set_reference_handle('654321')
+ eventref4 = gen.lib.EventRef()
+ eventref4.set_reference_handle('123456')
+ eventref5 = gen.lib.EventRef()
+ eventref5.set_reference_handle('234567')
+ self.phoenix.add_event_ref(eventref1)
+ self.phoenix.add_event_ref(eventref2)
+ self.phoenix.add_event_ref(eventref3)
+ self.ref_obj.add_event_ref(eventref4)
+ self.ref_obj.add_event_ref(eventref5)
+ self.phoenix.replace_handle_reference('Event', '654321', '123456')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_event_order_last(self):
+ eventref1 = gen.lib.EventRef()
+ eventref1.set_reference_handle('123456')
+ eventref2 = gen.lib.EventRef()
+ eventref2.set_reference_handle('234567')
+ eventref3 = gen.lib.EventRef()
+ eventref3.set_reference_handle('654321')
+ eventref4 = gen.lib.EventRef()
+ eventref4.set_reference_handle('234567')
+ eventref5 = gen.lib.EventRef()
+ eventref5.set_reference_handle('654321')
+ self.phoenix.add_event_ref(eventref1)
+ self.phoenix.add_event_ref(eventref2)
+ self.phoenix.add_event_ref(eventref3)
+ self.ref_obj.add_event_ref(eventref4)
+ self.ref_obj.add_event_ref(eventref5)
+ self.phoenix.replace_handle_reference('Event', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+
+class LdsordCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest,
+ SourceBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.LdsOrd()
+ self.phoenix.set_temple('London, England')
+ self.titanic = gen.lib.LdsOrd(self.phoenix)
+ self.ref_obj = gen.lib.LdsOrd(self.phoenix)
+
+ def test_type_equivalence(self):
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), IDENTICAL)
+ self.titanic.set_type(gen.lib.LdsOrd.CONFIRMATION)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_date_equivalence(self):
+ date = gen.lib.Date()
+ date.set_yr_mon_day(1999,12,5)
+ self.titanic.set_date_object(date)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_temple_equivalence(self):
+ self.titanic.set_temple('Baton Rouge, Louisiana')
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_status_equivalence(self):
+ self.titanic.set_status(gen.lib.LdsOrd.STATUS_CLEARED)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_famc_equivalence(self):
+ self.titanic.set_family_handle('F1')
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_privacy_equivalence(self):
+ self.titanic.set_privacy(True)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), EQUAL)
+
+class LdsordBaseCheck(unittest.TestCase):
+ def setUp(self):
+ self.phoenix = gen.lib.ldsordbase.LdsOrdBase()
+ self.titanic = gen.lib.ldsordbase.LdsOrdBase()
+ self.ref_list = gen.lib.ldsordbase.LdsOrdBase()
+ ldsord = gen.lib.LdsOrd()
+ ldsord.set_temple('London, England')
+ self.phoenix.add_lds_ord(ldsord)
+
+ def test_identical(self):
+ ldsord = gen.lib.LdsOrd()
+ ldsord.set_temple('London, England')
+ self.titanic.add_lds_ord(ldsord)
+ self.ref_list.add_lds_ord(ldsord)
+ self.phoenix._merge_lds_ord_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_equal(self):
+ ldsord = gen.lib.LdsOrd()
+ ldsord.set_temple('London, England')
+ ldsord.set_privacy(True)
+ self.titanic.add_lds_ord(ldsord)
+ self.ref_list.add_lds_ord(ldsord)
+ self.phoenix._merge_lds_ord_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_different(self):
+ ldsord = gen.lib.LdsOrd()
+ ldsord.set_temple('Baton Rouge, Louisiana')
+ self.titanic.add_lds_ord(ldsord)
+ self.ref_list = gen.lib.ldsordbase.LdsOrdBase(self.phoenix)
+ self.ref_list.add_lds_ord(ldsord)
+ self.phoenix._merge_lds_ord_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+class MediaBaseCheck(unittest.TestCase):
+ def setUp(self):
+ self.phoenix = gen.lib.mediabase.MediaBase()
+ self.titanic = gen.lib.mediabase.MediaBase()
+ self.ref_list = gen.lib.mediabase.MediaBase()
+ mediaref = gen.lib.MediaRef()
+ mediaref.set_reference_handle('123456')
+ mediaref.set_rectangle('10 10 90 90')
+ self.phoenix.add_media_reference(mediaref)
+
+ def test_merge_identical(self):
+ mediaref = gen.lib.MediaRef()
+ mediaref.set_reference_handle('123456')
+ mediaref.set_rectangle('10 10 90 90')
+ self.titanic.add_media_reference(mediaref)
+ self.ref_list.add_media_reference(mediaref)
+ self.phoenix._merge_media_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_merge_equal(self):
+ mediaref = gen.lib.MediaRef()
+ mediaref.set_reference_handle('123456')
+ mediaref.set_rectangle('10 10 90 90')
+ mediaref.set_privacy(True)
+ self.titanic.add_media_reference(mediaref)
+ self.ref_list.add_media_reference(mediaref)
+ self.phoenix._merge_media_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_merge_different(self):
+ mediaref1 = gen.lib.MediaRef()
+ mediaref1.set_reference_handle('123456')
+ mediaref1.set_rectangle('10 10 90 90')
+ mediaref2 = gen.lib.MediaRef()
+ mediaref2.set_reference_handle('123456')
+ mediaref2.set_rectangle('20 10 90 90')
+ self.titanic.add_media_reference(mediaref2)
+ self.ref_list.add_media_reference(mediaref1)
+ self.ref_list.add_media_reference(mediaref2)
+ self.phoenix._merge_media_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_replace_absent(self):
+ mediaref1 = gen.lib.MediaRef()
+ mediaref1.set_reference_handle('654321')
+ mediaref1.set_rectangle('10 10 90 90')
+ self.ref_list.add_media_reference(mediaref1)
+ self.phoenix.replace_media_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_replace_identical(self):
+ mediaref1 = gen.lib.MediaRef()
+ mediaref1.set_reference_handle('654321')
+ mediaref1.set_rectangle('10 10 90 90')
+ mediaref2 = gen.lib.MediaRef()
+ mediaref2.set_reference_handle('654321')
+ mediaref2.set_rectangle('10 10 90 90')
+ self.phoenix.add_media_reference(mediaref1)
+ self.ref_list.add_media_reference(mediaref2)
+ self.phoenix.replace_media_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_replace_equal(self):
+ mediaref1 = gen.lib.MediaRef()
+ mediaref1.set_reference_handle('654321')
+ mediaref1.set_rectangle('10 10 90 90')
+ mediaref1.set_privacy(True)
+ mediaref2 = gen.lib.MediaRef()
+ mediaref2.set_reference_handle('654321')
+ mediaref2.set_rectangle('10 10 90 90')
+ mediaref2.set_privacy(True)
+ self.phoenix.add_media_reference(mediaref1)
+ self.ref_list.add_media_reference(mediaref2)
+ self.phoenix.replace_media_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_replace_different(self):
+ mediaref1 = gen.lib.MediaRef()
+ mediaref1.set_reference_handle('654321')
+ mediaref1.set_rectangle('20 20 90 90')
+ mediaref2 = gen.lib.MediaRef()
+ mediaref2.set_reference_handle('654321')
+ mediaref2.set_rectangle('10 10 90 90')
+ mediaref3 = gen.lib.MediaRef()
+ mediaref3.set_reference_handle('654321')
+ mediaref3.set_rectangle('20 20 90 90')
+ self.phoenix.add_media_reference(mediaref1)
+ self.ref_list.add_media_reference(mediaref2)
+ self.ref_list.add_media_reference(mediaref3)
+ self.phoenix.replace_media_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_replace_order_first(self):
+ mediaref1 = gen.lib.MediaRef()
+ mediaref1.set_reference_handle('234567')
+ mediaref1.set_rectangle('10 10 90 90')
+ mediaref2 = gen.lib.MediaRef()
+ mediaref2.set_reference_handle('654321')
+ mediaref2.set_rectangle('10 10 90 90')
+ mediaref3 = gen.lib.MediaRef()
+ mediaref3.set_reference_handle('123456')
+ mediaref3.set_rectangle('10 10 90 90')
+ mediaref4 = gen.lib.MediaRef()
+ mediaref4.set_reference_handle('234567')
+ mediaref4.set_rectangle('10 10 90 90')
+ self.phoenix.add_media_reference(mediaref1)
+ self.phoenix.add_media_reference(mediaref2)
+ self.ref_list.add_media_reference(mediaref3)
+ self.ref_list.add_media_reference(mediaref4)
+ self.phoenix.replace_media_references('654321','123456')
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_replace_order_last(self):
+ mediaref1 = gen.lib.MediaRef()
+ mediaref1.set_reference_handle('234567')
+ mediaref1.set_rectangle('10 10 90 90')
+ mediaref2 = gen.lib.MediaRef()
+ mediaref2.set_reference_handle('654321')
+ mediaref2.set_rectangle('10 10 90 90')
+ mediaref3 = gen.lib.MediaRef()
+ mediaref3.set_reference_handle('234567')
+ mediaref3.set_rectangle('10 10 90 90')
+ mediaref4 = gen.lib.MediaRef()
+ mediaref4.set_reference_handle('654321')
+ mediaref4.set_rectangle('10 10 90 90')
+ self.phoenix.add_media_reference(mediaref1)
+ self.phoenix.add_media_reference(mediaref2)
+ self.ref_list.add_media_reference(mediaref3)
+ self.ref_list.add_media_reference(mediaref4)
+ self.phoenix.replace_media_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+class MediaObjectCheck(unittest.TestCase, PrivacyBaseTest, AttrBaseTest,
+ NoteBaseTest, SourceBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.MediaObject()
+ self.phoenix.set_path('example.png')
+ self.titanic = gen.lib.MediaObject(self.phoenix)
+ self.ref_obj = gen.lib.MediaObject(self.phoenix)
+
+class MediaRefCheck(unittest.TestCase, PrivacyBaseTest, AttrBaseTest,
+ SourceBaseTest, NoteBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.MediaRef()
+ self.phoenix.set_rectangle("10 10 90 90")
+ self.titanic = gen.lib.MediaRef(self.phoenix)
+ self.ref_obj = gen.lib.MediaRef(self.phoenix)
+
+ def test_ref_equivalence(self):
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), IDENTICAL)
+ self.titanic.set_reference_handle('123456')
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_rect_equivalence(self):
+ self.titanic.set_rectangle("20 20 80 80")
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_privacy_equivalence(self):
+ self.titanic.set_privacy(True)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), EQUAL)
+
+class NameCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest,
+ SourceBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.Name()
+ self.phoenix.set_first_name('Willem')
+ surname = gen.lib.Surname()
+ surname.set_surname("Oranje")
+ self.phoenix.add_surname(surname)
+ self.titanic = gen.lib.Name(self.phoenix)
+ self.ref_obj = gen.lib.Name(self.phoenix)
+
+ def test_datalist_equivalence(self):
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), IDENTICAL)
+ self.titanic.set_first_name('Maurits')
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_date_equivalence(self):
+ date = gen.lib.Date()
+ date.set_yr_mon_day(1999,12,5)
+ self.titanic.set_date_object(date)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_surname_equivalence(self):
+ surname = gen.lib.Surname()
+ surname.set_surname("Nassau")
+ self.titanic.add_surname(surname)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_privacy_equivalence(self):
+ self.titanic.set_privacy(True)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), EQUAL)
+
+class NoteCheck(unittest.TestCase, PrivacyBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.Note("hello world")
+ self.titanic = gen.lib.Note("hello world")
+ self.ref_obj = gen.lib.Note("hello world")
+
+class NoteBaseCheck(unittest.TestCase):
+ def setUp(self):
+ self.phoenix = gen.lib.notebase.NoteBase()
+ self.titanic = gen.lib.notebase.NoteBase()
+ note = gen.lib.Note("hello world")
+ note.set_handle('123456')
+ self.phoenix.add_note(note.get_handle())
+
+ def test_identical(self):
+ ref_note_list = gen.lib.notebase.NoteBase(self.phoenix)
+ self.titanic.add_note(self.phoenix.get_note_list()[0])
+ self.phoenix._merge_note_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), ref_note_list.serialize())
+
+ def test_different(self):
+ ref_note_list = gen.lib.notebase.NoteBase(self.phoenix)
+ note = gen.lib.Note("note other")
+ self.titanic.add_note(note.get_handle())
+ ref_note_list.add_note(note.get_handle())
+ self.phoenix._merge_note_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), ref_note_list.serialize())
+
+ def test_replace_nonew(self):
+ note = gen.lib.Note("note other")
+ note.set_handle('654321')
+ ref_note_list = gen.lib.notebase.NoteBase()
+ ref_note_list.add_note(note.get_handle())
+ self.phoenix.replace_note_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), ref_note_list.serialize())
+
+ def test_replace_newpresent(self):
+ note = gen.lib.Note("note other")
+ note.set_handle('654321')
+ note2 = gen.lib.Note("yet another note")
+ note2.set_handle('234567')
+ self.phoenix.add_note(note2.get_handle())
+ self.phoenix.add_note(note.get_handle())
+ ref_note_list = gen.lib.notebase.NoteBase()
+ ref_note_list.add_note(note2.get_handle())
+ ref_note_list.add_note(note.get_handle())
+ self.phoenix.replace_note_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), ref_note_list.serialize())
+
+ def todo_test_replace_child(self):
+ self.phoenix.replace_note_references('','')
+ self.assertEqual(self.phoenix.serialize(), ref_note_list.serialize())
+
+class PersonCheck(unittest.TestCase, PrivacyBaseTest, MediaBaseTest,
+ AttrBaseTest, NoteBaseTest, SourceBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.Person()
+ name = gen.lib.Name()
+ name.set_first_name('Adam')
+ self.phoenix.set_primary_name(name)
+ self.titanic = gen.lib.Person()
+ self.titanic.set_primary_name(name)
+ self.ref_obj = gen.lib.Person()
+ self.ref_obj.set_primary_name(name)
+
+ def test_replace_eventhandle_nonew(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_reference_handle('123456')
+ evtref2 = gen.lib.EventRef()
+ evtref2.set_reference_handle('654321')
+ self.phoenix.add_event_ref(evtref)
+ self.ref_obj.add_event_ref(evtref2)
+ self.phoenix._replace_handle_reference('Event', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_eventhandle_identical(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_reference_handle('123456')
+ evtref2 = gen.lib.EventRef()
+ evtref2.set_reference_handle('234567')
+ evtref3 = gen.lib.EventRef()
+ evtref3.set_reference_handle('654321')
+ self.phoenix.add_event_ref(evtref)
+ self.phoenix.add_event_ref(evtref2)
+ self.phoenix.add_event_ref(evtref3)
+ self.ref_obj.add_event_ref(evtref2)
+ self.ref_obj.add_event_ref(evtref3)
+ self.phoenix._replace_handle_reference('Event', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_eventhandle_equal(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_reference_handle('123456')
+ evtref2 = gen.lib.EventRef()
+ evtref2.set_reference_handle('234567')
+ evtref3 = gen.lib.EventRef()
+ evtref3.set_reference_handle('654321')
+ evtref3.set_privacy(True)
+ self.phoenix.add_event_ref(evtref)
+ self.phoenix.add_event_ref(evtref2)
+ self.phoenix.add_event_ref(evtref3)
+ self.ref_obj.add_event_ref(evtref2)
+ self.ref_obj.add_event_ref(evtref3)
+ self.phoenix._replace_handle_reference('Event', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_eventhandle_different(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_reference_handle('123456')
+ evtref2 = gen.lib.EventRef()
+ evtref2.set_reference_handle('234567')
+ evtref3 = gen.lib.EventRef()
+ evtref3.set_reference_handle('654321')
+ self.phoenix.add_event_ref(evtref)
+ self.phoenix.add_event_ref(evtref2)
+ self.ref_obj.add_event_ref(evtref3)
+ self.ref_obj.add_event_ref(evtref2)
+ self.phoenix._replace_handle_reference('Event', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_birth_lower(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_reference_handle('123456')
+ evtref2 = gen.lib.EventRef()
+ evtref2.set_reference_handle('654321')
+ self.phoenix.add_event_ref(evtref)
+ self.phoenix.add_event_ref(evtref2)
+ self.phoenix.birth_ref_index = 2
+ self.ref_obj.add_event_ref(evtref2)
+ self.ref_obj.birth_ref_index = 1
+ self.phoenix._replace_handle_reference('Event', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_birth_minusone(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_reference_handle('654321')
+ evtref2 = gen.lib.EventRef()
+ evtref2.set_reference_handle('123456')
+ self.phoenix.add_event_ref(evtref)
+ self.phoenix.add_event_ref(evtref2)
+ self.phoenix.birth_ref_index = 1
+ self.ref_obj.add_event_ref(evtref2)
+ self.ref_obj.birth_ref_index = -1
+ self.phoenix._replace_handle_reference('Event', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_death_lower(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_reference_handle('123456')
+ evtref2 = gen.lib.EventRef()
+ evtref2.set_reference_handle('654321')
+ self.phoenix.add_event_ref(evtref)
+ self.phoenix.add_event_ref(evtref2)
+ self.phoenix.death_ref_index = 2
+ self.ref_obj.add_event_ref(evtref2)
+ self.ref_obj.death_ref_index = 1
+ self.phoenix._replace_handle_reference('Event', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_death_minusone(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_reference_handle('654321')
+ evtref2 = gen.lib.EventRef()
+ evtref2.set_reference_handle('123456')
+ self.phoenix.add_event_ref(evtref)
+ self.phoenix.add_event_ref(evtref2)
+ self.phoenix.death_ref_index = 1
+ self.ref_obj.add_event_ref(evtref2)
+ self.ref_obj.death_ref_index = -1
+ self.phoenix._replace_handle_reference('Event', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_personhandle_nonew(self):
+ personref = gen.lib.PersonRef()
+ personref.set_reference_handle('123456')
+ self.phoenix.add_person_ref(personref)
+ personref2 = gen.lib.PersonRef()
+ personref2.set_reference_handle('654321')
+ self.ref_obj.add_person_ref(personref2)
+ self.phoenix._replace_handle_reference('Person', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_personhandle_identical(self):
+ personref = gen.lib.PersonRef()
+ personref.set_reference_handle('123456')
+ personref2 = gen.lib.PersonRef()
+ personref2.set_reference_handle('234567')
+ personref3 = gen.lib.PersonRef()
+ personref3.set_reference_handle('654321')
+ self.phoenix.add_person_ref(personref)
+ self.phoenix.add_person_ref(personref2)
+ self.phoenix.add_person_ref(personref3)
+ self.ref_obj.add_person_ref(personref2)
+ self.ref_obj.add_person_ref(personref3)
+ self.phoenix._replace_handle_reference('Person', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_personhandle_equal(self):
+ personref = gen.lib.PersonRef()
+ personref.set_reference_handle('123456')
+ personref.set_privacy(True)
+ personref2 = gen.lib.PersonRef()
+ personref2.set_reference_handle('234567')
+ personref3 = gen.lib.PersonRef()
+ personref3.set_reference_handle('654321')
+ personref4 = gen.lib.PersonRef()
+ personref4.set_reference_handle('654321')
+ personref4.set_privacy(True)
+ self.phoenix.add_person_ref(personref)
+ self.phoenix.add_person_ref(personref2)
+ self.phoenix.add_person_ref(personref3)
+ self.ref_obj.add_person_ref(personref2)
+ self.ref_obj.add_person_ref(personref4)
+ self.phoenix._replace_handle_reference('Person', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_personhandle_different(self):
+ personref = gen.lib.PersonRef()
+ personref.set_reference_handle('123456')
+ personref2 = gen.lib.PersonRef()
+ personref2.set_reference_handle('234567')
+ personref3 = gen.lib.PersonRef()
+ personref3.set_reference_handle('654321')
+ self.phoenix.add_person_ref(personref)
+ self.phoenix.add_person_ref(personref2)
+ self.ref_obj.add_person_ref(personref3)
+ self.ref_obj.add_person_ref(personref2)
+ self.phoenix._replace_handle_reference('Person', '123456', '654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_person_primaryname(self):
+ name = gen.lib.Name()
+ name.set_first_name('Abel')
+ self.titanic.set_primary_name(name)
+ self.ref_obj.add_alternate_name(name)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_person_altname(self):
+ name = gen.lib.Name()
+ name.set_first_name('Abel')
+ self.titanic.add_alternate_name(name)
+ self.ref_obj.add_alternate_name(name)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_person_eventref(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_reference_handle('123456')
+ self.titanic.add_event_ref(evtref)
+ self.ref_obj.add_event_ref(evtref)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_person_ldsord(self):
+ ldsord = gen.lib.LdsOrd()
+ ldsord.set_type(gen.lib.LdsOrd.BAPTISM)
+ self.titanic.add_lds_ord(ldsord)
+ self.ref_obj.add_lds_ord(ldsord)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_person_address(self):
+ address = gen.lib.Address()
+ address.set_city('The Hague')
+ self.titanic.add_address(address)
+ self.ref_obj.add_address(address)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_person_personref(self):
+ personref = gen.lib.PersonRef()
+ personref.set_reference_handle('123456')
+ self.titanic.add_person_ref(personref)
+ self.ref_obj.add_person_ref(personref)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def todo_test_merge_person_aschild(self):
+ pass
+
+ def todo_test_merge_person_asparent(self):
+ pass
+
+ def test_altname_identical(self):
+ name = gen.lib.Name()
+ name.set_first_name('Abel')
+ name2 = gen.lib.Name()
+ name2.set_first_name('Abel')
+ self.phoenix.add_alternate_name(name)
+ self.titanic.add_alternate_name(name2)
+ self.ref_obj.add_alternate_name(name)
+ self.phoenix._merge_alternate_names(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_altname_equal(self):
+ name = gen.lib.Name()
+ name.set_first_name('Abel')
+ name2 = gen.lib.Name()
+ name2.set_first_name('Abel')
+ name2.set_privacy(True)
+ self.phoenix.add_alternate_name(name)
+ self.titanic.add_alternate_name(name2)
+ self.ref_obj.add_alternate_name(name2)
+ self.phoenix._merge_alternate_names(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_altname_different(self):
+ name = gen.lib.Name()
+ name.set_first_name('Abel')
+ name2 = gen.lib.Name()
+ name2.set_first_name('Cain')
+ self.phoenix.add_alternate_name(name)
+ self.titanic.add_alternate_name(name2)
+ self.ref_obj.add_alternate_name(name)
+ self.ref_obj.add_alternate_name(name2)
+ self.phoenix._merge_alternate_names(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_eventrefs_identical(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_reference_handle('123456')
+ evtref2 = gen.lib.EventRef()
+ evtref2.set_reference_handle('123456')
+ self.phoenix.add_event_ref(evtref)
+ self.titanic.add_event_ref(evtref2)
+ self.ref_obj.add_event_ref(evtref)
+ self.phoenix._merge_event_ref_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_eventrefs_equal(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_reference_handle('123456')
+ evtref2 = gen.lib.EventRef()
+ evtref2.set_reference_handle('123456')
+ evtref2.set_privacy(True)
+ self.phoenix.add_event_ref(evtref)
+ self.titanic.add_event_ref(evtref2)
+ self.ref_obj.add_event_ref(evtref2)
+ self.phoenix._merge_event_ref_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_eventrefs_different(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_reference_handle('123456')
+ evtref2 = gen.lib.EventRef()
+ evtref2.set_reference_handle('234567')
+ self.phoenix.add_event_ref(evtref)
+ self.titanic.add_event_ref(evtref2)
+ self.ref_obj.add_event_ref(evtref)
+ self.ref_obj.add_event_ref(evtref2)
+ self.phoenix._merge_event_ref_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_eventrefs_birthref(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_reference_handle('123456')
+ evtref2 = gen.lib.EventRef()
+ evtref2.set_reference_handle('234567')
+ evtref3 = gen.lib.EventRef()
+ evtref3.set_reference_handle('123456')
+ self.phoenix.add_event_ref(evtref2)
+ self.titanic.add_event_ref(evtref)
+ self.titanic.birth_ref_index = 0
+ self.ref_obj.add_event_ref(evtref2)
+ self.ref_obj.add_event_ref(evtref3)
+ self.ref_obj.birth_ref_index = 1
+ self.phoenix._merge_event_ref_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_eventrefs_deathref(self):
+ evtref = gen.lib.EventRef()
+ evtref.set_reference_handle('123456')
+ evtref2 = gen.lib.EventRef()
+ evtref2.set_reference_handle('234567')
+ evtref3 = gen.lib.EventRef()
+ evtref3.set_reference_handle('123456')
+ self.phoenix.add_event_ref(evtref2)
+ self.titanic.add_event_ref(evtref)
+ self.titanic.death_ref_index = 0
+ self.ref_obj.add_event_ref(evtref2)
+ self.ref_obj.add_event_ref(evtref3)
+ self.ref_obj.death_ref_index = 1
+ self.phoenix._merge_event_ref_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_personrefs_identical(self):
+ personref = gen.lib.PersonRef()
+ personref.set_reference_handle('123456')
+ self.phoenix.add_person_ref(personref)
+ self.titanic.add_person_ref(personref)
+ self.ref_obj.add_person_ref(personref)
+ self.phoenix._merge_person_ref_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_personrefs_equal(self):
+ personref = gen.lib.PersonRef()
+ personref.set_reference_handle('123456')
+ personref2 = gen.lib.PersonRef()
+ personref2.set_reference_handle('123456')
+ personref2.set_privacy(True)
+ self.phoenix.add_person_ref(personref)
+ self.titanic.add_person_ref(personref2)
+ self.ref_obj.add_person_ref(personref2)
+ self.phoenix._merge_person_ref_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_personrefs_different(self):
+ personref = gen.lib.PersonRef()
+ personref.set_reference_handle('123456')
+ personref2 = gen.lib.PersonRef()
+ personref2.set_reference_handle('234567')
+ self.phoenix.add_person_ref(personref)
+ self.titanic.add_person_ref(personref2)
+ self.ref_obj.add_person_ref(personref)
+ self.ref_obj.add_person_ref(personref2)
+ self.phoenix._merge_person_ref_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+class PlaceCheck(unittest.TestCase, PrivacyBaseTest, MediaBaseTest,
+ UrlBaseTest, NoteBaseTest, SourceBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.Place()
+ self.phoenix.set_title('Place 1')
+ self.titanic = gen.lib.Place(self.phoenix)
+ self.ref_obj = gen.lib.Place(self.phoenix)
+
+ def test_merge_primary_identical(self):
+ loc = gen.lib.Location()
+ loc.set_city('Amsterdam')
+ self.phoenix.set_main_location(loc)
+ self.titanic.set_title('Place 2')
+ loc2 = gen.lib.Location()
+ loc2.set_city('Amsterdam')
+ self.titanic.set_main_location(loc2)
+ self.ref_obj.set_main_location(loc)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_primary_different(self):
+ loc = gen.lib.Location()
+ loc.set_city('Amsterdam')
+ self.phoenix.set_main_location(loc)
+ self.titanic.set_title('Place 2')
+ loc2 = gen.lib.Location()
+ loc2.set_city('Rotterdam')
+ self.titanic.set_main_location(loc2)
+ self.ref_obj.set_main_location(loc)
+ self.ref_obj.add_alternate_locations(loc2)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_primary_null(self):
+ """
+ Even if primary location of phoenix is null, still add titanics
+ primary to alternate locations.
+ """
+ loc = gen.lib.Location()
+ loc.set_city('Amsterdam')
+ self.titanic.set_title('Place2')
+ self.titanic.set_main_location(loc)
+ self.ref_obj.add_alternate_locations(loc)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_alternate_identical(self):
+ loc = gen.lib.Location()
+ loc.set_city('Amsterdam')
+ self.phoenix.add_alternate_locations(loc)
+ loc2 = gen.lib.Location()
+ loc2.set_city('Amsterdam')
+ self.titanic.add_alternate_locations(loc2)
+ self.ref_obj.add_alternate_locations(loc)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_alternate_different(self):
+ loc = gen.lib.Location()
+ loc.set_city('Amsterdam')
+ self.phoenix.add_alternate_locations(loc)
+ loc2 = gen.lib.Location()
+ loc2.set_city('Rotterdam')
+ self.titanic.add_alternate_locations(loc2)
+ self.ref_obj.add_alternate_locations(loc)
+ self.ref_obj.add_alternate_locations(loc2)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_prialt_identical(self):
+ loc = gen.lib.Location()
+ loc.set_city('Amsterdam')
+ self.phoenix.set_main_location(loc)
+ loc2 = gen.lib.Location()
+ loc2.set_city('Amsterdam')
+ self.titanic.add_alternate_locations(loc2)
+ self.ref_obj.set_main_location(loc)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_prialt2(self):
+ loc = gen.lib.Location()
+ loc.set_city('Amsterdam')
+ self.phoenix.set_main_location(loc)
+ loc2 = gen.lib.Location()
+ loc2.set_city('Rotterdam')
+ loc3 = gen.lib.Location()
+ loc3.set_city('Rotterdam')
+ self.phoenix.add_alternate_locations(loc2)
+ self.titanic.set_main_location(loc3)
+ self.ref_obj.set_main_location(loc)
+ self.ref_obj.add_alternate_locations(loc2)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+class RepoCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest, UrlBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.Repository()
+ self.phoenix.set_name('Repo 1')
+ self.phoenix.set_type(gen.lib.RepositoryType.LIBRARY)
+ self.titanic = gen.lib.Repository()
+ self.titanic.set_name('Repo 1')
+ self.titanic.set_type(gen.lib.RepositoryType.LIBRARY)
+ self.ref_obj = gen.lib.Repository()
+ self.ref_obj.set_name('Repo 1')
+ self.ref_obj.set_type(gen.lib.RepositoryType.LIBRARY)
+
+ def test_address(self):
+ address = gen.lib.Address()
+ address.set_city('Amsterdam')
+ self.titanic.add_address(address)
+ self.ref_obj.add_address(address)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace(self):
+ address = gen.lib.Address()
+ address.set_city('Utrecht')
+ srcref = gen.lib.SourceRef()
+ srcref.set_reference_handle('123456')
+ address.add_source_reference(srcref)
+ self.phoenix.add_address(address)
+ address2 = gen.lib.Address()
+ address2.set_city('Utrecht')
+ srcref2 = gen.lib.SourceRef()
+ srcref2.set_reference_handle('654321')
+ address2.add_source_reference(srcref2)
+ self.ref_obj.add_address(address2)
+ self.phoenix.replace_source_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+class RepoRefCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.RepoRef()
+ self.phoenix.set_reference_handle('123456')
+ self.titanic = gen.lib.RepoRef(self.phoenix)
+ self.ref_obj = gen.lib.RepoRef(self.phoenix)
+
+ def test_handle_equivalence(self):
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), IDENTICAL)
+ self.titanic.set_reference_handle('654321')
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_callnr_equivalence(self):
+ self.titanic.set_call_number('10')
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_privacy_equivalence(self):
+ self.titanic.set_privacy(True)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), EQUAL)
+
+class SourceCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest,
+ MediaBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.Source()
+ self.phoenix.set_title("Source 1")
+ self.titanic = gen.lib.Source()
+ self.titanic.set_title("Source 1")
+ self.ref_obj = gen.lib.Source()
+ self.ref_obj.set_title("Source 1")
+
+ def todo_test_replace(self):
+ pass
+
+ def test_merge_datamap(self):
+ self.phoenix.set_data_item('A', 'a')
+ self.phoenix.set_data_item('B', 'b')
+ self.titanic.set_data_item('B', 'bb')
+ self.titanic.set_data_item('C', 'c')
+ self.ref_obj.set_data_item('A', 'a')
+ self.ref_obj.set_data_item('B', 'b')
+ self.ref_obj.set_data_item('C', 'c')
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_reporef(self):
+ reporef = gen.lib.RepoRef()
+ reporef.set_reference_handle('123456')
+ self.titanic.add_repo_reference(reporef)
+ self.ref_obj.add_repo_reference(reporef)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_reporef_identical(self):
+ reporef = gen.lib.RepoRef()
+ reporef.set_reference_handle('123456')
+ self.phoenix.add_repo_reference(reporef)
+ self.titanic.add_repo_reference(reporef)
+ self.ref_obj.add_repo_reference(reporef)
+ self.phoenix._merge_reporef_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_merge_reporef_equal(self):
+ reporef = gen.lib.RepoRef()
+ reporef.set_reference_handle('123456')
+ reporef2 = gen.lib.RepoRef()
+ reporef2.set_reference_handle('123456')
+ reporef2.set_privacy(True)
+ self.phoenix.add_repo_reference(reporef)
+ self.titanic.add_repo_reference(reporef2)
+ self.ref_obj.add_repo_reference(reporef2)
+ self.phoenix._merge_reporef_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+
+ def test_merge_reporef_different(self):
+ reporef = gen.lib.RepoRef()
+ reporef.set_reference_handle('123456')
+ reporef2 = gen.lib.RepoRef()
+ reporef2.set_reference_handle('234567')
+ self.phoenix.add_repo_reference(reporef)
+ self.titanic.add_repo_reference(reporef2)
+ self.ref_obj.add_repo_reference(reporef)
+ self.ref_obj.add_repo_reference(reporef2)
+ self.phoenix._merge_reporef_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_reporef_nonew(self):
+ reporef = gen.lib.RepoRef()
+ reporef.set_reference_handle('123456')
+ reporef2 = gen.lib.RepoRef()
+ reporef2.set_reference_handle('654321')
+ self.phoenix.add_repo_reference(reporef)
+ self.ref_obj.add_repo_reference(reporef2)
+ self.phoenix.replace_repo_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_reporef_identical(self):
+ reporef = gen.lib.RepoRef()
+ reporef.set_reference_handle('123456')
+ reporef2 = gen.lib.RepoRef()
+ reporef2.set_reference_handle('234567')
+ reporef3 = gen.lib.RepoRef()
+ reporef3.set_reference_handle('654321')
+ self.phoenix.add_repo_reference(reporef)
+ self.phoenix.add_repo_reference(reporef2)
+ self.phoenix.add_repo_reference(reporef3)
+ self.ref_obj.add_repo_reference(reporef2)
+ self.ref_obj.add_repo_reference(reporef3)
+ self.phoenix.replace_repo_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_reporef_equal(self):
+ reporef = gen.lib.RepoRef()
+ reporef.set_reference_handle('123456')
+ reporef2 = gen.lib.RepoRef()
+ reporef2.set_reference_handle('234567')
+ reporef3 = gen.lib.RepoRef()
+ reporef3.set_reference_handle('654321')
+ reporef3.set_privacy(True)
+ self.phoenix.add_repo_reference(reporef)
+ self.phoenix.add_repo_reference(reporef2)
+ self.phoenix.add_repo_reference(reporef3)
+ self.ref_obj.add_repo_reference(reporef2)
+ self.ref_obj.add_repo_reference(reporef3)
+ self.phoenix.replace_repo_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+ def test_replace_reporef_different(self):
+ reporef = gen.lib.RepoRef()
+ reporef.set_reference_handle('123456')
+ reporef2 = gen.lib.RepoRef()
+ reporef2.set_reference_handle('234567')
+ reporef3 = gen.lib.RepoRef()
+ reporef3.set_reference_handle('654321')
+ reporef3.set_call_number('100')
+ reporef4 = gen.lib.RepoRef()
+ reporef4.set_reference_handle('654321')
+ self.phoenix.add_repo_reference(reporef)
+ self.phoenix.add_repo_reference(reporef2)
+ self.phoenix.add_repo_reference(reporef3)
+ self.ref_obj.add_repo_reference(reporef4)
+ self.ref_obj.add_repo_reference(reporef2)
+ self.ref_obj.add_repo_reference(reporef3)
+ self.phoenix.replace_repo_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+class SourceBaseCheck(unittest.TestCase):
+ def setUp(self):
+ self.phoenix = gen.lib.srcbase.SourceBase()
+ srcref = gen.lib.SourceRef()
+ srcref.set_reference_handle('123456')
+ self.phoenix.add_source_reference(srcref)
+ self.titanic = gen.lib.srcbase.SourceBase()
+ self.obj_list = gen.lib.srcbase.SourceBase()
+
+ def test_replace_nonew(self):
+ srcref = gen.lib.SourceRef()
+ srcref.set_reference_handle('654321')
+ self.obj_list.add_source_reference(srcref)
+ self.phoenix.replace_source_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), self.obj_list.serialize())
+
+ def test_replace_different(self):
+ srcref = gen.lib.SourceRef()
+ srcref.set_reference_handle('654321')
+ srcref.set_page('p.10')
+ srcref2 = gen.lib.SourceRef()
+ srcref2.set_reference_handle('654321')
+ self.obj_list.add_source_reference(srcref2)
+ self.obj_list.add_source_reference(srcref)
+ self.phoenix.add_source_reference(srcref)
+ self.phoenix.replace_source_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), self.obj_list.serialize())
+
+ def test_replace_identical(self):
+ srcref = gen.lib.SourceRef()
+ srcref.set_reference_handle('654321')
+ srcref2 = gen.lib.SourceRef()
+ srcref2.set_reference_handle('234567')
+ self.phoenix.add_source_reference(srcref2)
+ self.phoenix.add_source_reference(srcref)
+ self.obj_list.add_source_reference(srcref2)
+ self.obj_list.add_source_reference(srcref)
+ self.phoenix.replace_source_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), self.obj_list.serialize())
+
+ def test_replace_equal(self):
+ srcref = gen.lib.SourceRef()
+ srcref.set_reference_handle('654321')
+ srcref.set_privacy(True)
+ srcref2 = gen.lib.SourceRef()
+ srcref2.set_reference_handle('234567')
+ self.phoenix.add_source_reference(srcref2)
+ self.phoenix.add_source_reference(srcref)
+ self.obj_list.add_source_reference(srcref2)
+ self.obj_list.add_source_reference(srcref)
+ self.phoenix.replace_source_references('123456','654321')
+ self.assertEqual(self.phoenix.serialize(), self.obj_list.serialize())
+
+ def todo_test_replace_child(self):
+ pass
+
+ def test_merge_identical(self):
+ srcref = gen.lib.SourceRef()
+ srcref.set_reference_handle('123456')
+ self.titanic.add_source_reference(srcref)
+ self.obj_list.add_source_reference(srcref)
+ self.phoenix._merge_source_reference_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.obj_list.serialize())
+
+ def test_merge_equal(self):
+ srcref = gen.lib.SourceRef()
+ srcref.set_reference_handle('123456')
+ srcref.set_privacy(True)
+ self.titanic.add_source_reference(srcref)
+ self.obj_list.add_source_reference(srcref)
+ self.phoenix._merge_source_reference_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.obj_list.serialize())
+
+ def test_merge_different(self):
+ srcref = gen.lib.SourceRef()
+ srcref.set_reference_handle('234567')
+ srcref2 = gen.lib.SourceRef()
+ srcref2.set_reference_handle('123456')
+ self.titanic.add_source_reference(srcref)
+ self.obj_list.add_source_reference(srcref2)
+ self.obj_list.add_source_reference(srcref)
+ self.phoenix._merge_source_reference_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.obj_list.serialize())
+
+class SourceRefCheck(unittest.TestCase, PrivacyBaseTest, NoteBaseTest):
+ def setUp(self):
+ self.phoenix = gen.lib.SourceRef()
+ self.phoenix.set_reference_handle('123456')
+ self.phoenix.set_page('p.10')
+ self.titanic = gen.lib.SourceRef(self.phoenix)
+ self.ref_obj = gen.lib.SourceRef(self.phoenix)
+
+ def test_ref_equivalence(self):
+ self.titanic.set_reference_handle('654321')
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_page_equivalence(self):
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), IDENTICAL)
+ self.titanic.set_page('p.20')
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_date_equivalence(self):
+ date = gen.lib.Date()
+ date.set_yr_mon_day(1999, 12, 5)
+ self.titanic.set_date_object(date)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_privacy_equivalence(self):
+ self.titanic.set_privacy(True)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), EQUAL)
+
+ def test_merge_confidence(self):
+ known_values = ( (0, 0, 0), (0, 1, 0), (0, 2, 0), (0, 3, 0), (0, 4, 0),
+ (1, 0, 0), (1, 1, 1), (1, 2, 1), (1, 3, 1), (1, 4, 4),
+ (2, 0, 0), (2, 1, 1), (2, 2, 2), (2, 3, 3), (2, 4, 4),
+ (3, 0, 0), (3, 1, 1), (3, 2, 3), (3, 3, 3), (3, 4, 4),
+ (4, 0, 0), (4, 1, 4), (4, 2, 4), (4, 3, 4), (4, 4, 4))
+ for val1, val2, val_merge in known_values:
+ self.phoenix.set_confidence_level(val1)
+ self.titanic.set_confidence_level(val2)
+ self.ref_obj.set_confidence_level(val_merge)
+ self.phoenix.merge(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_obj.serialize())
+
+class SurnameCheck(unittest.TestCase):
+ def setUp(self):
+ self.phoenix = gen.lib.Surname()
+ self.phoenix.set_prefix('van')
+ self.titanic = gen.lib.Surname(self.phoenix)
+
+ def test_datalist_equivalence(self):
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), IDENTICAL)
+ self.titanic.set_prefix('von')
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ def test_primary_equivalence(self):
+ self.titanic.set_primary(False)
+ self.assertEqual(self.phoenix.is_equivalent(self.titanic), DIFFERENT)
+
+ # A Surname can never be EQUAL to another Surname.
+
+ # There is no merge method to check.
+
+class SurnameBaseCheck(unittest.TestCase):
+ def setUp(self):
+ self.phoenix = gen.lib.surnamebase.SurnameBase()
+ surname = gen.lib.Surname()
+ surname.set_surname("Oranje")
+ self.phoenix.add_surname(surname)
+ self.titanic = gen.lib.surnamebase.SurnameBase()
+ self.ref_list = gen.lib.surnamebase.SurnameBase()
+
+ def test_identical(self):
+ surname = gen.lib.Surname()
+ surname.set_surname("Oranje")
+ self.ref_list.add_surname(surname)
+ self.titanic.add_surname(surname)
+ self.phoenix._merge_surname_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_different(self):
+ surname = gen.lib.Surname()
+ surname.set_surname("Biesterfelt")
+ self.titanic.add_surname(surname)
+ self.ref_list = gen.lib.surnamebase.SurnameBase(self.phoenix)
+ self.ref_list.add_surname(surname)
+ self.phoenix._merge_surname_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+class TagBaseCheck(unittest.TestCase):
+ def setUp(self):
+ self.phoenix = gen.lib.tagbase.TagBase()
+ tag_handle = '123456'
+ self.phoenix.add_tag(tag_handle)
+ self.titanic = gen.lib.tagbase.TagBase()
+
+ def test_identical(self):
+ self.ref_list = gen.lib.tagbase.TagBase(self.phoenix)
+ self.titanic.add_tag(self.phoenix.get_tag_list()[0])
+ self.phoenix._merge_tag_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+ def test_different(self):
+ self.titanic.set_tag_list([])
+ tag_handle = '654321'
+ self.titanic.add_tag(tag_handle)
+ self.ref_list = gen.lib.tagbase.TagBase(self.phoenix)
+ self.ref_list.add_tag(tag_handle)
+ self.phoenix._merge_tag_list(self.titanic)
+ self.assertEqual(self.phoenix.serialize(), self.ref_list.serialize())
+
+
+if __name__ == "__main__":
+ unittest.main()