On 01/29/2016 09:42 AM, Jan Cholasta wrote:
> On 29.1.2016 09:25, Jan Cholasta wrote:
>> Hi,
>>
>> On 27.1.2016 18:38, Petr Viktorin wrote:
>>> Hello,
>>>
>>> Here is a mixed bag of Python 3 fixes.
>>> They fix some tests, and they should enable you to use `python3
>>> /usr/bin/ipa`.
>>
>> Patch 761:
>>
>> 1) The "invalid 'my_number': " bit comes from IPA itself, shouldn't we
>> check at least that?

Fixed

>> Patch 762:
>>
>> 1) We should handle UnicodeError here as well, in addition to TypeError:
>>
>>                   if k.lower() == 'negotiate':
>>                       try:
>> -                        token = base64.b64decode(v)
>> +                        token = base64.b64decode(v.encode('ascii'))
>>                           break
>>                       # b64decode raises TypeError on invalid input
>>                       except TypeError:

Fixed

>> 2) I would prefer if the encoding was specified explicitly here:
>>
>> +            response = json_decode_binary(json.loads(response.decode()))

Fixed

>> Patch 763:
>>
>> 1)
>>
>> +                    altname = altname

Fixed

>> 2) Nitpick, but could you please:
>>
>> -        if isinstance(name_or_oid, unicode):
>> -            name_or_oid = name_or_oid.encode('utf-8')
>> +        if six.PY2:
>> +            if isinstance(name_or_oid, unicode):
>> +                name_or_oid = name_or_oid.encode('utf-8')
>>
>> This way it's more visible that this is a py2-only thing.

Sure

>> Patch 764: LGTM
>>
>>
>> Patch 765:
>>
>> 1)
>>
>> +import tempfile
>> +import tempfile

Fixed.

>> Patch 766-767: LGTM
>>
>>
>> Patch 768:
>>
>> 1) Only binascii.Error should be handled in int_to_bytes, the try-except
>> block is there just to handle odd-length strings.

That's there for Python 2, where unhexlify raises TypeError.

>> 2) I think you can just remove the library_path.encode(), it's there
>> because the original C code did the same thing, but don't think it's
>> necessary.

OK

>> Patch 769: LGTM
> 
> Also, could you please reference
> <https://fedorahosted.org/freeipa/ticket/5638> in the patches?

Sure.

Thanks for the review! Updated patches attached.

-- 
Petr Viktorin
From e5cc6a408243454bd1e8ac5eae0af91d5138a3b0 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Mon, 21 Sep 2015 13:22:17 +0200
Subject: [PATCH] test_parameters: Ignore specific error message

In Python 3, the error message from the decimal module is
less clear than before.
(It's apparently the price to pay for speed -- Python3 uses
libmpdec as its Decimal implementation by default.)

Don't check for the exact error message.

https://fedorahosted.org/freeipa/ticket/5638
---
 ipatests/test_ipalib/test_parameters.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/ipatests/test_ipalib/test_parameters.py b/ipatests/test_ipalib/test_parameters.py
index b640f50dae4ebfb4f764e5ca9b2aa355fdfb6359..ea6b80ca859e16c91db4fad26aa8f484b34b6b15 100644
--- a/ipatests/test_ipalib/test_parameters.py
+++ b/ipatests/test_ipalib/test_parameters.py
@@ -1441,8 +1441,7 @@ class test_Decimal(ClassChecker):
         param = self.cls('my_number', precision=1)
         e = raises(ConversionError, param, '123456789012345678901234567890')
 
-        assert str(e) == \
-        "invalid 'my_number': quantize result has too many digits for current context"
+        assert str(e).startswith("invalid 'my_number': ")
 
     def test_exponential(self):
         """
-- 
2.5.0

From 3b957cdba60df736bed7fe562a352bc6b038e943 Mon Sep 17 00:00:00 2001
From: Michael Simacek <msima...@redhat.com>
Date: Tue, 22 Sep 2015 10:29:32 +0200
Subject: [PATCH] Fix bytes/string handling in rpc

https://fedorahosted.org/freeipa/ticket/5638
---
 ipalib/rpc.py | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/ipalib/rpc.py b/ipalib/rpc.py
index a165491adea5366a14a86d7c8bd6337e36fd1b44..c70b3a29fdc86ef10d9c0ce55a360233dbd8663e 100644
--- a/ipalib/rpc.py
+++ b/ipalib/rpc.py
@@ -349,7 +349,7 @@ def json_decode_binary(val):
     elif isinstance(val, list):
         return tuple(json_decode_binary(v) for v in val)
     else:
-        if isinstance(val, six.string_types):
+        if isinstance(val, bytes):
             try:
                 return val.decode('utf-8')
             except UnicodeDecodeError:
@@ -400,7 +400,7 @@ def xml_loads(data, encoding='UTF-8'):
 
 class DummyParser(object):
     def __init__(self):
-        self.data = ''
+        self.data = b''
 
     def feed(self, data):
         self.data += data
@@ -575,7 +575,7 @@ class KerbTransport(SSLTransport):
 
         if token:
             extra_headers.append(
-                ('Authorization', 'negotiate %s' % base64.b64encode(token))
+                ('Authorization', 'negotiate %s' % base64.b64encode(token).decode('ascii'))
             )
 
     def _auth_complete(self, response):
@@ -586,10 +586,10 @@ class KerbTransport(SSLTransport):
                 k, _, v = field.strip().partition(' ')
                 if k.lower() == 'negotiate':
                     try:
-                        token = base64.b64decode(v)
+                        token = base64.b64decode(v.encode('ascii'))
                         break
                     # b64decode raises TypeError on invalid input
-                    except TypeError:
+                    except (TypeError, UnicodeError):
                         pass
             if not token:
                 raise KerberosError(message="No valid Negotiate header in server response")
@@ -1068,12 +1068,12 @@ class JSONServerProxy(object):
         response = self.__transport.request(
             self.__host,
             self.__handler,
-            json.dumps(payload),
+            json.dumps(payload).encode('utf-8'),
             verbose=self.__verbose >= 3,
         )
 
         try:
-            response = json_decode_binary(json.loads(response))
+            response = json_decode_binary(json.loads(response.decode('ascii')))
         except ValueError as e:
             raise JSONError(str(e))
 
-- 
2.5.0

From 9ee2d332d9e7f07ff9f86ee1c0a6bf5e8cd31d9d Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Wed, 14 Oct 2015 15:02:51 +0200
Subject: [PATCH] ipaldap, ldapupdate: Encoding fixes for Python 3

https://fedorahosted.org/freeipa/ticket/5638
---
 ipapython/ipaldap.py            | 14 ++++++++++----
 ipaserver/install/ldapupdate.py |  8 ++++++++
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py
index 28bfcb5c2ee2140d38f17248fc9c90861cd251e4..7522c504b5b8901002776521f05f4ebab8c35ec8 100644
--- a/ipapython/ipaldap.py
+++ b/ipapython/ipaldap.py
@@ -346,11 +346,16 @@ class LDAPEntry(collections.MutableMapping):
             return self._names[name]
 
         if self._conn.schema is not None:
+            if six.PY2:
+                encoded_name = name.encode('utf-8')
+            else:
+                encoded_name = name
             attrtype = self._conn.schema.get_obj(
-                ldap.schema.AttributeType, name.encode('utf-8'))
+                ldap.schema.AttributeType, encoded_name)
             if attrtype is not None:
                 for altname in attrtype.names:
-                    altname = altname.decode('utf-8')
+                    if six.PY2:
+                        altname = altname.decode('utf-8')
                     self._names[altname] = name
 
         self._names[name] = name
@@ -774,8 +779,9 @@ class LDAPClient(object):
         if not self._decode_attrs:
             return bytes
 
-        if isinstance(name_or_oid, unicode):
-            name_or_oid = name_or_oid.encode('utf-8')
+        if six.PY2:
+            if isinstance(name_or_oid, unicode):
+                name_or_oid = name_or_oid.encode('utf-8')
 
         # Is this a special case attribute?
         if name_or_oid in self._SYNTAX_OVERRIDE:
diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py
index 2852513638f9e0ca505a1ac235d55928f2de5dc0..95e35f6976422e97c1344604483aecaf6e86f5d9 100644
--- a/ipaserver/install/ldapupdate.py
+++ b/ipaserver/install/ldapupdate.py
@@ -32,6 +32,7 @@ import pwd
 import fnmatch
 
 import ldap
+import six
 
 from ipaserver.install import installutils
 from ipapython import ipautil, ipaldap
@@ -44,6 +45,9 @@ from ipapython.dn import DN
 from ipapython.ipa_log_manager import log_mgr
 from ipapython.ipautil import wait_for_open_socket
 
+if six.PY3:
+    unicode = str
+
 UPDATES_DIR=paths.UPDATES_DIR
 UPDATE_SEARCH_TIME_LIMIT = 30  # seconds
 
@@ -429,6 +433,10 @@ class LDAPUpdate:
                                 "incorrect (%s)" % (v, data_source_name,
                                                     lcount, logical_line, e)
                             )
+                else:
+                    for i, v in enumerate(value):
+                        if isinstance(v, unicode):
+                            value[i] = v.encode('utf-8')
 
                 if action != 'replace':
                     value = value[0]
-- 
2.5.0

From a5e604c63a03436f27e813c7ee70f05ba770608a Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Tue, 26 Jan 2016 13:56:54 +0100
Subject: [PATCH] ipautil.run, kernel_keyring: Encoding fixes for Python 3

https://fedorahosted.org/freeipa/ticket/5638
---
 ipapython/ipautil.py                    | 4 ++--
 ipapython/kernel_keyring.py             | 6 +++---
 ipatests/test_ipapython/test_ipautil.py | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index 7949bdf05cd72c512e6c2bc24b1bc52012e63317..91a0eb21527d7d79351b701d5d57c64a652aa7dc 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -464,7 +464,7 @@ def run(args, stdin=None, raiseonerr=True, nolog=(), env=None,
         if six.PY2:
             output = stdout
         else:
-            output = stdout.encode(encoding)
+            output = stdout.decode(encoding)
     else:
         output = None
 
@@ -472,7 +472,7 @@ def run(args, stdin=None, raiseonerr=True, nolog=(), env=None,
         if six.PY2:
             error_output = stderr
         else:
-            error_output = stderr.encode(encoding)
+            error_output = stderr.decode(encoding)
     else:
         error_output = None
 
diff --git a/ipapython/kernel_keyring.py b/ipapython/kernel_keyring.py
index 7ba916ccb14758335f4ca528448310cc51120cd4..ed4868a9d8eaffdae6f717928663296bd20c762e 100644
--- a/ipapython/kernel_keyring.py
+++ b/ipapython/kernel_keyring.py
@@ -50,7 +50,7 @@ def get_real_key(key):
                  raiseonerr=False, capture_output=True)
     if result.returncode:
         raise ValueError('key %s not found' % key)
-    return result.output.rstrip()
+    return result.raw_output.rstrip()
 
 def get_persistent_key(key):
     assert isinstance(key, str)
@@ -58,7 +58,7 @@ def get_persistent_key(key):
                  raiseonerr=False, capture_output=True)
     if result.returncode:
         raise ValueError('persistent key %s not found' % key)
-    return result.output.rstrip()
+    return result.raw_output.rstrip()
 
 def is_persistent_keyring_supported():
     uid = os.geteuid()
@@ -93,7 +93,7 @@ def read_key(key):
     if result.returncode:
         raise ValueError('keyctl pipe failed: %s' % result.error_log)
 
-    return result.output
+    return result.raw_output
 
 def update_key(key, value):
     """
diff --git a/ipatests/test_ipapython/test_ipautil.py b/ipatests/test_ipapython/test_ipautil.py
index 1197d5ce552dc2c244d195175ef008d7b3a21c02..8a97bf5549da529d91b614112826319e4981d3ec 100644
--- a/ipatests/test_ipapython/test_ipautil.py
+++ b/ipatests/test_ipapython/test_ipautil.py
@@ -442,7 +442,7 @@ def test_run_no_capture_output():
 def test_run_bytes():
     result = ipautil.run(['echo', b'\x01\x02'], capture_output=True)
     assert result.returncode == 0
-    assert result.output == b'\x01\x02\n'
+    assert result.raw_output == b'\x01\x02\n'
 
 
 def test_run_decode():
-- 
2.5.0

From 9ca88fb06be39aa673e1c0631c84039285c00754 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Tue, 26 Jan 2016 14:10:18 +0100
Subject: [PATCH] tests: Use absolute imports

https://fedorahosted.org/freeipa/ticket/5638
---
 ipatests/test_cmdline/test_ipagetkeytab.py | 11 ++++++-----
 ipatests/test_integration/test_topology.py |  3 ++-
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/ipatests/test_cmdline/test_ipagetkeytab.py b/ipatests/test_cmdline/test_ipagetkeytab.py
index e712279bb7919af28cab373d097af599b8fa2fa3..6a1314f6c83c733b4ee72eaa4844ea32a77742a7 100644
--- a/ipatests/test_cmdline/test_ipagetkeytab.py
+++ b/ipatests/test_cmdline/test_ipagetkeytab.py
@@ -22,15 +22,16 @@ Test `ipa-getkeytab`
 
 import os
 import shutil
-from cmdline import cmdline_test
+import tempfile
+
+import gssapi
+import pytest
+
 from ipalib import api
 from ipalib import errors
-import tempfile
 from ipapython import ipautil, ipaldap
-import tempfile
-import gssapi
 from ipaserver.plugins.ldap2 import ldap2
-import pytest
+from ipatests.test_cmdline.cmdline import cmdline_test
 
 def use_keytab(principal, keytab):
     try:
diff --git a/ipatests/test_integration/test_topology.py b/ipatests/test_integration/test_topology.py
index ec3d1de97111bee1c1dc1716322fcd0fffffd6ec..8119aa9d7c9a57e68a89ef1d8086920286e64316 100644
--- a/ipatests/test_integration/test_topology.py
+++ b/ipatests/test_integration/test_topology.py
@@ -4,11 +4,12 @@
 
 import re
 import time
+
 import pytest
 
 from ipatests.test_integration.base import IntegrationTest
 from ipatests.test_integration import tasks
-from env_config import get_global_config
+from ipatests.test_integration.env_config import get_global_config
 from ipalib.constants import DOMAIN_SUFFIX_NAME
 
 config = get_global_config()
-- 
2.5.0

From 1e18e436b144ea85b9f8fc7b39fd1195386eb0de Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Tue, 26 Jan 2016 15:05:14 +0100
Subject: [PATCH] ipautil: Use mode 'w+' in write_tmp_file

Python defaults to 'w+b', but all callers in IPA write use text (as
opposed to bytes).

https://fedorahosted.org/freeipa/ticket/5638
---
 ipapython/ipautil.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index 91a0eb21527d7d79351b701d5d57c64a652aa7dc..6d07e07a08260995fb78e2ac23c825f734a4cd09 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -251,7 +251,7 @@ def copy_template_file(infilename, outfilename, vars):
 
 
 def write_tmp_file(txt):
-    fd = tempfile.NamedTemporaryFile()
+    fd = tempfile.NamedTemporaryFile('w+')
     fd.write(txt)
     fd.flush()
 
-- 
2.5.0

From 209629102fee7d28cda5c1111e177e73cc050d41 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Tue, 26 Jan 2016 15:32:29 +0100
Subject: [PATCH] test_util: str/bytes check fixes for Python 3

https://fedorahosted.org/freeipa/ticket/5638
---
 ipatests/test_util.py | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/ipatests/test_util.py b/ipatests/test_util.py
index 5d3328015043b7c08a6f17fa0cb0c41d1a865e5f..85b2843ac0440299c34440a864d603d4fd1298e9 100644
--- a/ipatests/test_util.py
+++ b/ipatests/test_util.py
@@ -158,9 +158,9 @@ def test_assert_deepequal():
         'foo', u'hello', u'world', tuple()
     )
 
-    e = raises(AssertionError, f, 'hello', u'hello', 'foo')
+    e = raises(AssertionError, f, b'hello', u'hello', 'foo')
     assert str(e) == TYPE % (
-        'foo', str, unicode, 'hello', u'hello', tuple()
+        'foo', bytes, unicode, b'hello', u'hello', tuple()
     )
 
     e = raises(AssertionError, f, 18, 18.0, 'foo')
@@ -183,7 +183,7 @@ def test_assert_deepequal():
 
     # Test with bad compound values:
     b = [
-        'hello',
+        b'hello',
         dict(naughty=u'nurse'),
         18,
     ]
@@ -194,12 +194,12 @@ def test_assert_deepequal():
 
     b = [
         u'hello',
-        dict(naughty='nurse'),
+        dict(naughty=b'nurse'),
         18,
     ]
     e = raises(AssertionError, f, a, b, 'foo')
     assert str(e) == TYPE % (
-        'foo', unicode, str, u'nurse', 'nurse', (1, 'naughty')
+        'foo', unicode, bytes, u'nurse', b'nurse', (1, 'naughty')
     )
 
     b = [
@@ -209,7 +209,7 @@ def test_assert_deepequal():
     ]
     e = raises(AssertionError, f, a, b, 'foo')
     assert str(e) == TYPE % (
-        b'foo', int, float, 18, 18.0, (0 if six.PY2 else 2,)
+        'foo', int, float, 18, 18.0, (0 if six.PY2 else 2,)
     )
 
     # List length mismatch
-- 
2.5.0

From c2a088cf771256e2bccce1767a0a86f0ad9ff108 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Tue, 26 Jan 2016 16:35:12 +0100
Subject: [PATCH] p11helper: Port to Python 3

- Use binascii.hexlify instead of encode('hex')
- Keep the library name as a text string instead of encoding to bytes

https://fedorahosted.org/freeipa/ticket/5638
---
 ipapython/p11helper.py | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/ipapython/p11helper.py b/ipapython/p11helper.py
index d1f128b485f36f27a0e703b24ef20e8f482883eb..5ff9ccc4e33d36934568794119deb295e580c0ae 100644
--- a/ipapython/p11helper.py
+++ b/ipapython/p11helper.py
@@ -4,6 +4,7 @@
 
 import random
 import ctypes.util
+import binascii
 
 import six
 from cryptography.hazmat.backends import default_backend
@@ -551,13 +552,13 @@ def char_array_to_unicode(array, l):
 
 def int_to_bytes(value):
     try:
-        return '{0:x}'.format(value).decode('hex')
-    except TypeError:
-        return '0{0:x}'.format(value).decode('hex')
+        return binascii.unhexlify('{0:x}'.format(value))
+    except (TypeError, binascii.Error):
+        return binascii.unhexlify('0{0:x}'.format(value))
 
 
 def bytes_to_int(value):
-    return int(value.encode('hex'), 16)
+    return int(binascii.hexlify(value), 16)
 
 
 def check_return_value(rv, message):
@@ -807,8 +808,6 @@ class P11_Helper(object):
         # Parse method args
         if isinstance(user_pin, unicode):
             user_pin = user_pin.encode()
-        if isinstance(library_path, unicode):
-            library_path = library_path.encode()
         self.slot = slot
 
         try:
-- 
2.5.0

From f7239486ffee652449ff378b2f9118c356d920d0 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Tue, 26 Jan 2016 16:49:23 +0100
Subject: [PATCH] cli: Don't encode/decode for stdin/stdout on Python 3

https://fedorahosted.org/freeipa/ticket/5638
---
 ipalib/cli.py | 41 ++++++++++++++++++++++++-----------------
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/ipalib/cli.py b/ipalib/cli.py
index 136e0aeb8b876b2fe021f08e49a85a0fdeb4b21b..e1abaa5d5dee844b453d049a6baa091c8d517b29 100644
--- a/ipalib/cli.py
+++ b/ipalib/cli.py
@@ -130,24 +130,31 @@ class textui(backend.Backend):
             return 'UTF-8'
         return stream.encoding
 
-    def decode(self, value):
-        """
-        Decode text from stdin.
-        """
-        if type(value) is bytes:
-            encoding = self.__get_encoding(sys.stdin)
-            return value.decode(encoding)
-        elif type(value) in (list, tuple):
-            return tuple(self.decode(v) for v in value)
-        return value
+    if six.PY2:
+        def decode(self, value):
+            """
+            Decode text from stdin.
+            """
+            if type(value) is bytes:
+                encoding = self.__get_encoding(sys.stdin)
+                return value.decode(encoding)
+            elif type(value) in (list, tuple):
+                return tuple(self.decode(v) for v in value)
+            return value
 
-    def encode(self, unicode_text):
-        """
-        Encode text for output to stdout.
-        """
-        assert type(unicode_text) is unicode
-        encoding = self.__get_encoding(sys.stdout)
-        return unicode_text.encode(encoding)
+        def encode(self, unicode_text):
+            """
+            Encode text for output to stdout.
+            """
+            assert type(unicode_text) is unicode
+            encoding = self.__get_encoding(sys.stdout)
+            return unicode_text.encode(encoding)
+    else:
+        def decode(self, value):
+            return value
+
+        def encode(self, value):
+            return value
 
     def choose_number(self, n, singular, plural=None):
         if n == 1 or plural is None:
-- 
2.5.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