From 6fe75d41e27122e1ba46a36655bb438ad96ec1c0 Mon Sep 17 00:00:00 2001 From: Nick Hall Date: Tue, 6 Aug 2013 18:47:59 +0000 Subject: [PATCH] Convert VCard unit tests to use ElementTree svn: r22807 --- .../plugins/export/test/exportvcard_test.py | 322 +++++++-------- .../plugins/importer/test/importvcard_test.py | 388 ++++++++---------- 2 files changed, 314 insertions(+), 396 deletions(-) diff --git a/gramps/plugins/export/test/exportvcard_test.py b/gramps/plugins/export/test/exportvcard_test.py index bca35ed45..fbf6a52c1 100644 --- a/gramps/plugins/export/test/exportvcard_test.py +++ b/gramps/plugins/export/test/exportvcard_test.py @@ -21,24 +21,17 @@ """ Unittest for export to VCard - -To be called from src directory. """ from __future__ import print_function import unittest -import sys -if sys.version_info[0] < 3: - from StringIO import StringIO -else: - from io import StringIO import time import subprocess -import libxml2 +import xml.etree.ElementTree as ET -from gramps.plugins.lib.libgrampsxml import GRAMPS_XML_VERSION +from ...lib.libgrampsxml import GRAMPS_XML_VERSION from gramps.version import VERSION -from gramps.plugins.export.exportvcard import VCardWriter +from ..exportvcard import VCardWriter class VCardCheck(unittest.TestCase): def setUp(self): @@ -49,10 +42,11 @@ class VCardCheck(unittest.TestCase): date = time.localtime(time.time()) self.input_list = ["BEGIN:VCARD", "VERSION:3.0", "FN:Lastname", "N:Lastname;;;;", "END:VCARD"] - strng = """ + self.header = """ - + "http://gramps-project.org/xml/%s/grampsxml.dtd">""" % \ + (GRAMPS_XML_VERSION, GRAMPS_XML_VERSION) + strng = """
@@ -65,21 +59,18 @@ class VCardCheck(unittest.TestCase): """ % \ - (GRAMPS_XML_VERSION, GRAMPS_XML_VERSION, GRAMPS_XML_VERSION, - date[0], date[1], date[2], VERSION) - self.input_ = libxml2.readDoc(strng, '', None, libxml2.XML_PARSE_NONET) - self.database = self.input_.getRootElement() - self.people = self.database.firstElementChild().nextElementSibling() - self.person = self.people.firstElementChild() - self.name = self.person.firstElementChild() - self.lastname = self.name.firstElementChild() + (GRAMPS_XML_VERSION, date[0], date[1], date[2], VERSION) + namespace = "http://gramps-project.org/xml/%s/" % GRAMPS_XML_VERSION + ET.register_namespace("", namespace) + self.database = ET.XML(strng) + self.people = self.database[1] + self.person = self.people[0] + self.name = self.person[0] + self.lastname = self.name[0] def do_test(self, input_doc, expect_str, debug=False): - input_strfile = StringIO() - buf = libxml2.createOutputBuffer(input_strfile, 'UTF-8') - input_doc.saveFormatFileTo(buf, 'UTF-8', 1) if debug: - print(input_strfile.getvalue()) + print(ET.tostring(input_doc)) process = subprocess.Popen('python Gramps.py ' '-i - -f gramps -e - -f vcf', @@ -87,15 +78,17 @@ class VCardCheck(unittest.TestCase): stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - result_str, err_str = process.communicate(input_strfile.getvalue()) + input_str = (self.header.encode('utf-8') + + ET.tostring(input_doc, encoding='utf-8')) + result_str, err_str = process.communicate(input_str) if debug: print(err_str) print(result_str) print(expect_str) - self.assertEqual(result_str, expect_str) + self.assertEqual(result_str, expect_str.encode('utf-8')) def test_base(self): - self.do_test(self.input_, + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_esc_string_none(self): @@ -118,234 +111,205 @@ class VCardCheck(unittest.TestCase): {"comma,":"semicolon;"}) def test_write_formatted_name_title(self): - self.name.newTextChild(None, 'title', 'Sir.') + ET.SubElement(self.name, "title").text = 'Sir.' self.expect[3] = "FN:Sir. Lastname" self.expect[4] = "N:Lastname;;;Sir.;" - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_name_multiple_surname(self): - self.lastname.setContent("Oranje") - self.lastname.newProp("prefix", "van") - self.name.newTextChild(None, "surname", "Nassau") + self.lastname.text = "Oranje" + self.lastname.set("prefix", "van") + ET.SubElement(self.name, "surname").text = "Nassau" self.expect[3] = "FN:van Oranje Nassau" self.expect[4] = "N:van Oranje,Nassau;;;;" self.expect[5] = "SORT-STRING:" + "Oranje".ljust(55) - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_name_callname(self): # callname not in first names! - self.name.newTextChild(None, "first", "B C") - self.name.newTextChild(None, "call", "A") + ET.SubElement(self.name, "first").text = "B C" + ET.SubElement(self.name, "call").text = "A" self.expect[3] = "FN:B C Lastname" self.expect[4] = "N:Lastname;A;B,C;;" self.expect[5] = "SORT-STRING:" + "Lastname".ljust(25) + "B C".ljust(30) - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_name_callname_in_addnames(self): - self.name.newTextChild(None, "first", "A B C") - self.name.newTextChild(None, "call", "B") + ET.SubElement(self.name, "first").text = "A B C" + ET.SubElement(self.name, "call").text = "B" self.expect[3] = "FN:A B C Lastname" self.expect[4] = "N:Lastname;B;A,C;;" self.expect[5] = "SORT-STRING:" + "Lastname".ljust(25) + "A B C".ljust(30) - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_name_no_callname(self): - self.name.newTextChild(None, "first", "A B C") + ET.SubElement(self.name, "first").text = "A B C" self.expect[3] = "FN:A B C Lastname" self.expect[4] = "N:Lastname;A;B,C;;" self.expect[5] = "SORT-STRING:" + "Lastname".ljust(25) + "A B C".ljust(30) - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_name_no_additional_names(self): - self.name.newTextChild(None, "first", "A") + ET.SubElement(self.name, "first").text = "A" self.expect[3] = "FN:A Lastname" self.expect[4] = "N:Lastname;A;;;" self.expect[5] = "SORT-STRING:" + "Lastname".ljust(25) + "A".ljust(30) - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_name_honprefix(self): - self.name.newTextChild(None, 'title', 'Sir') + ET.SubElement(self.name, "title").text = "Sir" self.expect[3] = "FN:Sir Lastname" self.expect[4] = "N:Lastname;;;Sir;" self.expect[5] = "SORT-STRING:" + "Lastname".ljust(55) - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_name_honsuffix(self): - self.name.newTextChild(None, 'suffix', 'Jr.') + ET.SubElement(self.name, "suffix").text = "Jr." self.expect[3] = "FN:Lastname\, Jr." self.expect[4] = "N:Lastname;;;;Jr." self.expect[5] = "SORT-STRING:" + "Lastname".ljust(55)+ "Jr." - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_nicknames_regular(self): - name = self.person.newChild(None, 'name', '') - name.newProp('type', 'Birth Name') - name.newProp('alt', '1') - name.newTextChild(None, 'nick', 'Nick') - name = self.person.newChild(None, 'name', '') - name.newProp('type', 'Birth Name') - name.newProp('alt', '1') - name.newTextChild(None, 'nick', 'N.') + attribs = {'type': 'Birth Name', 'alt': '1'} + name = ET.SubElement(self.person, "name", attrib=attribs) + ET.SubElement(name, 'nick').text = 'Nick' + name = ET.SubElement(self.person, "name", attrib=attribs) + ET.SubElement(name, 'nick').text = 'N.' self.expect.insert(6, "NICKNAME:Nick,N.") - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_nicknames_primary_nick(self): - self.name.newTextChild(None, 'nick', 'Nick') - name = self.person.newChild(None, 'name', '') - name.newProp('type', 'Birth Name') - name.newProp('alt', '1') - name.newTextChild(None, 'nick', 'N.') + ET.SubElement(self.name, 'nick').text = 'Nick' + attribs = {'type': 'Birth Name', 'alt': '1'} + name = ET.SubElement(self.person, "name", attrib=attribs) + ET.SubElement(name, 'nick').text = 'N.' self.expect.insert(6, "NICKNAME:Nick,N.") - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_birthdate_regular(self): - events = self.database.newChild(None, 'events', None) - event = events.newChild(None, 'event', None) - event.newProp('handle', '_e0000') - event.newProp('id', 'E0000') - event.newTextChild(None, 'type', 'Birth') - dateval = event.newChild(None, 'dateval', None) - dateval.newProp('val', '2001-02-28') - evtref = self.person.newChild(None, 'eventref', None) - evtref.newProp('hlink', '_e0000') - evtref.newProp('role', 'Primary') - self.people.addPrevSibling(events) + events = ET.Element('events') + self.database.insert(1, events) + attribs = {'handle': '_e0000', 'id': 'E0000'} + event = ET.SubElement(events, 'event', attrib=attribs) + ET.SubElement(event, 'type').text = 'Birth' + ET.SubElement(event, 'dateval', val='2001-02-28') + attribs = {'hlink': '_e0000', 'role': 'Primary'} + ET.SubElement(self.person, 'eventref', attrib=attribs) self.expect.insert(6, "BDAY:2001-02-28") - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_birthdate_empty(self): - events = self.database.newChild(None, 'events', None) - event = events.newChild(None, 'event', None) - event.newProp('handle', '_e0000') - event.newProp('id', 'E0000') - event.newTextChild(None, 'type', 'Birth') - evtref = self.person.newChild(None, 'eventref', None) - evtref.newProp('hlink', '_e0000') - evtref.newProp('role', 'Primary') - self.people.addPrevSibling(events) - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + events = ET.Element('events') + self.database.insert(1, events) + attribs = {'handle': '_e0000', 'id': 'E0000'} + event = ET.SubElement(events, 'event', attrib=attribs) + ET.SubElement(event, 'type').text = 'Birth' + attribs = {'hlink': '_e0000', 'role': 'Primary'} + ET.SubElement(self.person, 'eventref', attrib=attribs) + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_birhtdate_textonly(self): - events = self.database.newChild(None, 'events', None) - event = events.newChild(None, 'event', None) - event.newProp('handle', '_e0000') - event.newProp('id', 'E0000') - event.newTextChild(None, 'type', 'Birth') - datestr = event.newChild(None, 'datestr', None) - datestr.newProp('val', 'Christmas 2001') - evtref = self.person.newChild(None, 'eventref', None) - evtref.newProp('hlink', '_e0000') - evtref.newProp('role', 'Primary') - self.people.addPrevSibling(events) - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + events = ET.Element('events') + self.database.insert(1, events) + attribs = {'handle': '_e0000', 'id': 'E0000'} + event = ET.SubElement(events, 'event', attrib=attribs) + ET.SubElement(event, 'type').text = 'Birth' + ET.SubElement(event, 'dateval', val='Christmas 2001') + attribs = {'hlink': '_e0000', 'role': 'Primary'} + ET.SubElement(self.person, 'eventref', attrib=attribs) + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_birthdate_span(self): - events = self.database.newChild(None, 'events', None) - event = events.newChild(None, 'event', None) - event.newProp('handle', '_e0000') - event.newProp('id', 'E0000') - event.newTextChild(None, 'type', 'Birth') - datespan = event.newChild(None, 'datespan', None) - datespan.newProp('start', '2001-02-28') - datespan.newProp('stop', '2002-02-28') - evtref = self.person.newChild(None, 'eventref', None) - evtref.newProp('hlink', '_e0000') - evtref.newProp('role', 'Primary') - self.people.addPrevSibling(events) - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + events = ET.Element('events') + self.database.insert(1, events) + attribs = {'handle': '_e0000', 'id': 'E0000'} + event = ET.SubElement(events, 'event', attrib=attribs) + ET.SubElement(event, 'type').text = 'Birth' + attribs = {'start': '2001-02-28', 'stop': '2002-02-28'} + ET.SubElement(event, 'datespan', attrib=attribs) + attribs = {'hlink': '_e0000', 'role': 'Primary'} + ET.SubElement(self.person, 'eventref', attrib=attribs) + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_birthdate_range(self): - events = self.database.newChild(None, 'events', None) - event = events.newChild(None, 'event', None) - event.newProp('handle', '_e0000') - event.newProp('id', 'E0000') - event.newTextChild(None, 'type', 'Birth') - daterange = event.newChild(None, 'daterange', None) - daterange.newProp('start', '2001-02-28') - daterange.newProp('stop', '2002-02-28') - evtref = self.person.newChild(None, 'eventref', None) - evtref.newProp('hlink', '_e0000') - evtref.newProp('role', 'Primary') - self.people.addPrevSibling(events) - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + events = ET.Element('events') + self.database.insert(1, events) + attribs = {'handle': '_e0000', 'id': 'E0000'} + event = ET.SubElement(events, 'event', attrib=attribs) + ET.SubElement(event, 'type').text = 'Birth' + attribs = {'start': '2001-02-28', 'stop': '2002-02-28'} + ET.SubElement(event, 'daterange', attrib=attribs) + attribs = {'hlink': '_e0000', 'role': 'Primary'} + ET.SubElement(self.person, 'eventref', attrib=attribs) + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_addresses_regular(self): - address = self.person.newChild(None, 'address', None) - address.newChild(None, 'street', 'pobox bis street') - address.newChild(None, 'city', 'place') - address.newChild(None, 'country', 'country') - address.newChild(None, 'state', 'province') - address.newChild(None, 'postal', 'zip') + address = ET.SubElement(self.person, 'address') + ET.SubElement(address, 'street').text = 'pobox bis street' + ET.SubElement(address, 'city').text = 'place' + ET.SubElement(address, 'country').text = 'country' + ET.SubElement(address, 'state').text = 'province' + ET.SubElement(address, 'postal').text = 'zip' self.expect.insert(6, "ADR:;;pobox bis street;place;province;zip;country") - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_addresses_phone(self): - address = self.person.newChild(None, 'address', None) - address.newChild(None, 'phone', '01234-56789') + address = ET.SubElement(self.person, 'address') + ET.SubElement(address, 'phone').text = '01234-56789' self.expect.insert(6, "TEL:01234-56789") - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_urls_email(self): - url = self.person.newChild(None, 'url', None) - url.newProp('type', 'E-mail') - url.newProp('href', 'me@example.com') + attribs = {'type': 'E-mail', 'href': 'me@example.com'} + ET.SubElement(self.person, 'url', attrib=attribs) self.expect.insert(6, "EMAIL:me@example.com") - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_urls_emial_mailto(self): - url = self.person.newChild(None, 'url', None) - url.newProp('type', 'E-mail') - url.newProp('href', 'mailto:me@example.com') + attribs = {'type': 'E-mail', 'href': 'mailto:me@example.com'} + ET.SubElement(self.person, 'url', attrib=attribs) self.expect.insert(6, "EMAIL:me@example.com") - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_urls_url(self): - url = self.person.newChild(None, 'url', None) - url.newProp('type', 'Web Home') - url.newProp('href', 'http://www.example.org') + attribs = {'type': 'Web Home', 'href': 'http://www.example.org'} + ET.SubElement(self.person, 'url', attrib=attribs) self.expect.insert(6, "URL:http://www.example.org") - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_occupation_regular(self): - events = self.database.newChild(None, 'events', None) - event = events.newChild(None, 'event', None) - event.newProp('handle', '_e0000') - event.newProp('id', 'E0000') - event.newChild(None, 'type', 'Occupation') - event.newChild(None, 'description', 'carpenter') - evtref = self.person.newChild(None, 'eventref', None) - evtref.newProp('hlink', '_e0000') - evtref.newProp('role', 'Primary') - self.people.addPrevSibling(events) + events = ET.Element('events') + self.database.insert(1, events) + attribs = {'handle': '_e0000', 'id': 'E0000'} + event = ET.SubElement(events, 'event', attrib=attribs) + ET.SubElement(event, 'type').text = 'Occupation' + ET.SubElement(event, 'description').text = 'carpenter' + attribs = {'hlink': '_e0000', 'role': 'Primary'} + ET.SubElement(self.person, 'eventref', attrib=attribs) self.expect.insert(6, "ROLE:carpenter") - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') def test_write_occupation_lastdate(self): - events = self.database.newChild(None, 'events', None) - event = events.newChild(None, 'event', None) - event.newProp('handle', '_e0000') - event.newProp('id', 'E0000') - event.newChild(None, 'type', 'Occupation') - dateval = event.newChild(None, 'dateval', None) - dateval.newProp('val', '2011-02-28') - event.newChild(None, 'description', 'foreman') - event = events.newChild(None, 'event', None) - event.newProp('handle', '_e0001') - event.newProp('id', 'E0001') - event.newChild(None, 'type', 'Occupation') - dateval = event.newChild(None, 'dateval', None) - dateval.newProp('val', '2000-09-21') - event.newChild(None, 'description', 'carpenter') - evtref = self.person.newChild(None, 'eventref', None) - evtref.newProp('hlink', '_e0000') - evtref.newProp('role', 'Primary') - evtref = self.person.newChild(None, 'eventref', None) - evtref.newProp('hlink', '_e0001') - evtref.newProp('role', 'Primary') - self.people.addPrevSibling(events) + events = ET.Element('events') + self.database.insert(1, events) + attribs = {'handle': '_e0000', 'id': 'E0000'} + event = ET.SubElement(events, 'event', attrib=attribs) + ET.SubElement(event, 'type').text = 'Occupation' + ET.SubElement(event, 'dateval', val='2011-02-28') + ET.SubElement(event, 'description').text = 'foreman' + attribs = {'handle': '_e0001', 'id': 'E0001'} + event = ET.SubElement(events, 'event', attrib=attribs) + ET.SubElement(event, 'type').text = 'Occupation' + ET.SubElement(event, 'dateval', val='2000-09-21') + ET.SubElement(event, 'description').text = 'carpenter' + attribs = {'hlink': '_e0000', 'role': 'Primary'} + ET.SubElement(self.person, 'eventref', attrib=attribs) + attribs = {'hlink': '_e0001', 'role': 'Primary'} + ET.SubElement(self.person, 'eventref', attrib=attribs) self.expect.insert(6, "ROLE:foreman") - self.do_test(self.input_, "\r\n".join(self.expect) + '\r\n\r\n') + self.do_test(self.database, "\r\n".join(self.expect) + '\r\n\r\n') if __name__ == "__main__": unittest.main() diff --git a/gramps/plugins/importer/test/importvcard_test.py b/gramps/plugins/importer/test/importvcard_test.py index ce196f679..10ac28732 100644 --- a/gramps/plugins/importer/test/importvcard_test.py +++ b/gramps/plugins/importer/test/importvcard_test.py @@ -21,81 +21,63 @@ """ Unittest of import of VCard - -To be called from src directory. """ # in case of a failing test, add True as last parameter to do_test to see the output. from __future__ import print_function -import sys -import os -if sys.version_info[0] < 3: - from StringIO import StringIO -else: - from io import StringIO -import time import unittest +import time import subprocess -import libxml2 -import libxslt +import xml.etree.ElementTree as ET -from gramps.plugins.lib.libgrampsxml import GRAMPS_XML_VERSION -from gramps.gen.const import ROOT_DIR +from ...lib.libgrampsxml import GRAMPS_XML_VERSION from gramps.version import VERSION -from gramps.plugins.importer.importvcard import (VCardParser, fitin, - splitof_nameprefix) +from ..importvcard import VCardParser, fitin, splitof_nameprefix class VCardCheck(unittest.TestCase): def setUp(self): 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.header = """ - - + self.header = """
- \n +
""" % \ - (GRAMPS_XML_VERSION, GRAMPS_XML_VERSION, GRAMPS_XML_VERSION, - date[0], date[1], date[2], VERSION) + (GRAMPS_XML_VERSION, date[0], date[1], date[2], VERSION) expect_str = self.header + """U""" \ """Lastname
""" - self.gramps = libxml2.readDoc(expect_str, '', None, libxml2.XML_PARSE_NONET) - self.person = self.gramps.getRootElement().firstElementChild().\ - nextElementSibling().firstElementChild() - self.name = self.person.firstElementChild().nextElementSibling() + namespace = "http://gramps-project.org/xml/%s/" % GRAMPS_XML_VERSION + ET.register_namespace("", namespace) + self.gramps = ET.XML(expect_str) + self.person = self.gramps[1][0] + self.name = self.person[1] self.vcard = ["BEGIN:VCARD", "VERSION:3.0", "FN:Lastname", "N:Lastname;;;;", "END:VCARD"] - def tearDown(self): - self.style.freeStylesheet() - #self.gramps.freeDoc() # makes is crash + def canonicalize(self, doc): + handles = {} + for element in doc.iter("*"): + gramps_id = element.get('id') + if gramps_id is not None: + handles[element.get('handle')] = gramps_id + element.set('handle', gramps_id) + hlink = element.get('hlink') + if hlink is not None: + element.set('hlink', handles.get(hlink)) + if element.get('change') is not None: + del element.attrib['change'] + if element.text is not None and not element.text.strip(): + element.text = '' + if element.tail is not None and not element.tail.strip(): + element.tail = '' - def string2canonicalxml(self, input_str, buf): - if type(input_str) == type('string'): - doc = libxml2.readDoc(input_str, '', None, libxml2.XML_PARSE_NONET) - elif isinstance(input_str, libxml2.xmlDoc): - doc = input_str - else: - raise TypeError - param = {'replace_handles':"'ID'"} - canonical_doc = self.style.applyStylesheet(doc, param) - canonical_doc.saveFormatFileTo(buf, 'UTF-8', 1) - doc.freeDoc() - canonical_doc.freeDoc() - return + return ET.tostring(doc, encoding='utf-8') - def do_test(self, input_str, expect_str, debug=False): - expect_canonical_strfile = StringIO() - buf = libxml2.createOutputBuffer(expect_canonical_strfile, 'UTF-8') - self.string2canonicalxml(expect_str, buf) + def do_test(self, input_str, expect_doc, debug=False): + if debug: + print(input_str) process = subprocess.Popen('python Gramps.py ' '--config=preferences.eprefix:DEFAULT ' @@ -104,19 +86,15 @@ class VCardCheck(unittest.TestCase): stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - result_str, err_str = process.communicate(input_str) - result_canonical_strfile = StringIO() - buf2 = libxml2.createOutputBuffer(result_canonical_strfile, 'UTF-8') - self.string2canonicalxml(result_str, buf2) + result_str, err_str = process.communicate(input_str.encode('utf-8')) + result_doc = ET.XML(result_str) if debug: print(err_str) - print(result_canonical_strfile.getvalue()) - print(expect_canonical_strfile.getvalue()) - self.assertEqual(result_canonical_strfile.getvalue(), - expect_canonical_strfile.getvalue()) - expect_canonical_strfile.close() - result_canonical_strfile.close() + print(self.canonicalize(result_doc)) + print(self.canonicalize(expect_doc)) + self.assertEqual(self.canonicalize(result_doc), + self.canonicalize(expect_doc)) def test_base(self): self.do_test("\r\n".join(self.vcard), self.gramps) @@ -149,8 +127,8 @@ class VCardCheck(unittest.TestCase): def test_name_value_split_quoted_colon(self): self.vcard.insert(4, 'TEL;TYPE="FANCY:TYPE":01234-56789') - address = self.person.newChild(None, 'address', None) - address.newChild(None, 'phone', '01234-56789') + address = ET.SubElement(self.person, "address") + ET.SubElement(address, 'phone').text = '01234-56789' self.do_test("\r\n".join(self.vcard), self.gramps) def test_name_value_split_grouped(self): @@ -196,20 +174,20 @@ class VCardCheck(unittest.TestCase): def test_get_next_line_continuation(self): self.vcard.insert(4, "TEL:01234-\r\n 56789") - address = self.person.newChild(None, 'address', None) - address.newChild(None, 'phone', '01234-56789') + address = ET.SubElement(self.person, "address") + ET.SubElement(address, 'phone').text = '01234-56789' self.do_test("\r\n".join(self.vcard), self.gramps) def test_get_next_line_cr(self): self.vcard.insert(4, "TEL:01234-56789\r") - address = self.person.newChild(None, 'address', None) - address.newChild(None, 'phone', '01234-56789') + address = ET.SubElement(self.person, "address") + ET.SubElement(address, 'phone').text = '01234-56789' self.do_test("\r\n".join(self.vcard), self.gramps) def test_get_next_line_strip(self): self.vcard.insert(4, "TEL:01234-56789 ") - address = self.person.newChild(None, 'address', None) - address.newChild(None, 'phone', '01234-56789') + address = ET.SubElement(self.person, "address") + ET.SubElement(address, 'phone').text = '01234-56789' self.do_test("\r\n".join(self.vcard), self.gramps) def test_get_next_line_none(self): @@ -222,8 +200,8 @@ class VCardCheck(unittest.TestCase): def test_parse_vCard_file_lowercase(self): self.vcard.insert(4, "tel:01234-56789") - address = self.person.newChild(None, 'address', None) - address.newChild(None, 'phone', '01234-56789') + address = ET.SubElement(self.person, "address") + ET.SubElement(address, 'phone').text = '01234-56789' self.do_test("\r\n".join(self.vcard), self.gramps) def test_parse_vCard_unknown_property(self): @@ -234,14 +212,11 @@ class VCardCheck(unittest.TestCase): def test_next_person_no_end(self): self.vcard[4] = "BEGIN:VCARD" self.vcard.extend(["VERSION:3.0", "FN:Another", "N:Another;;;;", "END:VCARD"]) - people = self.gramps.getRootElement().firstElementChild().nextElementSibling() - person = people.newChild(None, 'person', None) - person.newProp('handle', 'I0001') - person.newProp('id', 'I0001') - person.newChild(None, 'gender', 'U') - name = person.newChild(None, 'name', None) - name.newProp('type', 'Birth Name') - name.newChild(None, 'surname', 'Another') + attribs = {'handle': 'I0001', 'id': 'I0001'} + person = ET.SubElement(self.gramps[1], "person", attribs) + ET.SubElement(person, 'gender').text = 'U' + name = ET.SubElement(person, 'name', {'type': 'Birth Name'}) + ET.SubElement(name, 'surname').text = 'Another' self.do_test("\r\n".join(self.vcard), self.gramps) def test_check_version(self): @@ -253,11 +228,13 @@ class VCardCheck(unittest.TestCase): self.vcard[2] = "FN:Lastname B A" self.vcard[3] = "N:Lastname;A;B;;" self.vcard.insert(4, "FN:Lastname A B") - name = self.person.firstElementChild().nextElementSibling() - surname = name.firstElementChild() - firstname = name.newChild(None, "first", "B A") - callname = name.newChild(None, "call", "A") - callname.addNextSibling(surname) + name = self.person[1] + first = ET.Element("first") + first.text = "B A" + name.insert(0, first) + call = ET.Element("call") + call.text = "A" + name.insert(1, call) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_name_parts_twice(self): @@ -267,26 +244,25 @@ class VCardCheck(unittest.TestCase): def test_add_name_regular(self): self.vcard[2] = "FN:Mr. Firstname Middlename Lastname Jr." self.vcard[3] = "N:Lastname;Firstname;Middlename;Mr.;Jr." - name = self.person.firstElementChild().nextElementSibling() - surname = name.firstElementChild() - firstname = name.newChild(None, 'first', 'Firstname Middlename') - firstname.addNextSibling(surname) - name.newChild(None, 'suffix', 'Jr.') - name.newChild(None, 'title', 'Mr.') + first = ET.Element('first') + first.text = 'Firstname Middlename' + self.name.insert(0, first) + ET.SubElement(self.name, 'suffix').text = 'Jr.' + ET.SubElement(self.name, 'title').text = 'Mr.' self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_name_multisurname(self): self.vcard[2] = "FN:Lastname Lastname2" self.vcard[3] = "N:Lastname,Lastname2;;;;" - surname = self.name.newChild(None, 'surname', 'Lastname2') + ET.SubElement(self.name, 'surname').text = 'Lastname2' self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_name_prefixsurname(self): self.vcard[2] = "FN:van d'Alembert" self.vcard[3] = "N:van d'Alembert;;;;" - surname = self.name.firstElementChild() - surname.setContent('Alembert') - surname.newProp('prefix', "van d'") + surname = self.name[0] + surname.text = 'Alembert' + surname.set('prefix', "van d'") self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_name_only_surname(self): @@ -296,91 +272,92 @@ class VCardCheck(unittest.TestCase): def test_add_name_upto_firstname(self): self.vcard[2] = "FN:Firstname Lastname" self.vcard[3] = "N:Lastname; Firstname;" - surname = self.name.firstElementChild() - first = self.name.newChild(None, 'first', 'Firstname') - first.addNextSibling(surname) + first = ET.Element('first') + first.text = 'Firstname' + self.name.insert(0, first) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_name_empty(self): self.vcard[2] = "FN:Lastname" self.vcard[3] = "N: " - people = self.gramps.getRootElement().firstElementChild().nextElementSibling() - people.unlinkNode() - people.freeNode() + self.gramps.remove(self.gramps[1]) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_firstname_regular(self): self.vcard[2] = "FN:A B Lastname" self.vcard[3] = "N:Lastname;A;B;;" - surname = self.name.firstElementChild() - firstname = self.name.newChild(None, 'first', 'A B') - firstname.addNextSibling(surname) + first = ET.Element('first') + first.text = 'A B' + self.name.insert(0, first) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_firstname_callname(self): self.vcard[2] = "FN:A B Lastname" self.vcard[3] = "N:Lastname;B;A;;" - surname = self.name.firstElementChild() - firstname = self.name.newChild(None, 'first', 'A B') - callname = self.name.newChild(None, 'call', 'B') - callname.addNextSibling(surname) + first = ET.Element('first') + first.text = 'A B' + self.name.insert(0, first) + call = ET.Element('call') + call.text = 'B' + self.name.insert(1, call) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_firstname_incomplete_fn(self): self.vcard[2] = "FN:A Lastname" self.vcard[3] = "N:Lastname;A;B;;" - surname = self.name.firstElementChild() - firstname = self.name.newChild(None, 'first', 'A B') - firstname.addNextSibling(surname) + first = ET.Element('first') + first.text = 'A B' + self.name.insert(0, first) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_firstname_middle(self): self.vcard[2] = "FN:A B C Lastname" self.vcard[3] = "N:Lastname;B;A C;;" - surname = self.name.firstElementChild() - firstname = self.name.newChild(None, 'first', 'A B C') - callname = self.name.newChild(None, 'call', 'B') - callname.addNextSibling(surname) + first = ET.Element('first') + first.text = 'A B C' + self.name.insert(0, first) + call = ET.Element('call') + call.text = 'B' + self.name.insert(1, call) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_firstname_fn_not_given(self): self.vcard[2] = "FN:B Lastname" self.vcard[3] = "N:Lastname;A;B;;" - surname = self.name.firstElementChild() - firstname = self.name.newChild(None, 'first', 'A B') - firstname.addNextSibling(surname) + first = ET.Element('first') + first.text = 'A B' + self.name.insert(0, first) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_firstname_no_addnames(self): self.vcard[2] = "FN:A Lastname" self.vcard[3] = "N:Lastname;A;;;" - surname = self.name.firstElementChild() - firstname = self.name.newChild(None, 'first', 'A') - firstname.addNextSibling(surname) + first = ET.Element('first') + first.text = 'A' + self.name.insert(0, first) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_firstname_no_givenname(self): self.vcard[2] = "FN:A Lastname" self.vcard[3] = "N:Lastname;;A;;" - surname = self.name.firstElementChild() - firstname = self.name.newChild(None, 'first', 'A') - firstname.addNextSibling(surname) + first = ET.Element('first') + first.text = 'A' + self.name.insert(0, first) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_firstname_no_fn(self): self.vcard[2] = "FN:" self.vcard[3] = "N:Lastname;;A;;" - surname = self.name.firstElementChild() - firstname = self.name.newChild(None, 'first', 'A') - firstname.addNextSibling(surname) + first = ET.Element('first') + first.text = 'A' + self.name.insert(0, first) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_nicknames_single(self): self.vcard.insert(4, "NICKNAME:Ton") - name = self.person.newChild(None, "name", None) - name.newProp("alt", "1") - name.newProp("type", "Birth Name") - name.newChild(None, "nick", "Ton") + attribs = {"alt": "1", "type": "Birth Name"} + name = ET.SubElement(self.person, 'name', attribs) + ET.SubElement(name, 'nick').text = "Ton" self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_nicknames_empty(self): @@ -389,39 +366,37 @@ class VCardCheck(unittest.TestCase): def test_add_nicknames_multiple(self): self.vcard.insert(4, "NICKNAME:A,B\,C") - name = self.person.newChild(None, "name", None) - name.newProp("alt", "1") - name.newProp("type", "Birth Name") - name.newChild(None, "nick", "A") - name = self.person.newChild(None, "name", None) - name.newProp("alt", "1") - name.newProp("type", "Birth Name") - name.newChild(None, "nick", "B,C") + attribs = {"alt": "1", "type": "Birth Name"} + name = ET.SubElement(self.person, 'name', attribs) + ET.SubElement(name, 'nick').text = "A" + attribs = {"alt": "1", "type": "Birth Name"} + name = ET.SubElement(self.person, 'name', attribs) + ET.SubElement(name, 'nick').text = "B,C" self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_address_all(self): self.vcard.insert(4, "ADR:box 1;bis;Broadway 11; New York; New York; NY1234; USA") - address = self.person.newChild(None, 'address', None) - address.newChild(None, 'street', 'box 1 bis Broadway 11') - address.newChild(None, 'city', 'New York') - address.newChild(None, 'state', 'New York') - address.newChild(None, 'country', 'USA') - address.newChild(None, 'postal', 'NY1234') + address = ET.SubElement(self.person, 'address') + ET.SubElement(address, 'street').text = 'box 1 bis Broadway 11' + ET.SubElement(address, 'city').text = 'New York' + ET.SubElement(address, 'state').text = 'New York' + ET.SubElement(address, 'country').text = 'USA' + ET.SubElement(address, 'postal').text = 'NY1234' self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_address_too_many(self): self.vcard.insert(4, "ADR:;;Broadway 11; New\,York; ;; USA; Earth") - address = self.person.newChild(None, 'address', None) - address.newChild(None, 'street', 'Broadway 11') - address.newChild(None, 'city', 'New,York') - address.newChild(None, 'country', 'USA') + address = ET.SubElement(self.person, 'address') + ET.SubElement(address, 'street').text = 'Broadway 11' + ET.SubElement(address, 'city').text = 'New,York' + ET.SubElement(address, 'country').text = 'USA' self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_address_too_few(self): self.vcard.insert(4, "ADR:;;Broadway 11; New York") - address = self.person.newChild(None, 'address', None) - address.newChild(None, 'street', 'Broadway 11') - address.newChild(None, 'city', 'New York') + address = ET.SubElement(self.person, 'address') + ET.SubElement(address, 'street').text = 'Broadway 11' + ET.SubElement(address, 'city').text = 'New York' self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_address_empty(self): @@ -430,8 +405,8 @@ class VCardCheck(unittest.TestCase): def test_add_phone_regular(self): self.vcard.insert(4, "TEL:01234-56789") - address = self.person.newChild(None, 'address', None) - address.newChild(None, 'phone', '01234-56789') + address = ET.SubElement(self.person, 'address') + ET.SubElement(address, 'phone').text = '01234-56789' self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_phone_empty(self): @@ -440,66 +415,50 @@ class VCardCheck(unittest.TestCase): def test_add_birthday_regular(self): self.vcard.insert(4, 'BDAY:2001-09-28') - eventref = self.person.newChild(None, 'eventref', None) - eventref.newProp('hlink', 'E0000') - eventref.newProp('role', 'Primary') - events = self.gramps.getRootElement().newChild(None, 'events', None) - event = events.newChild(None, 'event', None) - event.newProp('handle', 'E0000') - event.newProp('id', 'E0000') - event.newChild(None, 'type', 'Birth') - date = event.newChild(None, 'dateval', None) - date.newProp('val', '2001-09-28') - people = self.gramps.getRootElement().firstElementChild().nextElementSibling() - events.addNextSibling(people) + attribs = {'hlink': 'E0000', 'role': 'Primary'} + eventref = ET.SubElement(self.person, 'eventref', attribs) + events = ET.Element('events') + self.gramps.insert(1, events) + attribs = {'handle': 'E0000', 'id': 'E0000'} + event = ET.SubElement(events, 'event', attribs) + ET.SubElement(event, 'type').text = 'Birth' + ET.SubElement(event, 'dateval', {'val': '2001-09-28'}) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_birthday_datetime(self): self.vcard.insert(4, 'BDAY:2001-09-28T09:23:47Z') - eventref = self.person.newChild(None, 'eventref', None) - eventref.newProp('hlink', 'E0000') - eventref.newProp('role', 'Primary') - events = self.gramps.getRootElement().newChild(None, 'events', None) - event = events.newChild(None, 'event', None) - event.newProp('handle', 'E0000') - event.newProp('id', 'E0000') - event.newChild(None, 'type', 'Birth') - date = event.newChild(None, 'dateval', None) - date.newProp('val', '2001-09-28') - people = self.gramps.getRootElement().firstElementChild().nextElementSibling() - events.addNextSibling(people) + attribs = {'hlink': 'E0000', 'role': 'Primary'} + eventref = ET.SubElement(self.person, 'eventref', attribs) + events = ET.Element('events') + self.gramps.insert(1, events) + attribs = {'handle': 'E0000', 'id': 'E0000'} + event = ET.SubElement(events, 'event', attribs) + ET.SubElement(event, 'type').text = 'Birth' + ET.SubElement(event, 'dateval', {'val': '2001-09-28'}) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_birthday_no_dash(self): self.vcard.insert(4, 'BDAY:20010928') - eventref = self.person.newChild(None, 'eventref', None) - eventref.newProp('hlink', 'E0000') - eventref.newProp('role', 'Primary') - events = self.gramps.getRootElement().newChild(None, 'events', None) - event = events.newChild(None, 'event', None) - event.newProp('handle', 'E0000') - event.newProp('id', 'E0000') - event.newChild(None, 'type', 'Birth') - date = event.newChild(None, 'dateval', None) - date.newProp('val', '2001-09-28') - people = self.gramps.getRootElement().firstElementChild().nextElementSibling() - events.addNextSibling(people) + attribs = {'hlink': 'E0000', 'role': 'Primary'} + eventref = ET.SubElement(self.person, 'eventref', attribs) + events = ET.Element('events') + self.gramps.insert(1, events) + attribs = {'handle': 'E0000', 'id': 'E0000'} + event = ET.SubElement(events, 'event', attribs) + ET.SubElement(event, 'type').text = 'Birth' + ET.SubElement(event, 'dateval', {'val': '2001-09-28'}) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_birthday_one_dash(self): self.vcard.insert(4, 'BDAY:2001-0928') - eventref = self.person.newChild(None, 'eventref', None) - eventref.newProp('hlink', 'E0000') - eventref.newProp('role', 'Primary') - events = self.gramps.getRootElement().newChild(None, 'events', None) - event = events.newChild(None, 'event', None) - event.newProp('handle', 'E0000') - event.newProp('id', 'E0000') - event.newChild(None, 'type', 'Birth') - date = event.newChild(None, 'dateval', None) - date.newProp('val', '2001-09-28') - people = self.gramps.getRootElement().firstElementChild().nextElementSibling() - events.addNextSibling(people) + attribs = {'hlink': 'E0000', 'role': 'Primary'} + eventref = ET.SubElement(self.person, 'eventref', attribs) + events = ET.Element('events') + self.gramps.insert(1, events) + attribs = {'handle': 'E0000', 'id': 'E0000'} + event = ET.SubElement(events, 'event', attribs) + ET.SubElement(event, 'type').text = 'Birth' + ET.SubElement(event, 'dateval', {'val': '2001-09-28'}) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_birthday_ddmmyyyy(self): @@ -518,17 +477,14 @@ class VCardCheck(unittest.TestCase): def test_add_occupation_regular(self): self.vcard.insert(4, "ROLE:scarecrow") - eventref = self.person.newChild(None, 'eventref', None) - eventref.newProp('hlink', 'E0000') - eventref.newProp('role', 'Primary') - events = self.gramps.getRootElement().newChild(None, 'events', None) - event = events.newChild(None, 'event', None) - event.newProp('handle', 'E0000') - event.newProp('id', 'E0000') - event.newChild(None, 'type', 'Occupation') - event.newChild(None, 'description', 'scarecrow') - people = self.gramps.getRootElement().firstElementChild().nextElementSibling() - events.addNextSibling(people) + attribs = {'hlink': 'E0000', 'role': 'Primary'} + eventref = ET.SubElement(self.person, 'eventref', attribs) + events = ET.Element('events') + self.gramps.insert(1, events) + attribs = {'handle': 'E0000', 'id': 'E0000'} + event = ET.SubElement(events, 'event', attribs) + ET.SubElement(event, 'type').text = 'Occupation' + ET.SubElement(event, 'description').text = 'scarecrow' self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_occupation_empty(self): @@ -537,9 +493,8 @@ class VCardCheck(unittest.TestCase): def test_add_url_regular(self): self.vcard.insert(4, "URL:http://www.example.com") - url = self.person.newChild(None, 'url', None) - url.newProp('href', 'http://www.example.com') - url.newProp('type', 'Unknown') + attribs = {'href': 'http://www.example.com', 'type': 'Unknown'} + ET.SubElement(self.person, 'url', attribs) self.do_test("\r\n".join(self.vcard), self.gramps) def test_add_url_empty(self): @@ -548,9 +503,8 @@ class VCardCheck(unittest.TestCase): def test_add_email(self): self.vcard.insert(4, "EMAIL:me@example.org") - url = self.person.newChild(None, 'url', None) - url.newProp('href', 'me@example.org') - url.newProp('type', 'E-mail') + attribs = {'href': 'me@example.org', 'type': 'E-mail'} + ET.SubElement(self.person, 'url', attribs) self.do_test("\r\n".join(self.vcard), self.gramps)