[PATCH eac] [py3] Update the 0.9.0 version to python 3

Philippe Pepiot philippe.pepiot at logilab.fr
Thu Nov 28 09:40:37 CET 2019


# HG changeset patch
# User Guillaume Vandevelde <gvandevelde at logilab.fr>
# Date 1573032845 -3600
#      Wed Nov 06 10:34:05 2019 +0100
# Node ID 7c6bca9c24f6d7b07ecebe35cc7b11c254b93789
# Parent  d436f7f694981c1d9b0c94bc6c29067ed28214e0
# Parent  146d308ff8e3bf23826a59c8eb498c57e2590b58
# Available At https://hg.logilab.org/review/cubes/eac
#              hg pull https://hg.logilab.org/review/cubes/eac -r 7c6bca9c24f6
[py3] Update the 0.9.0 version to python 3

Merge branch 0.8

diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -24,4 +24,6 @@ 9ad41f3163f3394b8b2a6e8399a0c08c51b98507
 c2750fb7337f9ca940d42c548f2815bdde831a5a 0.8.0
 8b17ed8e18aa7a5b6c98f4cc8eac6c7de46e788a 0.8.1
 08d8650815c9302771560eecd38eb5e680ac46df 0.8.2
+2fda0621acc4955f13d53d6c8a8938c7dccc65a5 0.8.3
+01538af6f4cd381c45af65523517053d1a6f3f4f 0.8.4
 16721867887ceec47313cbcf557d6f9ad7f569cd 0.9.0
diff --git a/cubicweb_eac/entities.py b/cubicweb_eac/entities.py
--- a/cubicweb_eac/entities.py
+++ b/cubicweb_eac/entities.py
@@ -73,7 +73,8 @@ class AuthorityRecord(AnyEntity):
     @property
     def other_record_ids(self):
         return sorted([(r.local_type, r.value)
-                       for r in self.reverse_eac_other_record_id_of])
+                       for r in self.reverse_eac_other_record_id_of],
+                      key=lambda x: (x[0] or "", x[1]))
 
 
 class AgentKind(AnyEntity):
@@ -431,7 +432,7 @@ class AuthorityRecordEACAdapter(Abstract
             name = text_type(self.entity.eid)
         return u'EAC_{0}.xml'.format(name)
 
-    def dump(self):
+    def dump(self, _encoding=None):
         """Return an XML string representing the given agent using the EAC-CPF schema."""
         # Keep related activities since they are used multiple times
         self.activities = sorted(self.entity.reverse_generated, key=lambda x: x.start, reverse=True)
@@ -444,7 +445,15 @@ class AuthorityRecordEACAdapter(Abstract
         self.control_element(eac_cpf_elt)
         self.cpfdescription_element(eac_cpf_elt)
         tree = etree.ElementTree(eac_cpf_elt)
-        return etree.tostring(tree, xml_declaration=True, encoding=self.encoding, pretty_print=True)
+        encoding = _encoding if _encoding is not None else self.encoding
+        kwargs = {
+            'pretty_print': True,
+            'encoding': encoding,
+            'xml_declaration': True,
+        }
+        if encoding is text_type:
+            kwargs['xml_declaration'] = False
+        return etree.tostring(tree, **kwargs)
 
     def control_element(self, eac_cpf_elt):
         control_elt = self.element('control', parent=eac_cpf_elt)
diff --git a/test/export-roundtrip.rst b/test/export-roundtrip.rst
--- a/test/export-roundtrip.rst
+++ b/test/export-roundtrip.rst
@@ -3,12 +3,14 @@ A roundtrip export test case
 
 .. code-block:: python
 
+    >>> from __future__ import print_function
+    >>> from six import text_type
     >>> fpath = self.datapath('FRAD033_EAC_00001_simplified_export.xml')
     >>> created, updated = testutils.eac_import(cnx, fpath)
     >>> record = cnx.find('AuthorityRecord', isni=u'22330001300016').one()
-    >>> generated_eac = record.cw_adapt_to('EAC-CPF').dump()
-    >>> print generated_eac
-    <?xml version='1.0' encoding='utf-8'?>
+    >>> generated_eac = record.cw_adapt_to('EAC-CPF').dump(_encoding=text_type)
+    >>> print(generated_eac)
+    <?xml version='1.0'?>
     <eac-cpf xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="urn:isbn:1-931666-33-4" xsi:schemaLocation="urn:isbn:1-931666-33-4 http://eac.staatsbibliothek-berlin.de/schema/cpf.xsd">
       <control>
         <recordId>987654321</recordId>
diff --git a/test/export-simple.rst b/test/export-simple.rst
--- a/test/export-simple.rst
+++ b/test/export-simple.rst
@@ -3,6 +3,8 @@ A simple export test case
 
 .. code-block:: python
 
+    >>> from __future__ import print_function
+    >>> from six import text_type
     >>> from cubicweb import Binary
     >>> record = testutils.authority_record(cnx, u'666', u'Charlie')
     >>> home_addr = cnx.create_entity(
@@ -23,17 +25,17 @@ A simple export test case
     >>> resource_relation = cnx.create_entity(
     ...     'EACResourceRelation', resource_relation_resource=uri,
     ...     resource_relation_agent=record,
-    ...     xml_wrap=Binary('<pif><paf>pouf</paf></pif>'))
+    ...     xml_wrap=Binary(b'<pif><paf>pouf</paf></pif>'))
     >>> record2 = testutils.authority_record(
     ...     cnx, u'2', u'does not matter', kind=u'authority',
     ...     cwuri=u'http://www.example.org/record2')
     >>> chronological_relation = cnx.create_entity(
     ...     'ChronologicalRelation', entry=u'Super Service',
     ...     chronological_predecessor=record2, chronological_successor=record,
-    ...     xml_wrap=Binary('<plip>plop</plip>'))
+    ...     xml_wrap=Binary(b'<plip>plop</plip>'))
     >>> cnx.commit()
-    >>> print record.cw_adapt_to('EAC-CPF').dump()
-    <?xml version='1.0' encoding='utf-8'?>
+    >>> print(record.cw_adapt_to('EAC-CPF').dump(_encoding=text_type))
+    <?xml version='1.0'?>
     <eac-cpf xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="urn:isbn:1-931666-33-4" xsi:schemaLocation="urn:isbn:1-931666-33-4 http://eac.staatsbibliothek-berlin.de/schema/cpf.xsd">
       <control>
         <recordId>666</recordId>
diff --git a/test/test_dataimport.py b/test/test_dataimport.py
--- a/test/test_dataimport.py
+++ b/test/test_dataimport.py
@@ -24,7 +24,7 @@ import sys
 import unittest
 
 from lxml import etree
-from six import reraise
+from six import PY2, reraise
 from six.moves import map
 from contextlib import contextmanager
 
@@ -65,6 +65,15 @@ def extentities2dict(entities):
     return edict
 
 
+def mk_extid_generator():
+    """Predicate extid_generator."""
+    gen = map(str, count())
+    if PY2:
+        return gen.next
+    else:
+        return gen.__next__
+
+
 @contextmanager
 def ctx_assert(ctx):
     try:
@@ -87,14 +96,15 @@ class EACXMLParserTC(unittest.TestCase):
     def file_extentities(self, fname):
         fpath = self.datapath(fname)
         import_log = SimpleImportLog(fpath)
-        # Use a predictable extid_generator.
-        extid_generator = map(str, count()).next
         importer = dataimport.EACCPFImporter(fpath, import_log, mock_,
-                                             extid_generator=extid_generator)
+                                             extid_generator=mk_extid_generator())
         return importer.external_entities()
 
     def test_parse_FRAD033_EAC_00001(self):
-        _gen_extid = map(str, (x for x in count() if x not in (2, 38))).next
+        if PY2:
+            _gen_extid = map(str, (x for x in count() if x not in (2, 38))).next
+        else:
+            _gen_extid = map(str, (x for x in count() if x not in (2, 38))).__next__
         expected = [
             ('EACOtherRecordId', _gen_extid(),
              {'eac_other_record_id_of': set(['authorityrecord-FRAD033_EAC_00001']),
@@ -488,10 +498,9 @@ class EACXMLParserTC(unittest.TestCase):
              {'chronological_predecessor': set(['authorityrecord-FRAD033_EAC_00001']),
               'chronological_successor': set(['/dev/null']),
               'date_relation': set(['56']),
-              'xml_wrap': set(['<gloups xmlns="urn:isbn:1-931666-33-4"'
-                               u' xmlns:xsi="http://www.w3.org/2001/XML'
-                               u'Schema-instance" xmlns:xlink="http://'
-                               u'www.w3.org/1999/xlink">hips</gloups>']),
+              'xml_wrap': set([b'<gloups xmlns="urn:isbn:1-931666-33-4" xmlns:xsi="http://www'
+                               b'.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.'
+                               b'org/1999/xlink">hips</gloups>']),
               'entry': set([u'Trash']),
               },
              ),
@@ -505,9 +514,9 @@ class EACXMLParserTC(unittest.TestCase):
               'entry': [u'Trash'],
               'identity_from': ['authorityrecord-FRAD033_EAC_00001'],
               'identity_to': ['/dev/null'],
-              'xml_wrap': set([u'<gloups xmlns="urn:isbn:1-931666-33-4" '
-                               u'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
-                               u'xmlns:xlink="http://www.w3.org/1999/xlink">hips</gloups>'])}
+              'xml_wrap': set([b'<gloups xmlns="urn:isbn:1-931666-33-4" xmlns:xsi="http://www'
+                               b'.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.'
+                               b'org/1999/xlink">hips</gloups>'])}
              ),
             ('DateEntity', _gen_extid(),
              {'start_date': [datetime.date(2042, 1, 1)],
@@ -543,10 +552,9 @@ class EACXMLParserTC(unittest.TestCase):
               'resource_relation_resource': set([
                   'http://gael.gironde.fr/ead.html?id=FRAD033_IR_N']),
               'resource_relation_agent': set(['authorityrecord-FRAD033_EAC_00001']),
-              'xml_wrap': set(['<he xmlns="urn:isbn:1-931666-33-4" '
-                               u'xmlns:xlink="http://www.w3.org/1999'
-                               u'/xlink" xmlns:xsi="http://www.w3.org'
-                               u'/2001/XMLSchema-instance">joe</he>'])
+              'xml_wrap': set([b'<he xmlns="urn:isbn:1-931666-33-4" xmlns:xlink="http://www.w'
+                               b'3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchem'
+                               b'a-instance">joe</he>'])
               },
              ),
             ('DateEntity', _gen_extid(),
@@ -567,17 +575,17 @@ class EACXMLParserTC(unittest.TestCase):
                                                  'id=FRAD033_IR_N']),
               'relation_entry': set([u'Alumni communication\n\tmanagement, '
                                      'University of\n\tGlasgow\n\t']),
-              'xml_wrap': set(['<mods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
-                               u' xmlns="urn:isbn:1-931666-33-4" xmlns:xlink="http://www.w3'
-                               u'.org/1999/xlink" xsi:schemaLocation="http://www.loc.gov'
-                               u'/mods/v3 http:         //www.loc.gov/mods/v3/mods-3-3.xsd'
-                               u'">\n\t    <titleInfo>\n\t      <title>Artisti trentini'
-                               u' tra le due\n\t      guerre\n\t      </title>\n\t    </titleInfo'
-                               u'>\n\t    <name>\n\t      <namePart type="given">Nicoletta'
-                               u'\n\t      </namePart>\n\t      <namePart type="family'
-                               u'">Boschiero\n\t      </namePart>\n\t      <role>\n\t\t<roleTerm'
-                               u' type="text">autore\n\t\t</roleTerm>\n\t      </role>\n\t'
-                               u'    </name>\n\t  </mods>\n\t']),
+              'xml_wrap': set([b'<mods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
+                               b'xmlns="urn:isbn:1-931666-33-4" xmlns:xlink="http://www.w3.or'
+                               b'g/1999/xlink" xsi:schemaLocation="http://www.loc.gov/mods/v3'
+                               b' http:         //www.loc.gov/mods/v3/mods-3-3.xsd">\n\t    <ti'
+                               b'tleInfo>\n\t      <title>Artisti trentini tra le due\n\t    '
+                               b'  guerre\n\t      </title>\n\t    </titleInfo>\n\t    <nam'
+                               b'e>\n\t      <namePart type="given">Nicoletta\n\t      </name'
+                               b'Part>\n\t      <namePart type="family">Boschiero\n\t      </'
+                               b'namePart>\n\t      <role>\n\t\t<roleTerm type="text">autore\n\t'
+                               b'\t</roleTerm>\n\t      </role>\n\t    </name>\n\t  </mods>\n'
+                               b'\t']),
               'xml_attributes': set([u'{"{http://www.w3.org/1999/xlink}actuate": '
                                      u'"onLoad", "{http://www.w3.org/1999/xlink}arcrole": '
                                      u'"http://test_arcrole.lol.com", '
@@ -691,10 +699,8 @@ class EACXMLParserTC(unittest.TestCase):
         expected = [ExtEntity(*vals) for vals in expected]
         fpath = self.datapath('FRAD033_EAC_00001_simplified.xml')
         import_log = SimpleImportLog(fpath)
-        # Use a predictable extid_generator.
-        extid_generator = map(str, count()).next
         importer = dataimport.EACCPFImporter(fpath, import_log, mock_,
-                                             extid_generator=extid_generator)
+                                             extid_generator=mk_extid_generator())
         entities = list(importer.external_entities())
         # Used for an easier handling of the order error while generating the 2 lists
         self.check_order_entities(entities, expected)
@@ -702,7 +708,7 @@ class EACXMLParserTC(unittest.TestCase):
         visited = set([])
         for x in importer._visited.values():
             visited.update(x)
-        self.assertItemsEqual(visited, [x.extid for x in expected])
+        self.assertCountEqual(visited, [x.extid for x in expected])
         # Gather not-visited tag by name and group source lines.
         not_visited = {}
         for tagname, sourceline in importer.not_visited():
@@ -833,10 +839,10 @@ class EACXMLParserTC(unittest.TestCase):
     def test_errors(self):
         log = SimpleImportLog('<dummy>')
         with self.assertRaises(dataimport.InvalidXML):
-            importer = dataimport.EACCPFImporter(BytesIO('no xml'), log, mock_)
+            importer = dataimport.EACCPFImporter(BytesIO(b'no xml'), log, mock_)
             list(importer.external_entities())
         with self.assertRaises(dataimport.MissingTag):
-            importer = dataimport.EACCPFImporter(BytesIO('<xml/>'), log, mock_)
+            importer = dataimport.EACCPFImporter(BytesIO(b'<xml/>'), log, mock_)
             list(importer.external_entities())
 
 
@@ -963,9 +969,9 @@ class EACDataImportTC(CubicWebTC):
         self.assertEqual(exturi.uri,
                          u'http://gael.gironde.fr/ead.html?id=FRAD033_IR_N')
         self.assertEqual(rrelation.xml_wrap.getvalue(),
-                         u'<he xmlns="urn:isbn:1-931666-33-4" xmlns:xlink="http'
-                         u'://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org'
-                         u'/2001/XMLSchema-instance">joe</he>')
+                         b'<he xmlns="urn:isbn:1-931666-33-4" xmlns:xlink="http'
+                         b'://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org'
+                         b'/2001/XMLSchema-instance">joe</he>')
         self.assertEqual(rrelation.json_attrs, {u"{http://www.w3.org/1999/xlink}actuate":
                                                 u"onRequest",
                                                 u"{http://www.w3.org/1999/xlink}show": u"new",
@@ -982,17 +988,17 @@ class EACDataImportTC(CubicWebTC):
                          u'Alumni communication\n\tmanagement, '
                          'University of\n\tGlasgow\n\t')
         self.assertEqual(func_relation.xml_wrap.getvalue(),
-                         u'<mods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
-                         u' xmlns="urn:isbn:1-931666-33-4" xmlns:xlink="http://www.w3'
-                         u'.org/1999/xlink" xsi:schemaLocation="http://www.loc.gov'
-                         u'/mods/v3 http:         //www.loc.gov/mods/v3/mods-3-3.xsd'
-                         u'">\n\t    <titleInfo>\n\t      <title>Artisti trentini tra'
-                         u' le due\n\t      guerre\n\t      </title>\n\t    </titleInfo>\n'
-                         u'\t    <name>\n\t      <namePart type="given">Nicoletta\n\t'
-                         u'      </namePart>\n\t      <namePart type="family">Boschiero\n'
-                         u'\t      </namePart>\n\t      <role>\n\t\t<roleTerm type="text'
-                         u'">autore\n\t\t</roleTerm>\n\t      </role>\n\t    </name>\n\t'
-                         u'  </mods>\n\t')
+                         b'<mods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
+                         b' xmlns="urn:isbn:1-931666-33-4" xmlns:xlink="http://www.w3'
+                         b'.org/1999/xlink" xsi:schemaLocation="http://www.loc.gov'
+                         b'/mods/v3 http:         //www.loc.gov/mods/v3/mods-3-3.xsd'
+                         b'">\n\t    <titleInfo>\n\t      <title>Artisti trentini tra'
+                         b' le due\n\t      guerre\n\t      </title>\n\t    </titleInfo>\n'
+                         b'\t    <name>\n\t      <namePart type="given">Nicoletta\n\t'
+                         b'      </namePart>\n\t      <namePart type="family">Boschiero\n'
+                         b'\t      </namePart>\n\t      <role>\n\t\t<roleTerm type="text'
+                         b'">autore\n\t\t</roleTerm>\n\t      </role>\n\t    </name>\n\t'
+                         b'  </mods>\n\t')
         self.assertEqual(func_relation.function_relation_agent[0], record)
         self.assertEqual(func_relation.function_relation_function[0].uri,
                          u'http://gael.gironde.fr/ead.html?id=FRAD033_IR_N')
diff --git a/test/test_entities.py b/test/test_entities.py
--- a/test/test_entities.py
+++ b/test/test_entities.py
@@ -18,6 +18,7 @@
 
 
 from lxml import etree
+from six import text_type
 
 from cubicweb.devtools.testlib import CubicWebTC
 
@@ -57,7 +58,7 @@ class EACExportTC(CubicWebTC):
             tag, = serializer._eac_richstring_paragraph_elements(
                 mandate, 'description')
         self.assertEqual(tag.tag, 'span')
-        self.assertIn(desc, etree.tostring(tag))
+        self.assertIn(desc, etree.tostring(tag, encoding=text_type))
 
     def test_richstring_html_multiple_elements(self):
         with self.admin_access.cnx() as cnx:
@@ -73,8 +74,8 @@ class EACExportTC(CubicWebTC):
                 mandate, 'description')
         self.assertEqual(h1.tag, 'h1')
         self.assertEqual(a.tag, 'a')
-        self.assertIn(etree.tostring(h1), desc[0])
-        self.assertIn(etree.tostring(a), desc[1])
+        self.assertIn(etree.tostring(h1, encoding=text_type), desc[0])
+        self.assertIn(etree.tostring(a, encoding=text_type), desc[1])
 
     def test_richstring_markdown(self):
         with self.admin_access.cnx() as cnx:
@@ -93,7 +94,7 @@ class EACExportTC(CubicWebTC):
             tag, = serializer._eac_richstring_paragraph_elements(
                 mandate, 'description')
         self.assertEqual(tag.tag, 'p')
-        self.assertIn(desc_html, etree.tostring(tag))
+        self.assertIn(desc_html, etree.tostring(tag, encoding=text_type))
 
     def test_richstring_rest(self):
         with self.admin_access.cnx() as cnx:
@@ -112,7 +113,7 @@ class EACExportTC(CubicWebTC):
             ptag, = serializer._eac_richstring_paragraph_elements(
                 mandate, 'description')
         self.assertEqual(ptag.tag, 'p')
-        self.assertIn(desc_html, etree.tostring(ptag))
+        self.assertIn(desc_html, etree.tostring(ptag, encoding=text_type))
 
     def test_richstring_empty(self):
         def check(authority_record):
diff --git a/test/test_views.py b/test/test_views.py
--- a/test/test_views.py
+++ b/test/test_views.py
@@ -15,6 +15,7 @@
 # with this program. If not, see <http://www.gnu.org/licenses/>.
 """cubicweb-eac test for views."""
 
+import io
 try:
     import unittest2 as unittest
 except ImportError:
@@ -37,7 +38,7 @@ class FuncViewsTC(CubicWebTC):
         with self.admin_access.web_request() as req:
             # simply test the form properly render and is well formed
             self.view(regid, req=req, template=None)
-            fields = {'file': (fname, open(self.datapath(fname)))}
+            fields = {'file': (fname, io.open(self.datapath(fname), 'rb'))}
             req.form = self.fake_form(regid, fields)
             # now actually test the import
             req.view(regid)
@@ -54,7 +55,7 @@ class FuncViewsTC(CubicWebTC):
         with self.admin_access.web_request() as req:
             # simply test the form properly render and is well formed
             self.view(regid, req=req, template=None)
-            fields = {'file': (fname, open(self.datapath(fname)))}
+            fields = {'file': (fname, io.open(self.datapath(fname), 'rb'))}
             req.form = self.fake_form(regid, fields)
             # now actually test the import
             html = req.view(regid)
@@ -66,7 +67,7 @@ class FuncViewsTC(CubicWebTC):
         regid = 'eac.import'
         fname = 'invalid_xml.xml'
         with self.admin_access.web_request() as req:
-            fields = {'file': (fname, open(self.datapath(fname)))}
+            fields = {'file': (fname, io.open(self.datapath(fname), 'rb'))}
             req.form = self.fake_form(regid, fields)
             # now actually test the import
             html = req.view(regid)
@@ -76,7 +77,7 @@ class FuncViewsTC(CubicWebTC):
         regid = 'eac.import'
         fname = 'missing_tag.xml'
         with self.admin_access.web_request() as req:
-            fields = {'file': (fname, open(self.datapath(fname)))}
+            fields = {'file': (fname, io.open(self.datapath(fname), 'rb'))}
             req.form = self.fake_form(regid, fields)
             # now actually test the import
             html = req.view(regid)
@@ -105,7 +106,7 @@ class FuncViewsTC(CubicWebTC):
             cnx.create_entity('EACResourceRelation',
                               resource_relation_agent=bob,
                               resource_relation_resource=uri,
-                              xml_wrap=Binary('<plip>plop</plip>'))
+                              xml_wrap=Binary(b'<plip>plop</plip>'))
             cnx.commit()
         with self.admin_access.web_request() as req:
             rset = req.find('EACResourceRelation')
diff --git a/tox.ini b/tox.ini
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = py27,flake8,check-manifest
+envlist = py27,py3,flake8,check-manifest
 
 [testenv]
 deps =




More information about the saem-devel mailing list