Yet another batch of py3 patches.

We're getting closer: if this was merged, my WIP branch that passes
ipapython & ipalib tests under py3 would currently be down to:
 8 files changed, 73 insertions(+), 23 deletions(-)

-- 
Petr Viktorin
From d2689e85c3f5ffcf30d3524740c45a648d134110 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Tue, 6 Oct 2015 13:54:33 +0200
Subject: [PATCH] Handle binascii.Error from base64.b64decode()

In Python 3, the base64.b64decode function raises binascii.Error (a ValueError
subclass) when it finds incorrect padding. In Python 2 it raises TypeError.

Callers should usually handle ValueError; unless they are specifically
concerned with handling base64 padding issues).

In some cases, callers should handle ValueError:
- ipalib.pkcs10 (get_friendlyname, load_certificate_request): callers should
  handle ValueError
- ipalib.x509 (load_certificate*, get_*): callers should handle ValueError

In other cases ValueError is handled:
- ipalib.parameters
- ipapython.ssh
- ipalib.rpc (json_decode_binary - callers already expect ValueError)
- ipaserver.install.ldapupdate

Elsewhere no error handling is done, because values come from trusted
sources, or are pre-validated:
- vault plugin
- ipaserver.install.cainstance
- ipaserver.install.certs
- ipaserver.install.ipa_otptoken_import
---
 ipalib/parameters.py                   | 2 +-
 ipalib/plugins/cert.py                 | 6 ++++--
 ipaplatform/redhat/tasks.py            | 2 +-
 ipapython/ssh.py                       | 2 +-
 ipaserver/install/ipa_cacert_manage.py | 2 +-
 ipaserver/install/ldapupdate.py        | 2 +-
 ipatests/test_pkcs10/test_pkcs10.py    | 7 +++----
 7 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/ipalib/parameters.py b/ipalib/parameters.py
index ef8814eeb68c4461c8ffc341a897f9322aababd3..dadd87d6a328bdb4297f9b6bd51602b24b8d300a 100644
--- a/ipalib/parameters.py
+++ b/ipalib/parameters.py
@@ -1383,7 +1383,7 @@ def _convert_scalar(self, value, index=None):
         if isinstance(value, unicode):
             try:
                 value = base64.b64decode(value)
-            except TypeError as e:
+            except (TypeError, ValueError) as e:
                 raise Base64DecodeError(reason=str(e))
         return super(Bytes, self)._convert_scalar(value, index)
 
diff --git a/ipalib/plugins/cert.py b/ipalib/plugins/cert.py
index e4593200e01addea31c8fcda981fbe1d65058c27..b4ea2feae5de9ffc020709092f79791d99472ffc 100644
--- a/ipalib/plugins/cert.py
+++ b/ipalib/plugins/cert.py
@@ -21,6 +21,8 @@
 
 import os
 import time
+import binascii
+
 from ipalib import Command, Str, Int, Bytes, Flag, File
 from ipalib import api
 from ipalib import errors
@@ -156,7 +158,7 @@ def validate_csr(ugettext, csr):
             return
     try:
         request = pkcs10.load_certificate_request(csr)
-    except TypeError as e:
+    except (TypeError, binascii.Error) as e:
         raise errors.Base64DecodeError(reason=str(e))
     except Exception as e:
         raise errors.CertificateOperationError(error=_('Failure decoding Certificate Signing Request: %s') % e)
@@ -368,7 +370,7 @@ def execute(self, csr, **kw):
             subject = pkcs10.get_subject(csr)
             extensions = pkcs10.get_extensions(csr)
             subjectaltname = pkcs10.get_subjectaltname(csr) or ()
-        except (NSPRError, PyAsn1Error) as e:
+        except (NSPRError, PyAsn1Error, ValueError) as e:
             raise errors.CertificateOperationError(
                 error=_("Failure decoding Certificate Signing Request: %s") % e)
 
diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py
index 446e2886eedca11e66c9e7e6a3d778cd35af0cb6..94d2cb4e906965a20bcfdd55f38854005091c26f 100644
--- a/ipaplatform/redhat/tasks.py
+++ b/ipaplatform/redhat/tasks.py
@@ -210,7 +210,7 @@ def insert_ca_certs_into_systemwide_ca_store(self, ca_certs):
                 issuer = x509.get_der_issuer(cert, x509.DER)
                 serial_number = x509.get_der_serial_number(cert, x509.DER)
                 public_key_info = x509.get_der_public_key_info(cert, x509.DER)
-            except (NSPRError, PyAsn1Error) as e:
+            except (NSPRError, PyAsn1Error, ValueError) as e:
                 root_logger.warning(
                     "Failed to decode certificate \"%s\": %s", nickname, e)
                 continue
diff --git a/ipapython/ssh.py b/ipapython/ssh.py
index 02f577e8b3228c528d474c9468ad4b640dbf682b..a625c422c49a3b0e9082f4351fde7450a4c839d7 100644
--- a/ipapython/ssh.py
+++ b/ipapython/ssh.py
@@ -102,7 +102,7 @@ def _parse_base64(self, key):
 
         try:
             key = base64.b64decode(key)
-        except (TypeError, binascii.Error):
+        except (TypeError, ValueError):
             return False
 
         return self._parse_raw(key)
diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py
index a2242fd3df383af9b8aed2aed142ea8cc8a4ef90..66cba891fad4b679ae51a4a11a094de341c24e88 100644
--- a/ipaserver/install/ipa_cacert_manage.py
+++ b/ipaserver/install/ipa_cacert_manage.py
@@ -334,7 +334,7 @@ def install(self):
             except IOError as e:
                 raise admintool.ScriptError(
                     "Can't open \"%s\": %s" % (cert_filename, e))
-            except (TypeError, NSPRError) as e:
+            except (TypeError, NSPRError, ValueError) as e:
                 raise admintool.ScriptError("Not a valid certificate: %s" % e)
             subject = nss_cert.subject
             cert = nss_cert.der_data
diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py
index fd02bdc024802f3a3ab34ea8399e439941913e6d..86c01104710ff166a07057f9873ed8661621e704 100644
--- a/ipaserver/install/ldapupdate.py
+++ b/ipaserver/install/ldapupdate.py
@@ -423,7 +423,7 @@ def emit_item(logical_line):
                     for i, v in enumerate(value):
                         try:
                             value[i] = base64.b64decode(v)
-                        except TypeError as e:
+                        except (TypeError, ValueError) as e:
                             raise BadSyntax(
                                 "Base64 encoded value %s on line %s:%d: %s is "
                                 "incorrect (%s)" % (v, data_source_name,
diff --git a/ipatests/test_pkcs10/test_pkcs10.py b/ipatests/test_pkcs10/test_pkcs10.py
index 86314dfe54293901c012de45edc460b01ec8b613..a36d1883e7563a927bfaef5783e29cc154c42d57 100644
--- a/ipatests/test_pkcs10/test_pkcs10.py
+++ b/ipatests/test_pkcs10/test_pkcs10.py
@@ -23,10 +23,9 @@
 # FIXME: Pylint errors
 # pylint: disable=no-member
 
-import os
-import sys
+import binascii
+
 import nose
-from ipatests.util import raises, PluginTester
 from ipalib import pkcs10
 from ipapython import ipautil
 import nss.nss as nss
@@ -122,5 +121,5 @@ def test_4(self):
         csr = self.read_file("test4.csr")
         try:
             request = pkcs10.load_certificate_request(csr)
-        except TypeError as typeerr:
+        except (TypeError, binascii.Error) as typeerr:
             assert(str(typeerr) == 'Incorrect padding')
-- 
2.1.0

From 6b928631b6e4ee4600eb4807c89972c24bc1a88a Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Tue, 6 Oct 2015 15:06:45 +0200
Subject: [PATCH] ipatest.util: Port to Python 3

- Allow bytes or str in Fuzzy
- test_util: Fix indices in lists whose elements are unorderable in py3
---
 ipatests/test_util.py | 8 ++++----
 ipatests/util.py      | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/ipatests/test_util.py b/ipatests/test_util.py
index a0ee7384efedaf31e5dfdb8ba199f8b3d1aa34ea..aeb3c93efc8ad4deda996bad932b87fb347d52c1 100644
--- a/ipatests/test_util.py
+++ b/ipatests/test_util.py
@@ -113,7 +113,7 @@ def test_repr(self):
     def test_eq(self):
         assert (self.klass('bar') == u'foobar') is True
         assert (self.klass('^bar') == u'foobar') is False
-        assert (self.klass('bar', type=str) == u'foobar') is False
+        assert (self.klass('bar', type=bytes) == u'foobar') is False
 
         assert ('18' == self.klass()) is True
         assert ('18' == self.klass(type=int)) is False
@@ -127,7 +127,7 @@ def test_eq(self):
 
         t = lambda other: other.endswith('bar')
         assert (self.klass(test=t) == 'foobar') is True
-        assert (self.klass(test=t, type=unicode) == 'foobar') is False
+        assert (self.klass(test=t, type=unicode) == b'foobar') is False
         assert (self.klass(test=t) == 'barfoo') is False
 
         assert (False == self.klass()) is True
@@ -186,7 +186,7 @@ def test_assert_deepequal():
     ]
     e = raises(AssertionError, f, a, b, 'foo')
     assert str(e) == TYPE % (
-        'foo', unicode, str, u'hello', 'hello', (2,)
+        'foo', unicode, bytes, u'hello', b'hello', (2 if six.PY2 else 0,)
     )
 
     b = [
@@ -206,7 +206,7 @@ def test_assert_deepequal():
     ]
     e = raises(AssertionError, f, a, b, 'foo')
     assert str(e) == TYPE % (
-        'foo', int, float, 18, 18.0, (0,)
+        b'foo', int, float, 18, 18.0, (0 if six.PY2 else 2,)
     )
 
     # List length mismatch
diff --git a/ipatests/util.py b/ipatests/util.py
index c6566c930838c444425fb654c3e807c20b1c7530..c70e8cfff29a0001fca4fe0d676a95007e4e4ef2 100644
--- a/ipatests/util.py
+++ b/ipatests/util.py
@@ -227,7 +227,7 @@ def __init__(self, regex=None, type=None, test=None):
             self.re = re.compile(regex)
             if type is None:
                 type = unicode
-            assert type in (unicode, str, six.string_types)
+            assert type in (unicode, bytes, six.string_types)
         self.regex = regex
         self.type = type
         self.test = test
-- 
2.1.0

From 74a856c98d6d9b5bbbf30ebe9df1540cf40c6c09 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Wed, 14 Oct 2015 16:03:33 +0200
Subject: [PATCH] ipalib.messages: Add "message" property to PublicMessage

In Python 3, the "message" property was removed in favor of calling str().
Add it to PublicMessage, since IPA code depends on it.
---
 ipalib/messages.py | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/ipalib/messages.py b/ipalib/messages.py
index 3b982f4737b0bf58940aaa1ca94b7ddb6137987b..466769095fab757d004e7d68e6f84d4fe6f913bf 100644
--- a/ipalib/messages.py
+++ b/ipalib/messages.py
@@ -122,6 +122,11 @@ def to_dict(self):
             code=self.errno,
         )
 
+    if six.PY3:
+        @property
+        def message(self):
+            return str(self)
+
 
 class VersionMissing(PublicMessage):
     """
-- 
2.1.0

From c27e69652d5b6169c32b41f6583e6346fd7cd541 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Thu, 17 Sep 2015 18:46:14 +0200
Subject: [PATCH] Fix more bytes/unicode issues

---
 ipalib/config.py                        |  2 +-
 ipalib/rpc.py                           |  4 +--
 ipapython/dnsutil.py                    |  2 +-
 ipapython/ipaldap.py                    |  5 ++--
 ipaserver/install/replication.py        | 46 ++++++++++++++---------------
 ipatests/data.py                        |  2 +-
 ipatests/test_cmdline/test_cli.py       |  4 +--
 ipatests/test_ipalib/test_base.py       | 10 +++++--
 ipatests/test_ipalib/test_errors.py     | 10 +++----
 ipatests/test_ipalib/test_frontend.py   | 11 +++++--
 ipatests/test_ipalib/test_parameters.py | 52 +++++++++++++++++++++------------
 ipatests/test_ipalib/test_rpc.py        | 22 +++++++++-----
 12 files changed, 101 insertions(+), 69 deletions(-)

diff --git a/ipalib/config.py b/ipalib/config.py
index 92a3235f5c193b2edc2ad2ca4ddef0699f649858..44dedf2943b55899665888f84c6404a2ea357afe 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -244,7 +244,7 @@ def __setitem__(self, key, value):
         assert not hasattr(self, key)
         if isinstance(value, six.string_types):
             value = value.strip()
-            if isinstance(value, str):
+            if isinstance(value, bytes):
                 value = value.decode('utf-8')
             m = {
                 'True': True,
diff --git a/ipalib/rpc.py b/ipalib/rpc.py
index 5b596b601a141288f61a765e9c89906ac42adc1a..6a7f6982b632f965515a66369c9ea302db0fa448 100644
--- a/ipalib/rpc.py
+++ b/ipalib/rpc.py
@@ -224,7 +224,7 @@ def xml_unwrap(value, encoding='UTF-8'):
             return dict(
                 (k, xml_unwrap(v, encoding)) for (k, v) in value.items()
             )
-    if type(value) is str:
+    if isinstance(value, bytes):
         return value.decode(encoding)
     if isinstance(value, Binary):
         assert type(value.data) is bytes
@@ -363,7 +363,7 @@ def json_decode_binary(val):
 
 def decode_fault(e, encoding='UTF-8'):
     assert isinstance(e, Fault)
-    if type(e.faultString) is str:
+    if isinstance(e.faultString, bytes):
         return Fault(e.faultCode, e.faultString.decode(encoding))
     return e
 
diff --git a/ipapython/dnsutil.py b/ipapython/dnsutil.py
index 7844d7bec32602dd53935c104df38fdd4a15f2b2..a11d744d7131206cd0bb5d950c3725271b66410c 100644
--- a/ipapython/dnsutil.py
+++ b/ipapython/dnsutil.py
@@ -39,7 +39,7 @@ def __init__(self, labels, origin=None):
         try:
             if isinstance(labels, six.string_types):
                 #pylint: disable=E1101
-                labels = dns.name.from_unicode(unicode(labels), origin).labels
+                labels = dns.name.from_text(unicode(labels), origin).labels
             elif isinstance(labels, dns.name.Name):
                 labels = labels.labels
 
diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py
index 38c6aad043c49fce17fa07e699cf7912b45a6ede..7e5bc04fea1dc89cc141051025d00a57d74b2b41 100644
--- a/ipapython/ipaldap.py
+++ b/ipapython/ipaldap.py
@@ -1314,8 +1314,9 @@ def find_entries(self, filter=None, attrs_list=None, base_dn=None,
 
         # pass arguments to python-ldap
         with self.error_handler():
-            filter = self.encode(filter)
-            attrs_list = self.encode(attrs_list)
+            if six.PY2:
+                filter = self.encode(filter)
+                attrs_list = self.encode(attrs_list)
 
             while True:
                 if paged_search:
diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py
index a09467897f8bfac879384c954c4f6d070489f548..443f7ca23bb40aeef861d679aa5bda1f0aa532ff 100644
--- a/ipaserver/install/replication.py
+++ b/ipaserver/install/replication.py
@@ -1273,26 +1273,26 @@ def replica_cleanup(self, replica, realm, force=False):
             try:
                 entry.raw['aci'].remove(
                     b'(target = "ldap:///cn=*,cn=ca_renewal,cn=ipa,cn=etc,'
-                    '%(suffix)s")(version 3.0; acl "Add CA Certificates for '
-                    'renewals"; allow(add) userdn = "ldap:///fqdn=%(fqdn)s,'
-                    'cn=computers,cn=accounts,%(suffix)s";)' % sub)
+                    b'%(suffix)s")(version 3.0; acl "Add CA Certificates for '
+                    b'renewals"; allow(add) userdn = "ldap:///fqdn=%(fqdn)s,'
+                    b'cn=computers,cn=accounts,%(suffix)s";)' % sub)
             except ValueError:
                 pass
             try:
                 entry.raw['aci'].remove(
                     b'(target = "ldap:///cn=*,cn=ca_renewal,cn=ipa,cn=etc,'
-                    '%(suffix)s")(targetattr = "userCertificate")'
-                    '(version 3.0; acl "Modify CA Certificates for renewals"; '
-                    'allow(write) userdn = "ldap:///fqdn=%(fqdn)s,'
-                    'cn=computers,cn=accounts,%(suffix)s";)' % sub)
+                    b'%(suffix)s")(targetattr = "userCertificate")'
+                    b'(version 3.0; acl "Modify CA Certificates for renewals"; '
+                    b'allow(write) userdn = "ldap:///fqdn=%(fqdn)s,'
+                    b'cn=computers,cn=accounts,%(suffix)s";)' % sub)
             except ValueError:
                 pass
             try:
                 entry.raw['aci'].remove(
                     b'(target = "ldap:///cn=CAcert,cn=ipa,cn=etc,%(suffix)s")'
-                    '(targetattr = cACertificate)(version 3.0; acl "Modify CA '
-                    'Certificate"; allow (write) userdn = "ldap:///fqdn='
-                    '%(fqdn)s,cn=computers,cn=accounts,%(suffix)s";)' % sub)
+                    b'(targetattr = cACertificate)(version 3.0; acl "Modify CA '
+                    b'Certificate"; allow (write) userdn = "ldap:///fqdn='
+                    b'%(fqdn)s,cn=computers,cn=accounts,%(suffix)s";)' % sub)
             except ValueError:
                 pass
 
@@ -1318,19 +1318,19 @@ def replica_cleanup(self, replica, realm, force=False):
             try:
                 entry.raw['aci'].remove(
                     b'(targetfilter = "(objectClass=nsContainer)")'
-                    '(targetattr = "cn || objectClass || ipaConfigString")'
-                    '(version 3.0; acl "Read IPA Masters"; allow (read, '
-                    'search, compare) userdn = "ldap:///fqdn=%(fqdn)s,'
-                    'cn=computers,cn=accounts,%(suffix)s";)' % sub)
+                    b'(targetattr = "cn || objectClass || ipaConfigString")'
+                    b'(version 3.0; acl "Read IPA Masters"; allow (read, '
+                    b'search, compare) userdn = "ldap:///fqdn=%(fqdn)s,'
+                    b'cn=computers,cn=accounts,%(suffix)s";)' % sub)
             except ValueError:
                 pass
             try:
                 entry.raw['aci'].remove(
                     b'(targetfilter = "(objectClass=nsContainer)")'
-                    '(targetattr = "ipaConfigString")(version 3.0; acl '
-                    '"Modify IPA Masters"; allow (write) userdn = '
-                    '"ldap:///fqdn=%(fqdn)s,cn=computers,cn=accounts,'
-                    '%(suffix)s";)' % sub)
+                    b'(targetattr = "ipaConfigString")(version 3.0; acl '
+                    b'"Modify IPA Masters"; allow (write) userdn = '
+                    b'"ldap:///fqdn=%(fqdn)s,cn=computers,cn=accounts,'
+                    b'%(suffix)s";)' % sub)
             except ValueError:
                 pass
 
@@ -1356,11 +1356,11 @@ def replica_cleanup(self, replica, realm, force=False):
             try:
                 entry.raw['aci'].remove(
                     b'(targetfilter = "(&(objectClass=ipaCertificate)'
-                    '(ipaConfigString=ipaCA))")(targetattr = '
-                    '"ipaCertIssuerSerial || cACertificate")(version 3.0; acl '
-                    '"Modify CA Certificate Store Entry"; allow (write) '
-                    'userdn = "ldap:///fqdn=%(fqdn)s,cn=computers,cn=accounts,'
-                    '%(suffix)s";)' % sub)
+                    b'(ipaConfigString=ipaCA))")(targetattr = '
+                    b'"ipaCertIssuerSerial || cACertificate")(version 3.0; acl '
+                    b'"Modify CA Certificate Store Entry"; allow (write) '
+                    b'userdn = "ldap:///fqdn=%(fqdn)s,cn=computers,cn=accounts,'
+                    b'%(suffix)s";)' % sub)
             except ValueError:
                 pass
 
diff --git a/ipatests/data.py b/ipatests/data.py
index 7fe2002c632c8e5505dce33bace51aa6b28e8395..7ea7e81fdcf79980610a8f368c80f577bc793b11 100644
--- a/ipatests/data.py
+++ b/ipatests/data.py
@@ -27,7 +27,7 @@
 # A string that should have bytes 'x\00' through '\xff':
 binary_bytes = b''.join(struct.pack('B', d) for d in range(256))
 assert b'\x00' in binary_bytes and b'\xff' in binary_bytes
-assert type(binary_bytes) is str and len(binary_bytes) == 256
+assert type(binary_bytes) is bytes and len(binary_bytes) == 256
 
 # A UTF-8 encoded str:
 utf8_bytes = b'\xd0\x9f\xd0\xb0\xd0\xb2\xd0\xb5\xd0\xbb'
diff --git a/ipatests/test_cmdline/test_cli.py b/ipatests/test_cmdline/test_cli.py
index 1b6c793afdbc24b158446b1c1278cc992d2307c6..74a7c6ca45fd0ae032cd02cf25d5ef663799feac 100644
--- a/ipatests/test_cmdline/test_cli.py
+++ b/ipatests/test_cmdline/test_cli.py
@@ -305,8 +305,8 @@ def test_without_options():
 
             # Create a mock service object to test against
             adtrust_add = dict(
-                ipaconfigstring='enabledService',
-                objectclass=['top', 'nsContainer', 'ipaConfigObject']
+                ipaconfigstring=b'enabledService',
+                objectclass=[b'top', b'nsContainer', b'ipaConfigObject']
             )
 
             mockldap = util.MockLDAP()
diff --git a/ipatests/test_ipalib/test_base.py b/ipatests/test_ipalib/test_base.py
index 67a82aa92638d8f748fb681cc925da581d6ba192..9b1b6a7788594755dfef3b9acb63c3f80de49287 100644
--- a/ipatests/test_ipalib/test_base.py
+++ b/ipatests/test_ipalib/test_base.py
@@ -183,8 +183,14 @@ def test_check_name():
     ]
     for name in okay:
         assert name is f(name)
-        e = raises(TypeError, f, unicode(name))
-        assert str(e) == TYPE_ERROR % ('name', str, unicode(name), unicode)
+        if six.PY2:
+            bad_type = unicode
+            bad_value = unicode(name)
+        else:
+            bad_type = bytes
+            bad_value = name.encode('ascii')
+        e = raises(TypeError, f, bad_value)
+        assert str(e) == TYPE_ERROR % ('name', str, bad_value, bad_type)
     for name in nope:
         e = raises(ValueError, f, name)
         assert str(e) == NAME_ERROR % (NAME_REGEX, name)
diff --git a/ipatests/test_ipalib/test_errors.py b/ipatests/test_ipalib/test_errors.py
index 6dd9e6cce1d75bc147911078feee2cd8b9862651..954bfcd9ac7147995e0b28b209ae92895cbcdbfa 100644
--- a/ipatests/test_ipalib/test_errors.py
+++ b/ipatests/test_ipalib/test_errors.py
@@ -213,8 +213,8 @@ def __get_klass(self):
 
     def new(self, format=None, message=None, **kw):
         # Test that TypeError is raised if message isn't unicode:
-        e = raises(TypeError, self.klass, message='The message')
-        assert str(e) == TYPE_ERROR % ('message', unicode, 'The message', str)
+        e = raises(TypeError, self.klass, message=b'The message')
+        assert str(e) == TYPE_ERROR % ('message', unicode, b'The message', bytes)
 
         # Test the instance:
         for (key, value) in kw.items():
@@ -261,9 +261,9 @@ def test_init(self):
         assert inst.key1 is val1
         assert inst.key2 is val2
 
-        # Test with format=None, message=str
-        e = raises(TypeError, self.klass, message='the message', **kw)
-        assert str(e) == TYPE_ERROR % ('message', unicode, 'the message', str)
+        # Test with format=None, message=bytes
+        e = raises(TypeError, self.klass, message=b'the message', **kw)
+        assert str(e) == TYPE_ERROR % ('message', unicode, b'the message', bytes)
 
         # Test with format=None, message=None
         e = raises(ValueError, self.klass, **kw)
diff --git a/ipatests/test_ipalib/test_frontend.py b/ipatests/test_ipalib/test_frontend.py
index cfa37df6998929ac674cafab0a74a60945db5056..ace6b7eb44a7d906396f105d080cc1a32d035a48 100644
--- a/ipatests/test_ipalib/test_frontend.py
+++ b/ipatests/test_ipalib/test_frontend.py
@@ -294,9 +294,14 @@ def is_production_mode():
         assert ns.source.multivalue is False
 
         # Test TypeError:
-        e = raises(TypeError, self.get_instance, args=(u'whatever',))
-        assert str(e) == TYPE_ERROR % (
-            'spec', (str, parameters.Param), u'whatever', unicode)
+        if six.PY2:
+            e = raises(TypeError, self.get_instance, args=(u'whatever',))
+            assert str(e) == TYPE_ERROR % (
+                'spec', (str, parameters.Param), u'whatever', unicode)
+        else:
+            e = raises(TypeError, self.get_instance, args=(b'whatever',))
+            assert str(e) == TYPE_ERROR % (
+                'spec', (str, parameters.Param), b'whatever', bytes)
 
         # Test ValueError, required after optional:
         e = raises(ValueError, self.get_instance, args=('arg1?', 'arg2'))
diff --git a/ipatests/test_ipalib/test_parameters.py b/ipatests/test_ipalib/test_parameters.py
index d6e5106353a0960387224f507b2339be6f6cf442..fbbb0a27f46a04e662a9394d4851dd6e542643b4 100644
--- a/ipatests/test_ipalib/test_parameters.py
+++ b/ipatests/test_ipalib/test_parameters.py
@@ -155,8 +155,12 @@ def test_parse_param_spec():
     assert f('name^') == ('name^', dict(required=True, multivalue=False))
 
     # Test that TypeError is raised if spec isn't an str:
-    e = raises(TypeError, f, u'name?')
-    assert str(e) == TYPE_ERROR % ('spec', str, u'name?', unicode)
+    if six.PY2:
+        bad_value = u'name?'
+    else:
+        bad_value = b'name?'
+    e = raises(TypeError, f, bad_value)
+    assert str(e) == TYPE_ERROR % ('spec', str, bad_value, type(bad_value))
 
 
 class DummyRule(object):
@@ -737,7 +741,7 @@ def test_init(self):
         Test the `ipalib.parameters.Bytes.__init__` method.
         """
         o = self.cls('my_bytes')
-        assert o.type is str
+        assert o.type is bytes
         assert o.password is False
         assert o.rules == tuple()
         assert o.class_rules == tuple()
@@ -798,12 +802,12 @@ def test_rule_minlength(self):
         assert dummy.translation is translation
 
         # Test with passing values:
-        for value in ('abc', 'four', '12345'):
+        for value in (b'abc', b'four', b'12345'):
             assert rule(dummy, value) is None
             assert dummy.called() is False
 
         # Test with failing values:
-        for value in ('', 'a', '12'):
+        for value in (b'', b'a', b'12'):
             assert_equal(
                 rule(dummy, value),
                 translation % dict(minlength=3)
@@ -824,12 +828,12 @@ def test_rule_maxlength(self):
         assert dummy.translation is translation
 
         # Test with passing values:
-        for value in ('ab', '123', 'four'):
+        for value in (b'ab', b'123', b'four'):
             assert rule(dummy, value) is None
             assert dummy.called() is False
 
         # Test with failing values:
-        for value in ('12345', 'sixsix'):
+        for value in (b'12345', b'sixsix'):
             assert_equal(
                 rule(dummy, value),
                 translation % dict(maxlength=4)
@@ -850,12 +854,12 @@ def test_rule_length(self):
         assert dummy.translation is translation
 
         # Test with passing values:
-        for value in ('1234', 'four'):
+        for value in (b'1234', b'four'):
             assert rule(dummy, value) is None
             assert dummy.called() is False
 
         # Test with failing values:
-        for value in ('ab', '123', '12345', 'sixsix'):
+        for value in (b'ab', b'123', b'12345', b'sixsix'):
             assert_equal(
                 rule(dummy, value),
                 translation % dict(length=4),
@@ -869,9 +873,9 @@ def test_rule_pattern(self):
         Test the `ipalib.parameters.Bytes._rule_pattern` method.
         """
         # Test our assumptions about Python re module and Unicode:
-        pat = '\w+$'
+        pat = b'\w+$'
         r = re.compile(pat)
-        assert r.match('Hello_World') is not None
+        assert r.match(b'Hello_World') is not None
         assert r.match(utf8_bytes) is None
         assert r.match(binary_bytes) is None
 
@@ -883,12 +887,12 @@ def test_rule_pattern(self):
         dummy = dummy_ugettext(translation)
 
         # Test with passing values:
-        for value in ('HELLO', 'hello', 'Hello_World'):
+        for value in (b'HELLO', b'hello', b'Hello_World'):
             assert rule(dummy, value) is None
             assert dummy.called() is False
 
         # Test with failing values:
-        for value in ('Hello!', 'Hello World', utf8_bytes, binary_bytes):
+        for value in (b'Hello!', b'Hello World', utf8_bytes, binary_bytes):
             assert_equal(
                 rule(dummy, value),
                 translation % dict(pattern=pat),
@@ -924,7 +928,7 @@ def test_convert_scalar(self):
         mthd = o._convert_scalar
         for value in (u'Hello', 42, 1.2, unicode_str):
             assert mthd(value) == unicode(value)
-        bad = [True, 'Hello', dict(one=1), utf8_bytes]
+        bad = [True, b'Hello', dict(one=1), utf8_bytes]
         for value in bad:
             e = raises(errors.ConversionError, mthd, value)
             assert e.name == 'my_str'
@@ -1028,7 +1032,10 @@ def test_rule_pattern(self):
         pat = '\w{5}$'
         r1 = re.compile(pat)
         r2 = re.compile(pat, re.UNICODE)
-        assert r1.match(unicode_str) is None
+        if six.PY2:
+            assert r1.match(unicode_str) is None
+        else:
+            assert r1.match(unicode_str) is not None
         assert r2.match(unicode_str) is not None
 
         # Create instance:
@@ -1164,8 +1171,8 @@ class test_StrEnum(EnumChecker):
     _name = 'my_strenum'
     _datatype = unicode
     _test_values = u'Hello', u'naughty', u'nurse!'
-    _bad_type_values = u'Hello', 'naughty', u'nurse!'
-    _bad_type = str
+    _bad_type_values = u'Hello', b'naughty', u'nurse!'
+    _bad_type = bytes
     _translation = u"values='Hello', 'naughty', 'nurse!'"
     _bad_values = u'Howdy', u'quiet', u'library!'
     _single_value_translation = u"value='Hello'"
@@ -1551,7 +1558,11 @@ def test_create_param():
         assert p.multivalue is kw['multivalue']
 
     # Test that TypeError is raised when spec is neither a Param nor a str:
-    for spec in (u'one', 42, parameters.Param, parameters.Str):
+    if six.PY2:
+        bad_value = u'one'
+    else:
+        bad_value = b'one'
+    for spec in (bad_value, 42, parameters.Param, parameters.Str):
         e = raises(TypeError, f, spec)
         assert str(e) == \
             TYPE_ERROR % ('spec', (str, parameters.Param), spec, type(spec))
@@ -1590,7 +1601,10 @@ def test_convert_scalar(self):
             e = raises(errors.ConversionError, mthd, value)
             assert e.name == 'my_str'
             assert e.index is None
-            assert_equal(e.error, "The character '\\xc3' is not allowed.")
+            if six.PY2:
+                assert_equal(e.error, "The character '\\xc3' is not allowed.")
+            else:
+                assert_equal(e.error, "The character 'á' is not allowed.")
 
 
 class test_DateTime(ClassChecker):
diff --git a/ipatests/test_ipalib/test_rpc.py b/ipatests/test_ipalib/test_rpc.py
index 827788063e6fef61cbb57330e3f0fd14edc8d931..159fdd81a601af693e40121dca3c1e139a7b75f5 100644
--- a/ipatests/test_ipalib/test_rpc.py
+++ b/ipatests/test_ipalib/test_rpc.py
@@ -63,19 +63,25 @@ def test_round_trip():
     """
     # We first test that our assumptions about xmlrpc.client module in the Python
     # standard library are correct:
-    assert_equal(dump_n_load(utf8_bytes), unicode_str)
+    if six.PY2:
+        output_binary_type = bytes
+    else:
+        output_binary_type = Binary
+
+    if six.PY2:
+        assert_equal(dump_n_load(utf8_bytes), unicode_str)
     assert_equal(dump_n_load(unicode_str), unicode_str)
     # "Binary" is not "str". pylint: disable=no-member
     assert_equal(dump_n_load(Binary(binary_bytes)).data, binary_bytes)
     assert isinstance(dump_n_load(Binary(binary_bytes)), Binary)
-    assert type(dump_n_load(b'hello')) is bytes
-    assert type(dump_n_load(u'hello')) is bytes
-    assert_equal(dump_n_load(b''), b'')
-    assert_equal(dump_n_load(u''), b'')
+    assert type(dump_n_load(b'hello')) is output_binary_type
+    assert type(dump_n_load(u'hello')) is str
+    assert_equal(dump_n_load(b''), output_binary_type(b''))
+    assert_equal(dump_n_load(u''), str())
     assert dump_n_load(None) is None
 
     # Now we test our wrap and unwrap methods in combination with dumps, loads:
-    # All str should come back str (because they get wrapped in
+    # All bytes should come back bytes (because they get wrapped in
     # xmlrpc.client.Binary().  All unicode should come back unicode because str
     # explicity get decoded by rpc.xml_unwrap() if they weren't already
     # decoded by xmlrpc.client.loads().
@@ -136,7 +142,7 @@ def test_xml_dumps():
     params = (binary_bytes, utf8_bytes, unicode_str, None)
 
     # Test serializing an RPC request:
-    data = f(params, API_VERSION, b'the_method')
+    data = f(params, API_VERSION, 'the_method')
     (p, m) = loads(data)
     assert_equal(m, u'the_method')
     assert type(p) is tuple
@@ -167,7 +173,7 @@ def test_xml_loads():
     wrapped = rpc.xml_wrap(params, API_VERSION)
 
     # Test un-serializing an RPC request:
-    data = dumps(wrapped, b'the_method', allow_none=True)
+    data = dumps(wrapped, 'the_method', allow_none=True)
     (p, m) = f(data)
     assert_equal(m, u'the_method')
     assert_equal(p, params)
-- 
2.1.0

From 5fa481b625b609b03721911b278e930ff0ea095a Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Thu, 17 Sep 2015 18:50:51 +0200
Subject: [PATCH] Work around ipalib.text (i18n) str/unicode handling

Python 3 doesn't provide ugettext/ungettext, since gettext/ngettext
work with (unicode) strings.
---
 ipalib/text.py | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/ipalib/text.py b/ipalib/text.py
index 9afe4d3009f3fdd44fbf2a8408a3254b0e3c7c92..28953fa785a3ff820de692430885591d127f4a74 100644
--- a/ipalib/text.py
+++ b/ipalib/text.py
@@ -247,21 +247,27 @@ def __repr__(self):
         return '%s(%r, domain=%r, localedir=%r)' % (self.__class__.__name__,
             self.msg, self.domain, self.localedir)
 
-    def __str__(self):
+    def as_unicode(self):
         """
         Translate this message and return as a ``unicode`` instance.
         """
         if self.key in context.__dict__:
-            g = context.__dict__[self.key].ugettext
+            t = context.__dict__[self.key]
         else:
-            g = create_translation(self.key).ugettext
-        return g(self.msg)
+            t = create_translation(self.key)
+        if six.PY2:
+            return t.ugettext(self.msg)
+        else:
+            return t.gettext(self.msg)
+
+    def __str__(self):
+        return unicode(self.as_unicode())
 
     def __json__(self):
-        return self.__unicode__()   #pylint: disable=no-member
+        return unicode(self)   #pylint: disable=no-member
 
     def __mod__(self, kw):
-        return self.__unicode__() % kw  #pylint: disable=no-member
+        return unicode(self) % kw  #pylint: disable=no-member
 
 
 @six.python_2_unicode_compatible
@@ -401,10 +407,13 @@ def __mod__(self, kw):
 
     def __call__(self, count):
         if self.key in context.__dict__:
-            ng = context.__dict__[self.key].ungettext
+            t = context.__dict__[self.key]
         else:
-            ng = create_translation(self.key).ungettext
-        return ng(self.singular, self.plural, count)
+            t = create_translation(self.key)
+        if six.PY2:
+            return t.ungettext(self.singular, self.plural, count)
+        else:
+            return t.ngettext(self.singular, self.plural, count)
 
 
 @six.python_2_unicode_compatible
-- 
2.1.0

From e39d633f1bf698549aaaf690e821843ce5015dca Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Tue, 13 Oct 2015 17:51:11 +0200
Subject: [PATCH] Fix left-over Python 3 syntax errors

---
 ipaserver/install/dsinstance.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index f572c8773a5f2d5d324eb44dd13a8afa0b6f070a..3c54161dd2abcb9bd1b24859a19a8b0e7f93df08 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -438,11 +438,11 @@ def __configure_sasl_mappings(self):
             for r in res:
                 try:
                     self.admin_conn.delete_entry(r)
-                except Exception, e:
+                except Exception as e:
                     root_logger.critical(
                         "Error during SASL mapping removal: %s", e)
                     raise
-        except Exception, e:
+        except Exception as e:
             root_logger.critical("Error while enumerating SASL mappings %s", e)
             raise
 
-- 
2.1.0

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to