Hello,
Here is another batch of Python 3 porting patches.

-- 
Petr Viktorin
From 53770dbbee76728517d7ae0b5ebce3446bb6692b Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Fri, 18 Sep 2015 11:30:15 +0200
Subject: [PATCH] Do not compare types that are not comparable in Python 3

In Python 3, different types are generally not comparable (except for equality),
and None can't be compared to None.
Fix cases of these comparisons.

In ipatest.util, give up on sorting lists if the sorting raises a TypeError.
---
 ipalib/parameters.py                    |  6 +++---
 ipatests/test_ipapython/test_ipautil.py |  2 +-
 ipatests/util.py                        | 10 ++++++++--
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/ipalib/parameters.py b/ipalib/parameters.py
index 34cd65d2980514729d58427443ee1b2296a37cb7..c7468627133aa862988634bb677eb24ccf5dc261 100644
--- a/ipalib/parameters.py
+++ b/ipalib/parameters.py
@@ -1157,9 +1157,9 @@ def __init__(self, name, *rules, **kw):
 
         super(Decimal, self).__init__(name, *rules, **kw)
 
-        if (self.minvalue > self.maxvalue) \
-            and (self.minvalue is not None and \
-                 self.maxvalue is not None):
+        if (self.minvalue is not None and
+                self.maxvalue is not None and
+                self.minvalue > self.maxvalue):
             raise ValueError(
                 '%s: minvalue > maxvalue (minvalue=%s, maxvalue=%s)' % (
                     self.nice, self.minvalue, self.maxvalue)
diff --git a/ipatests/test_ipapython/test_ipautil.py b/ipatests/test_ipapython/test_ipautil.py
index 609e1f0e5be29278391551d2dafccbdbe36e36a5..e19cd2cb677d0508685ccb8f82c2656e078e2069 100644
--- a/ipatests/test_ipapython/test_ipautil.py
+++ b/ipatests/test_ipapython/test_ipautil.py
@@ -321,7 +321,7 @@ def test_popitem(self):
     def test_fromkeys(self):
         dct = ipautil.CIDict.fromkeys(('A', 'b', 'C'))
         assert sorted(dct.keys()) == sorted(['A', 'b', 'C'])
-        assert sorted(dct.values()) == [None] * 3
+        assert list(dct.values()) == [None] * 3
 
 
 class TestTimeParser(object):
diff --git a/ipatests/util.py b/ipatests/util.py
index d180c91b77b0bafd6bff2f01b9dfd7740519c1bd..85b5dbc5e6f8d4a7d484fe1a05a3e9be8a09335a 100644
--- a/ipatests/util.py
+++ b/ipatests/util.py
@@ -331,8 +331,14 @@ def assert_deepequal(expected, got, doc='', stack=tuple()):
             s_got = got
             s_expected = expected
         else:
-            s_got = sorted(got)
-            s_expected = sorted(expected)
+            try:
+                s_got = sorted(got)
+            except TypeError:
+                s_got = got
+            try:
+                s_expected = sorted(expected)
+            except TypeError:
+                s_expected = expected
         for (i, e_sub) in enumerate(s_expected):
             g_sub = s_got[i]
             assert_deepequal(e_sub, g_sub, doc, stack + (i,))
-- 
2.1.0

From d0cf54888a1249cb9a40f5e1e8044ba9dcf611c8 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Fri, 18 Sep 2015 17:20:08 +0200
Subject: [PATCH] x509: Port to Python 3

In python 3 , `bytes` has the buffer interface, and `buffer` was removed.

Also, invalid padding in base64-encoded data raises a ValueError rather
than TypeError.

In tests, use pytest.assert_raises for more correct exception assertions.
Also, get rid of unused imports in the tests
---
 ipalib/x509.py                    |  9 ++++++++-
 ipatests/test_ipalib/test_x509.py | 21 ++++++---------------
 2 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/ipalib/x509.py b/ipalib/x509.py
index e48d3edf78ed701482cdb3b1998a8f3afe708b5c..037d6785c85552a7335d848f7b21fb5eba26ceda 100644
--- a/ipalib/x509.py
+++ b/ipalib/x509.py
@@ -37,10 +37,13 @@
 import sys
 import base64
 import re
+
 import nss.nss as nss
 from nss.error import NSPRError
 from pyasn1.type import univ, namedtype, tag
 from pyasn1.codec.der import decoder, encoder
+import six
+
 from ipapython import ipautil
 from ipalib import api
 from ipalib import _
@@ -127,7 +130,11 @@ def load_certificate(data, datatype=PEM, dbdir=None):
 
     initialize_nss_database(dbdir=dbdir)
 
-    return nss.Certificate(buffer(data))
+    if six.PY2:
+        return nss.Certificate(buffer(data))
+    else:
+        # In python 3 , `bytes` has the buffer interface
+        return nss.Certificate(data)
 
 def load_certificate_from_file(filename, dbdir=None):
     """
diff --git a/ipatests/test_ipalib/test_x509.py b/ipatests/test_ipalib/test_x509.py
index c7fafbbd95f38e28dfa57b6080c8a9c511921cb9..d8004c4a0b4d37130b71b2026956d04c44aa6db3 100644
--- a/ipatests/test_ipalib/test_x509.py
+++ b/ipatests/test_ipalib/test_x509.py
@@ -21,17 +21,12 @@
 Test the `ipalib.x509` module.
 """
 
-import os
-from os import path
-import sys
-from ipatests.util import raises, setitem, delitem, ClassChecker
-from ipatests.util import getitem, setitem, delitem
-from ipatests.util import TempDir, TempHome
-from ipalib.constants import TYPE_ERROR, OVERRIDE_ERROR, SET_ERROR, DEL_ERROR
-from ipalib.constants import NAME_REGEX, NAME_ERROR
 import base64
-from ipalib import x509
+
+import pytest
 from nss.error import NSPRError
+
+from ipalib import x509
 from ipapython.dn import DN
 
 # certutil -
@@ -66,16 +61,12 @@ def test_1_load_base64_cert(self):
 
         # Load a good cert with bad headers
         newcert = '-----BEGIN CERTIFICATE-----' + goodcert
-        try:
+        with pytest.raises((TypeError, ValueError)):
             cert = x509.load_certificate(newcert)
-        except TypeError:
-            pass
 
         # Load a bad cert
-        try:
+        with pytest.raises(NSPRError):
             cert = x509.load_certificate(badcert)
-        except NSPRError:
-            pass
 
     def test_1_load_der_cert(self):
         """
-- 
2.1.0

From 63a97c44c37096efb7647e8766af3ee3fa5ac467 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Fri, 18 Sep 2015 17:26:07 +0200
Subject: [PATCH] Rename caught exception for use outside the except: block.

In Python 3, the variable with the currently handled exception is unset
at the end of the except block. (This is done to break reference
cycles, since exception instances now carry tracebacks, which contain
all locals.)

Fix this in baseldap's error handler.

Use a simpler structure for the ipatests.raises utility that only uses the
exception inside the except block.
---
 ipalib/plugins/baseldap.py | 3 ++-
 ipatests/util.py           | 7 ++-----
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py
index 847db9c21baae07f58af1155f8665038b80565d8..1c822ecda04a53c53d2c3c79ba3227c192a5a54a 100644
--- a/ipalib/plugins/baseldap.py
+++ b/ipalib/plugins/baseldap.py
@@ -1148,7 +1148,8 @@ def wrapped(*call_args, **call_kwargs):
             while True:
                 try:
                     return func(*call_args, **call_kwargs)
-                except errors.ExecutionError as e:
+                except errors.ExecutionError as exc:
+                    e = exc
                     if not callbacks:
                         raise
                     # call exc_callback in the next loop
diff --git a/ipatests/util.py b/ipatests/util.py
index 85b5dbc5e6f8d4a7d484fe1a05a3e9be8a09335a..c6566c930838c444425fb654c3e807c20b1c7530 100644
--- a/ipatests/util.py
+++ b/ipatests/util.py
@@ -370,14 +370,11 @@ def raises(exception, callback, *args, **kw):
     Tests that the expected exception is raised; raises ExceptionNotRaised
     if test fails.
     """
-    raised = False
     try:
         callback(*args, **kw)
     except exception as e:
-        raised = True
-    if not raised:
-        raise ExceptionNotRaised(exception)
-    return e
+        return e
+    raise ExceptionNotRaised(exception)
 
 
 def getitem(obj, key):
-- 
2.1.0

From 6e5aa8a43edcc0229e4b425c633ca5d85a0f9ae9 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Fri, 18 Sep 2015 17:59:16 +0200
Subject: [PATCH] test_ipalib.test_frontend: Port unbound method tests to
 Python 3

Python 3 uses plain function objects instead of unbound methods.
So, what was Class.method.__func__ is now just Class.method.
---
 ipatests/test_ipalib/test_frontend.py | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/ipatests/test_ipalib/test_frontend.py b/ipatests/test_ipalib/test_frontend.py
index d22718c8bad6e90d7dd1520c7a4ff03670fcddeb..cfa37df6998929ac674cafab0a74a60945db5056 100644
--- a/ipatests/test_ipalib/test_frontend.py
+++ b/ipatests/test_ipalib/test_frontend.py
@@ -648,7 +648,10 @@ def forward(self, *args, **kw):
         (api, home) = create_test_api(in_server=True)
         api.finalize()
         o = my_cmd(api)
-        assert o.run.__func__ is self.cls.run.__func__
+        if six.PY2:
+            assert o.run.__func__ is self.cls.run.__func__
+        else:
+            assert o.run.__func__ is self.cls.run
         out = o.run(*args, **kw)
         assert ('execute', args, kw) == out
 
@@ -656,7 +659,10 @@ def forward(self, *args, **kw):
         (api, home) = create_test_api(in_server=False)
         api.finalize()
         o = my_cmd(api)
-        assert o.run.__func__ is self.cls.run.__func__
+        if six.PY2:
+            assert o.run.__func__ is self.cls.run.__func__
+        else:
+            assert o.run.__func__ is self.cls.run
         assert ('forward', args, kw) == o.run(*args, **kw)
 
     def test_messages(self):
@@ -688,14 +694,20 @@ def forward(self, *args, **kw):
         (api, home) = create_test_api(in_server=True)
         api.finalize()
         o = my_cmd(api)
-        assert o.run.__func__ is self.cls.run.__func__
+        if six.PY2:
+            assert o.run.__func__ is self.cls.run.__func__
+        else:
+            assert o.run.__func__ is self.cls.run
         assert {'name': 'execute', 'messages': expected} == o.run(*args, **kw)
 
         # Test in non-server context
         (api, home) = create_test_api(in_server=False)
         api.finalize()
         o = my_cmd(api)
-        assert o.run.__func__ is self.cls.run.__func__
+        if six.PY2:
+            assert o.run.__func__ is self.cls.run.__func__
+        else:
+            assert o.run.__func__ is self.cls.run
         assert {'name': 'forward', 'messages': expected} == o.run(*args, **kw)
 
     def test_validate_output_basic(self):
-- 
2.1.0

From 932757f8e4632bc2b6ef245212be784ce19f93ac Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Mon, 21 Sep 2015 10:34:15 +0200
Subject: [PATCH] ipalib.aci: Port to Python 3

- Don't encode under Python 3, where shlex would choke on bytes
- Sort the attrs dictionary in export_to_string, so the tests are
  deterministic. (The iteration order of dicts was always unspecified,
  but was always the same in practice under CPython 2.)
---
 ipalib/aci.py                                  | 14 ++++++++------
 ipatests/test_ipalib/test_aci.py               |  6 +++---
 ipatests/test_xmlrpc/test_permission_plugin.py | 10 +++++-----
 3 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/ipalib/aci.py b/ipalib/aci.py
index 687ac6357394b704ab8ca75001b73cb242bc8000..a76435f0a7cc0b1162ba1b86f08d4d1ef000e4f7 100755
--- a/ipalib/aci.py
+++ b/ipalib/aci.py
@@ -75,16 +75,16 @@ def export_to_string(self):
         """Output a Directory Server-compatible ACI string"""
         self.validate()
         aci = ""
-        for t in self.target:
-            op = self.target[t]['operator']
-            if type(self.target[t]['expression']) in (tuple, list):
+        for t, v in sorted(self.target.items()):
+            op = v['operator']
+            if type(v['expression']) in (tuple, list):
                 target = ""
-                for l in self.target[t]['expression']:
+                for l in v['expression']:
                     target = target + l + " || "
                 target = target[:-4]
                 aci = aci + "(%s %s \"%s\")" % (t, op, target)
             else:
-                aci = aci + "(%s %s \"%s\")" % (t, op, self.target[t]['expression'])
+                aci = aci + "(%s %s \"%s\")" % (t, op, v['expression'])
         aci = aci + "(version 3.0;acl \"%s\";%s (%s) %s %s \"%s\"" % (self.name, self.action, ",".join(self.permissions), self.bindrule['keyword'], self.bindrule['operator'], self.bindrule['expression']) + ";)"
         return aci
 
@@ -97,7 +97,9 @@ def _remove_quotes(self, s):
         return s
 
     def _parse_target(self, aci):
-        lexer = shlex.shlex(aci.encode('utf-8'))
+        if six.PY2:
+            aci = aci.encode('utf-8')
+        lexer = shlex.shlex(aci)
         lexer.wordchars = lexer.wordchars + "."
 
         l = []
diff --git a/ipatests/test_ipalib/test_aci.py b/ipatests/test_ipalib/test_aci.py
index 794d4e82b465f557325c6f1baa0c143836395876..fc484988f8de2bd8a5a9e63e818641d3d1293f4d 100644
--- a/ipatests/test_ipalib/test_aci.py
+++ b/ipatests/test_ipalib/test_aci.py
@@ -41,7 +41,7 @@ def test_aci_parsing_1_with_aci_keyword():
 
 def test_aci_parsing_2():
     check_aci_parsing('(target="ldap:///uid=bjensen,dc=example,dc=com";)(targetattr=*) (version 3.0;acl "aci1";allow (write) userdn="ldap:///self";;)',
-        '(targetattr = "*")(target = "ldap:///uid=bjensen,dc=example,dc=com";)(version 3.0;acl "aci1";allow (write) userdn = "ldap:///self";;)')
+        '(target = "ldap:///uid=bjensen,dc=example,dc=com";)(targetattr = "*")(version 3.0;acl "aci1";allow (write) userdn = "ldap:///self";;)')
 
 def test_aci_parsing_3():
     check_aci_parsing(' (targetattr = "givenName || sn || cn || displayName || title || initials || loginShell || gecos || homePhone || mobile || pager || facsimileTelephoneNumber || telephoneNumber || street || roomNumber || l || st || postalCode || manager || secretary || description || carLicense || labeledURI || inetUserHTTPURL || seeAlso || employeeType  || businessCategory || ou")(version 3.0;acl "Self service";allow (write) userdn = "ldap:///self";;)',
@@ -53,11 +53,11 @@ def test_aci_parsing_4():
 
 def test_aci_parsing_5():
     check_aci_parsing('(targetattr=member)(target="ldap:///cn=ipausers,cn=groups,cn=accounts,dc=example,dc=com";)(version 3.0;acl "add_user_to_default_group";allow (write) groupdn="ldap:///cn=add_user_to_default_group,cn=taskgroups,dc=example,dc=com";;)',
-        '(targetattr = "member")(target = "ldap:///cn=ipausers,cn=groups,cn=accounts,dc=example,dc=com";)(version 3.0;acl "add_user_to_default_group";allow (write) groupdn = "ldap:///cn=add_user_to_default_group,cn=taskgroups,dc=example,dc=com";;)')
+        '(target = "ldap:///cn=ipausers,cn=groups,cn=accounts,dc=example,dc=com";)(targetattr = "member")(version 3.0;acl "add_user_to_default_group";allow (write) groupdn = "ldap:///cn=add_user_to_default_group,cn=taskgroups,dc=example,dc=com";;)')
 
 def test_aci_parsing_6():
     check_aci_parsing('(targetattr!=member)(targe="ldap:///cn=ipausers,cn=groups,cn=accounts,dc=example,dc=com";)(version 3.0;acl "add_user_to_default_group";allow (write) groupdn="ldap:///cn=add_user_to_default_group,cn=taskgroups,dc=example,dc=com";;)',
-        '(targetattr != "member")(targe = "ldap:///cn=ipausers,cn=groups,cn=accounts,dc=example,dc=com";)(version 3.0;acl "add_user_to_default_group";allow (write) groupdn = "ldap:///cn=add_user_to_default_group,cn=taskgroups,dc=example,dc=com";;)')
+        '(targe = "ldap:///cn=ipausers,cn=groups,cn=accounts,dc=example,dc=com";)(targetattr != "member")(version 3.0;acl "add_user_to_default_group";allow (write) groupdn = "ldap:///cn=add_user_to_default_group,cn=taskgroups,dc=example,dc=com";;)')
 
 def test_aci_parsing_7():
     check_aci_parsing('(targetattr = "userPassword || krbPrincipalKey || sambaLMPassword || sambaNTPassword || passwordHistory")(version 3.0; acl "change_password"; allow (write) groupdn = "ldap:///cn=change_password,cn=taskgroups,dc=example,dc=com";;)',
diff --git a/ipatests/test_xmlrpc/test_permission_plugin.py b/ipatests/test_xmlrpc/test_permission_plugin.py
index 88401190a01d8d8420f135ccd8e204172d2ecca2..b9c8d1b9866905bbab9afbf2c716f47c2fd43fc9 100644
--- a/ipatests/test_xmlrpc/test_permission_plugin.py
+++ b/ipatests/test_xmlrpc/test_permission_plugin.py
@@ -1453,8 +1453,8 @@ class test_permission(Declarative):
 
         verify_permission_aci(
             permission1, api.env.basedn,
-            '(targetattr = "sn")' +
             '(target = "ldap:///%s";)' % DN('cn=editors', groups_dn) +
+            '(targetattr = "sn")' +
             '(version 3.0;acl "permission:%s";' % permission1 +
             'allow (write) groupdn = "ldap:///%s";;)' % permission1_dn,
         ),
@@ -1623,8 +1623,8 @@ class test_permission_rollback(Declarative):
 
         verify_permission_aci(
             permission1, users_dn,
-            '(targetattr = "sn")' +
             '(target = "ldap:///%s";)' % DN(('uid', 'admin'), users_dn) +
+            '(targetattr = "sn")' +
             '(version 3.0;acl "permission:%s";' % permission1 +
             'allow (write) groupdn = "ldap:///%s";;)' % permission1_dn,
         ),
@@ -1964,8 +1964,8 @@ class test_permission_sync_attributes(Declarative):
 
         verify_permission_aci(
             permission1, groups_dn,
-            '(targetattr = "sn")' +
             '(target = "ldap:///%s";)' % DN(('cn', 'editors'), groups_dn) +
+            '(targetattr = "sn")' +
             '(targetfilter = "%s")' % group_filter +
             '(version 3.0;acl "permission:%s";' % permission1 +
             'allow (write) groupdn = "ldap:///%s";;)' % permission1_dn,
@@ -2000,8 +2000,8 @@ class test_permission_sync_attributes(Declarative):
 
         verify_permission_aci(
             permission1, groups_dn,
-            '(targetattr = "sn")' +
             '(target = "ldap:///%s";)' % DN(('cn', 'editors'), groups_dn) +
+            '(targetattr = "sn")' +
             '(targetfilter = "(&(cn=blabla)%s)")' % group_filter +
             '(version 3.0;acl "permission:%s";' % permission1 +
             'allow (write) groupdn = "ldap:///%s";;)' % permission1_dn,
@@ -2235,8 +2235,8 @@ class test_permission_sync_nice(Declarative):
 
         verify_permission_aci(
             permission1, groups_dn,
-            '(targetattr = "sn")' +
             '(target = "ldap:///%s";)' % DN(('cn', 'editors'), groups_dn) +
+            '(targetattr = "sn")' +
             '(targetfilter = "%s")' % group_filter +
             '(version 3.0;acl "permission:%s";' % permission1 +
             'allow (write) groupdn = "ldap:///%s";;)' % permission1_dn,
-- 
2.1.0

From da8ed21ebde962473dce739aa795318f593e893e Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Fri, 18 Sep 2015 17:52:10 +0200
Subject: [PATCH] Add `message` property to IPA's errors and warnings under
 Python 3

Python 3 removes the "message" attribute from exceptions, in favor
of just calling str().
Add it back for IPA's own exception types.
---
 ipalib/errors.py | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/ipalib/errors.py b/ipalib/errors.py
index 49b628aad6b09e13ee2fbaeb942fac30ca57d544..b82d19949df6a648359b33a16455d2b258d5f2d7 100644
--- a/ipalib/errors.py
+++ b/ipalib/errors.py
@@ -102,6 +102,8 @@
             - **5100 - 5999**  *Reserved for future use*
 """
 
+import six
+
 from ipalib.text import ngettext as ungettext
 from ipalib import messages
 from ipaplatform.paths import paths
@@ -124,6 +126,11 @@ def __init__(self, **kw):
             setattr(self, key, value)
         Exception.__init__(self, self.msg)
 
+    if six.PY3:
+        @property
+        def message(self):
+            return str(self)
+
 
 class SubprocessError(PrivateError):
     """
@@ -251,6 +258,11 @@ def __init__(self, format=None, message=None, **kw):
     rval = 1
     format = None
 
+    if six.PY3:
+        @property
+        def message(self):
+            return str(self)
+
 
 class VersionError(PublicError):
     """
-- 
2.1.0

From 5f2d10891f8c4b84887d66887aa6dd19e787132c Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Fri, 18 Sep 2015 14:10:17 +0200
Subject: [PATCH] test_keyring: Use str(e) instead of e.message for exceptions

---
 ipatests/test_ipapython/test_keyring.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ipatests/test_ipapython/test_keyring.py b/ipatests/test_ipapython/test_keyring.py
index 9a5fc98ea9fe731c50b6708b547d06c80cb823d5..0a7f0980c9c03ef094a286c75cf93a8bc4a986c1 100644
--- a/ipatests/test_ipapython/test_keyring.py
+++ b/ipatests/test_ipapython/test_keyring.py
@@ -60,7 +60,7 @@ def test_01(self):
         try:
             result = kernel_keyring.read_key(TEST_KEY)
         except ValueError as e:
-            assert e.message == 'key %s not found' % TEST_KEY
+            assert str(e) == 'key %s not found' % TEST_KEY
 
     def test_02(self):
         """
-- 
2.1.0

From 04c1c0a68b5f68cee18a8fe7667c52d5deb44c1d Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Mon, 21 Sep 2015 13:29:18 +0200
Subject: [PATCH] ipalib.parameters: Handle 0-prefixed octal format of ints

In Python 2, numbers prfixed with '0' are parsed as octal,
e.g. '020' -> 16. In Python 3, the prefix is '0o'.

Handle the old syntax for IPA's parameter conversion to keep
backwards compatibility.
---
 ipalib/parameters.py                    | 3 +++
 ipatests/test_ipalib/test_parameters.py | 1 +
 2 files changed, 4 insertions(+)

diff --git a/ipalib/parameters.py b/ipalib/parameters.py
index c7468627133aa862988634bb677eb24ccf5dc261..8d27d900aab747dcae03d9ade1fec77a41b32597 100644
--- a/ipalib/parameters.py
+++ b/ipalib/parameters.py
@@ -1072,6 +1072,9 @@ def convert_int(value):
         if type(value) is unicode:
             if u'.' in value:
                 return int(float(value))
+            if six.PY3 and re.match('0[0-9]+', value):
+                # 0-prefixed octal format
+                return int(value, 8)
             return int(value, 0)
 
         raise ValueError(value)
diff --git a/ipatests/test_ipalib/test_parameters.py b/ipatests/test_ipalib/test_parameters.py
index 845e4290d384db308d8b43c7956dbbd79b709231..5504a52b54d9f97a3b54f237e331440d3d0807cd 100644
--- a/ipatests/test_ipalib/test_parameters.py
+++ b/ipatests/test_ipalib/test_parameters.py
@@ -1195,6 +1195,7 @@ def check_int_scalar_conversions(o):
     assert o._convert_scalar(u'16') == 16
     assert o._convert_scalar(u'0x10') == 16
     assert o._convert_scalar(u'020') == 16
+    assert o._convert_scalar(u'0o20') == 16
 
 
 class test_IntEnum(EnumChecker):
-- 
2.1.0

From 7fc8317edfb5a401c40bcb031b12fea557ce9442 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Mon, 21 Sep 2015 14:15:00 +0200
Subject: [PATCH] ipalib.parameters: Require bytes for Bytes.pattern

---
 ipalib/parameters.py                    | 5 ++++-
 ipatests/test_ipalib/test_parameters.py | 1 -
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/ipalib/parameters.py b/ipalib/parameters.py
index 8d27d900aab747dcae03d9ade1fec77a41b32597..ef8814eeb68c4461c8ffc341a897f9322aababd3 100644
--- a/ipalib/parameters.py
+++ b/ipalib/parameters.py
@@ -1270,7 +1270,6 @@ class Data(Param):
         ('minlength', int, None),
         ('maxlength', int, None),
         ('length', int, None),
-        ('pattern', (six.string_types,), None),
         ('pattern_errmsg', (six.string_types,), None),
     )
 
@@ -1338,6 +1337,9 @@ class Bytes(Data):
 
     type = bytes
     type_error = _('must be binary data')
+    kwargs = Data.kwargs + (
+        ('pattern', (bytes,), None),
+    )
 
     def __init__(self, name, *rules, **kw):
         if kw.get('pattern', None) is None:
@@ -1399,6 +1401,7 @@ class Str(Data):
     """
 
     kwargs = Data.kwargs + (
+        ('pattern', (six.string_types,), None),
         ('noextrawhitespace', bool, True),
     )
 
diff --git a/ipatests/test_ipalib/test_parameters.py b/ipatests/test_ipalib/test_parameters.py
index 5504a52b54d9f97a3b54f237e331440d3d0807cd..d6e5106353a0960387224f507b2339be6f6cf442 100644
--- a/ipatests/test_ipalib/test_parameters.py
+++ b/ipatests/test_ipalib/test_parameters.py
@@ -692,7 +692,6 @@ def test_init(self):
         assert o.minlength is None
         assert o.maxlength is None
         assert o.length is None
-        assert o.pattern is None
 
         # Test mixing length with minlength or maxlength:
         o = self.cls('my_data', length=5)
-- 
2.1.0

From d4416fda489ed403e99dea96f7930ef141bff7b0 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Tue, 6 Oct 2015 13:48:12 +0200
Subject: [PATCH] rpc: Name argument to KerberosError

---
 ipalib/rpc.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ipalib/rpc.py b/ipalib/rpc.py
index 13b756a5c98a3bd612f023f6b728126cabf19b82..5b596b601a141288f61a765e9c89906ac42adc1a 100644
--- a/ipalib/rpc.py
+++ b/ipalib/rpc.py
@@ -600,7 +600,7 @@ def _auth_complete(self, response):
                     except TypeError:
                         pass
             if not token:
-                raise KerberosError("No valid Negotiate header in server response")
+                raise KerberosError(message="No valid Negotiate header in server response")
             token = self._sec_context.step(token=token)
             if self._sec_context.complete:
                 self._sec_context = None
-- 
2.1.0

From 17d745bbd2b4aa4332d11c513f45c63ca381e54d Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Thu, 8 Oct 2015 15:39:14 +0200
Subject: [PATCH] Alias long to int under Python 3

In py3, the two types are unified under the name "int".
---
 ipapython/install/cli.py                 | 5 +++++
 ipaserver/dcerpc.py                      | 1 +
 ipaserver/install/ipa_otptoken_import.py | 1 +
 3 files changed, 7 insertions(+)

diff --git a/ipapython/install/cli.py b/ipapython/install/cli.py
index ce64baa5f97b04cd5f9f1c5c862650664bdaa091..a9efa74f3ee892097ce32de56e2d8d1898bb1aa5 100644
--- a/ipapython/install/cli.py
+++ b/ipapython/install/cli.py
@@ -10,6 +10,8 @@
 import optparse
 import signal
 
+import six
+
 from ipapython import admintool, ipa_log_manager
 from ipapython.ipautil import CheckedIPAddress, private_ccache
 
@@ -17,6 +19,9 @@
 
 __all__ = ['install_tool', 'uninstall_tool']
 
+if six.PY3:
+    long = int
+
 
 def install_tool(configurable_class, command_name, log_file_name,
                  positional_arguments=None, usage=None, debug_option=False,
diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
index 77610c6d4d7dbac1e66095828a00265046060c90..2e412861ebc265a9b07c8634068151181a3e9b9e 100644
--- a/ipaserver/dcerpc.py
+++ b/ipaserver/dcerpc.py
@@ -63,6 +63,7 @@
 
 if six.PY3:
     unicode = str
+    long = int
 
 __doc__ = _("""
 Classes to manage trust joins using DCE-RPC calls
diff --git a/ipaserver/install/ipa_otptoken_import.py b/ipaserver/install/ipa_otptoken_import.py
index 6377c069686932080e6cf90076612f66745c67a1..9e70b74a166ad9a02774e66f98405ed2f7368d48 100644
--- a/ipaserver/install/ipa_otptoken_import.py
+++ b/ipaserver/install/ipa_otptoken_import.py
@@ -40,6 +40,7 @@
 
 if six.PY3:
     unicode = str
+    long = int
 
 
 class ValidationError(Exception):
-- 
2.1.0

From e75eb0cb459514845939d66390c19fa0f0a867e0 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Wed, 23 Sep 2015 12:33:16 +0200
Subject: [PATCH] ipaldap: Remove extraneous `long` (included in six.int_types)

---
 ipapython/ipaldap.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py
index e0ebabbfcaf24e49b2befee1ec98b7afe662b532..38c6aad043c49fce17fa07e699cf7912b45a6ede 100644
--- a/ipapython/ipaldap.py
+++ b/ipapython/ipaldap.py
@@ -833,7 +833,7 @@ def encode(self, val):
                 return 'TRUE'
             else:
                 return 'FALSE'
-        elif isinstance(val, (unicode, six.integer_types, long, Decimal, DN)):
+        elif isinstance(val, (unicode, six.integer_types, Decimal, DN)):
             return value_to_utf8(val)
         elif isinstance(val, DNSName):
             return val.to_text()
-- 
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