From 404cc493f030da07bec44bf761e602568d25dd97 Mon Sep 17 00:00:00 2001 From: Eshin Kunishima Date: Sun, 2 Apr 2017 14:02:25 +0900 Subject: [PATCH 1/7] futurize stage1 --- libzfs_core/test/test_libzfs_core.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libzfs_core/test/test_libzfs_core.py b/libzfs_core/test/test_libzfs_core.py index 089e311..9da61de 100644 --- a/libzfs_core/test/test_libzfs_core.py +++ b/libzfs_core/test/test_libzfs_core.py @@ -7,6 +7,7 @@ that the operations produce expected effects or fail with expected exceptions. """ +from __future__ import print_function import unittest import contextlib @@ -27,8 +28,8 @@ def _print(*args): for arg in args: - print arg, - print + print(arg, end=' ') + print() @contextlib.contextmanager @@ -59,7 +60,7 @@ def _zfs_mount(fs): with suppress(): subprocess.check_output(unmount_cmd, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: - print 'failed to mount %s @ %s : %s' % (fs, mntdir, e.output) + print('failed to mount %s @ %s : %s' % (fs, mntdir, e.output)) raise finally: os.rmdir(mntdir) @@ -3483,7 +3484,7 @@ def __init__(self, size=128 * 1024 * 1024, readonly=False, filesystems=[]): if 'permission denied' in e.output: raise unittest.SkipTest( 'insufficient privileges to run libzfs_core tests') - print 'command failed: ', e.output + print('command failed: ', e.output) raise except Exception: self.cleanUp() @@ -3518,7 +3519,7 @@ def reset(self): subprocess.check_output( self._zpool_create, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: - print 'command failed: ', e.output + print('command failed: ', e.output) raise for fs in self._filesystems: lzc.lzc_create(self.makeName(fs)) From d8ba45eece293047f73dc36469d2511b99c9f82e Mon Sep 17 00:00:00 2001 From: Eshin Kunishima Date: Sun, 2 Apr 2017 20:09:44 +0900 Subject: [PATCH 2/7] futurize stage2 --- libzfs_core/__init__.py | 1 + libzfs_core/_constants.py | 1 + libzfs_core/_error_translation.py | 26 ++++++++++++---------- libzfs_core/_libzfs_core.py | 17 ++++++++------ libzfs_core/_nvlist.py | 4 +++- libzfs_core/bindings/__init__.py | 2 ++ libzfs_core/bindings/libnvpair.py | 1 + libzfs_core/bindings/libzfs_core.py | 1 + libzfs_core/ctypes.py | 1 + libzfs_core/exceptions.py | 1 + libzfs_core/test/test_libzfs_core.py | 33 +++++++++++++++++----------- libzfs_core/test/test_nvlist.py | 6 +++-- 12 files changed, 59 insertions(+), 35 deletions(-) diff --git a/libzfs_core/__init__.py b/libzfs_core/__init__.py index 54c2969..9d6d2f2 100644 --- a/libzfs_core/__init__.py +++ b/libzfs_core/__init__.py @@ -23,6 +23,7 @@ Maximum length of any ZFS name. ''' +from __future__ import unicode_literals from ._constants import ( MAXNAMELEN, diff --git a/libzfs_core/_constants.py b/libzfs_core/_constants.py index 45016b4..6b0459f 100644 --- a/libzfs_core/_constants.py +++ b/libzfs_core/_constants.py @@ -3,6 +3,7 @@ """ Important `libzfs_core` constants. """ +from __future__ import unicode_literals #: Maximum length of any ZFS name. MAXNAMELEN = 255 diff --git a/libzfs_core/_error_translation.py b/libzfs_core/_error_translation.py index ad8d08a..f722191 100644 --- a/libzfs_core/_error_translation.py +++ b/libzfs_core/_error_translation.py @@ -12,7 +12,9 @@ The parameters and exceptions are documented in the `libzfs_core` interfaces. """ +from __future__ import unicode_literals +from builtins import map import errno import re import string @@ -74,7 +76,7 @@ def lzc_snapshot_translate_errors(ret, errlist, snaps, props): def _map(ret, name): if ret == errno.EXDEV: - pool_names = map(_pool_name, snaps) + pool_names = list(map(_pool_name, snaps)) same_pool = all(x == pool_names[0] for x in pool_names) if same_pool: return lzc_exc.DuplicateSnapshots(name) @@ -121,7 +123,7 @@ def _map(ret, name): if ret == errno.EINVAL: if name: snap = bookmarks[name] - pool_names = map(_pool_name, bookmarks.keys()) + pool_names = list(map(_pool_name, list(bookmarks.keys()))) if not _is_valid_bmark_name(name): return lzc_exc.BookmarkNameInvalid(name) elif not _is_valid_snap_name(snap): @@ -131,7 +133,7 @@ def _map(ret, name): elif any(x != _pool_name(name) for x in pool_names): return lzc_exc.PoolsDiffer(name) else: - invalid_names = [b for b in bookmarks.keys() if not _is_valid_bmark_name(b)] + invalid_names = [b for b in list(bookmarks.keys()) if not _is_valid_bmark_name(b)] if invalid_names: return lzc_exc.BookmarkNameInvalid(invalid_names[0]) if ret == errno.EEXIST: @@ -142,7 +144,7 @@ def _map(ret, name): return lzc_exc.BookmarkNotSupported(name) return _generic_exception(ret, name, "Failed to create bookmark") - _handle_err_list(ret, errlist, bookmarks.keys(), lzc_exc.BookmarkFailure, _map) + _handle_err_list(ret, errlist, list(bookmarks.keys()), lzc_exc.BookmarkFailure, _map) def lzc_get_bookmarks_translate_error(ret, fsname, props): @@ -200,7 +202,7 @@ def _map(ret, name): return lzc_exc.PoolsDiffer(name) elif ret == errno.EINVAL: if name: - pool_names = map(_pool_name, holds.keys()) + pool_names = list(map(_pool_name, list(holds.keys()))) if not _is_valid_snap_name(name): return lzc_exc.NameInvalid(name) elif len(name) > MAXNAMELEN: @@ -208,7 +210,7 @@ def _map(ret, name): elif any(x != _pool_name(name) for x in pool_names): return lzc_exc.PoolsDiffer(name) else: - invalid_names = [b for b in holds.keys() if not _is_valid_snap_name(b)] + invalid_names = [b for b in list(holds.keys()) if not _is_valid_snap_name(b)] if invalid_names: return lzc_exc.NameInvalid(invalid_names[0]) fs_name = None @@ -230,13 +232,13 @@ def _map(ret, name): if ret == errno.EBADF: raise lzc_exc.BadHoldCleanupFD() - _handle_err_list(ret, errlist, holds.keys(), lzc_exc.HoldFailure, _map) + _handle_err_list(ret, errlist, list(holds.keys()), lzc_exc.HoldFailure, _map) def lzc_release_translate_errors(ret, errlist, holds): if ret == 0: return - for _, hold_list in holds.iteritems(): + for _, hold_list in holds.items(): if not isinstance(hold_list, list): raise lzc_exc.TypeError('holds must be in a list') @@ -245,7 +247,7 @@ def _map(ret, name): return lzc_exc.PoolsDiffer(name) elif ret == errno.EINVAL: if name: - pool_names = map(_pool_name, holds.keys()) + pool_names = list(map(_pool_name, list(holds.keys()))) if not _is_valid_snap_name(name): return lzc_exc.NameInvalid(name) elif len(name) > MAXNAMELEN: @@ -253,7 +255,7 @@ def _map(ret, name): elif any(x != _pool_name(name) for x in pool_names): return lzc_exc.PoolsDiffer(name) else: - invalid_names = [b for b in holds.keys() if not _is_valid_snap_name(b)] + invalid_names = [b for b in list(holds.keys()) if not _is_valid_snap_name(b)] if invalid_names: return lzc_exc.NameInvalid(invalid_names[0]) elif ret == errno.ENOENT: @@ -270,7 +272,7 @@ def _map(ret, name): else: return _generic_exception(ret, name, "Failed to release snapshot hold") - _handle_err_list(ret, errlist, holds.keys(), lzc_exc.HoldReleaseFailure, _map) + _handle_err_list(ret, errlist, list(holds.keys()), lzc_exc.HoldReleaseFailure, _map) def lzc_get_holds_translate_error(ret, snapname): @@ -525,7 +527,7 @@ def _handle_err_list(ret, errlist, names, exception, mapper): else: errors = [] suppressed_count = errlist.pop('N_MORE_ERRORS', 0) - for name, err in errlist.iteritems(): + for name, err in errlist.items(): errors.append(mapper(err, name)) raise exception(errors, suppressed_count) diff --git a/libzfs_core/_libzfs_core.py b/libzfs_core/_libzfs_core.py index f5597f9..d6bfd9a 100644 --- a/libzfs_core/_libzfs_core.py +++ b/libzfs_core/_libzfs_core.py @@ -12,7 +12,10 @@ are directly returned. Error conditions are signalled by exceptions rather than by integer error codes. """ +from __future__ import unicode_literals +from builtins import next +from builtins import object import errno import functools import fcntl @@ -376,8 +379,8 @@ def lzc_hold(holds, fd=None): errors.lzc_hold_translate_errors(ret, errlist, holds, fd) # If there is no error (no exception raised by _handleErrList), but errlist # is not empty, then it contains missing snapshots. - assert all(x == errno.ENOENT for x in errlist.itervalues()) - return errlist.keys() + assert all(x == errno.ENOENT for x in errlist.values()) + return list(errlist.keys()) def lzc_release(holds): @@ -411,7 +414,7 @@ def lzc_release(holds): ''' errlist = {} holds_dict = {} - for snap, hold_list in holds.iteritems(): + for snap, hold_list in holds.items(): if not isinstance(hold_list, list): raise TypeError('holds must be in a list') holds_dict[snap] = {hold: None for hold in hold_list} @@ -421,8 +424,8 @@ def lzc_release(holds): errors.lzc_release_translate_errors(ret, errlist, holds) # If there is no error (no exception raised by _handleErrList), but errlist # is not empty, then it contains missing snapshots and tags. - assert all(x == errno.ENOENT for x in errlist.itervalues()) - return errlist.keys() + assert all(x == errno.ENOENT for x in errlist.values()) + return list(errlist.keys()) def lzc_get_holds(snapname): @@ -1025,9 +1028,9 @@ def lzc_get_props(name): mountpoint_val = '/' + name else: mountpoint_val = None - result = {k: v['value'] for k, v in result.iteritems()} + result = {k: v['value'] for k, v in result.items()} if 'clones' in result: - result['clones'] = result['clones'].keys() + result['clones'] = list(result['clones'].keys()) if mountpoint_val is not None: result['mountpoint'] = mountpoint_val return result diff --git a/libzfs_core/_nvlist.py b/libzfs_core/_nvlist.py index 1f1c39b..e40c421 100644 --- a/libzfs_core/_nvlist.py +++ b/libzfs_core/_nvlist.py @@ -30,7 +30,9 @@ - a value can be a list of dictionaries that adhere to this format - all elements of a list value must be of the same type """ +from __future__ import unicode_literals +from builtins import range import numbers from collections import namedtuple from contextlib import contextmanager @@ -228,7 +230,7 @@ def _nvlist_to_dict(nvlist, props): def _dict_to_nvlist(props, nvlist): - for k, v in props.items(): + for k, v in list(props.items()): if not isinstance(k, bytes): raise TypeError('Unsupported key type ' + type(k).__name__) ret = 0 diff --git a/libzfs_core/bindings/__init__.py b/libzfs_core/bindings/__init__.py index d6fd2b8..74543e6 100644 --- a/libzfs_core/bindings/__init__.py +++ b/libzfs_core/bindings/__init__.py @@ -5,7 +5,9 @@ `libzfs_core` uses. The modules expose CFFI objects required to make calls to functions in the libraries. """ +from __future__ import unicode_literals +from builtins import object import threading import importlib diff --git a/libzfs_core/bindings/libnvpair.py b/libzfs_core/bindings/libnvpair.py index d3f3adf..a1618d5 100644 --- a/libzfs_core/bindings/libnvpair.py +++ b/libzfs_core/bindings/libnvpair.py @@ -3,6 +3,7 @@ """ Python bindings for ``libnvpair``. """ +from __future__ import unicode_literals CDEF = """ typedef ... nvlist_t; diff --git a/libzfs_core/bindings/libzfs_core.py b/libzfs_core/bindings/libzfs_core.py index cc9d6b8..4607d2c 100644 --- a/libzfs_core/bindings/libzfs_core.py +++ b/libzfs_core/bindings/libzfs_core.py @@ -3,6 +3,7 @@ """ Python bindings for ``libzfs_core``. """ +from __future__ import unicode_literals CDEF = """ enum lzc_send_flags { diff --git a/libzfs_core/ctypes.py b/libzfs_core/ctypes.py index bd168f2..d03c536 100644 --- a/libzfs_core/ctypes.py +++ b/libzfs_core/ctypes.py @@ -3,6 +3,7 @@ """ Utility functions for casting to a specific C type. """ +from __future__ import unicode_literals from .bindings.libnvpair import ffi as _ffi diff --git a/libzfs_core/exceptions.py b/libzfs_core/exceptions.py index 5ed00c4..5b519d2 100644 --- a/libzfs_core/exceptions.py +++ b/libzfs_core/exceptions.py @@ -3,6 +3,7 @@ """ Exceptions that can be raised by libzfs_core operations. """ +from __future__ import unicode_literals import errno diff --git a/libzfs_core/test/test_libzfs_core.py b/libzfs_core/test/test_libzfs_core.py index 9da61de..1852fb9 100644 --- a/libzfs_core/test/test_libzfs_core.py +++ b/libzfs_core/test/test_libzfs_core.py @@ -8,7 +8,14 @@ exceptions. """ from __future__ import print_function - +from __future__ import division +from __future__ import unicode_literals + +from builtins import bytes +from builtins import zip +from builtins import range +from builtins import object +from past.utils import old_div import unittest import contextlib import errno @@ -1238,11 +1245,11 @@ def test_snaprange_space(self): lzc.lzc_snapshot([snap3]) space = lzc.lzc_snaprange_space(snap1, snap2) - self.assertIsInstance(space, (int, long)) + self.assertIsInstance(space, (int, int)) space = lzc.lzc_snaprange_space(snap2, snap3) - self.assertIsInstance(space, (int, long)) + self.assertIsInstance(space, (int, int)) space = lzc.lzc_snaprange_space(snap1, snap3) - self.assertIsInstance(space, (int, long)) + self.assertIsInstance(space, (int, int)) def test_snaprange_space_2(self): snap1 = ZFSTest.pool.makeName("fs1@snap1") @@ -1364,17 +1371,17 @@ def test_send_space(self): lzc.lzc_snapshot([snap3]) space = lzc.lzc_send_space(snap2, snap1) - self.assertIsInstance(space, (int, long)) + self.assertIsInstance(space, (int, int)) space = lzc.lzc_send_space(snap3, snap2) - self.assertIsInstance(space, (int, long)) + self.assertIsInstance(space, (int, int)) space = lzc.lzc_send_space(snap3, snap1) - self.assertIsInstance(space, (int, long)) + self.assertIsInstance(space, (int, int)) space = lzc.lzc_send_space(snap1) - self.assertIsInstance(space, (int, long)) + self.assertIsInstance(space, (int, int)) space = lzc.lzc_send_space(snap2) - self.assertIsInstance(space, (int, long)) + self.assertIsInstance(space, (int, int)) space = lzc.lzc_send_space(snap3) - self.assertIsInstance(space, (int, long)) + self.assertIsInstance(space, (int, int)) def test_send_space_2(self): snap1 = ZFSTest.pool.makeName("fs1@snap1") @@ -1516,7 +1523,7 @@ def test_send_full(self): lzc.lzc_send(snap, None, fd) st = os.fstat(fd) # 5%, arbitrary. - self.assertAlmostEqual(st.st_size, estimate, delta=estimate / 20) + self.assertAlmostEqual(st.st_size, estimate, delta=old_div(estimate, 20)) def test_send_incremental(self): snap1 = ZFSTest.pool.makeName("fs1@snap1") @@ -1537,7 +1544,7 @@ def test_send_incremental(self): lzc.lzc_send(snap2, snap1, fd) st = os.fstat(fd) # 5%, arbitrary. - self.assertAlmostEqual(st.st_size, estimate, delta=estimate / 20) + self.assertAlmostEqual(st.st_size, estimate, delta=old_div(estimate, 20)) def test_send_flags(self): snap = ZFSTest.pool.makeName("fs1@snap") @@ -2825,7 +2832,7 @@ def test_get_holds(self): self.assertEquals(len(holds), 2) self.assertIn('tag1', holds) self.assertIn('tag2', holds) - self.assertIsInstance(holds['tag1'], (int, long)) + self.assertIsInstance(holds['tag1'], (int, int)) def test_get_holds_after_auto_cleanup(self): snap = ZFSTest.pool.getRoot().getSnap() diff --git a/libzfs_core/test/test_nvlist.py b/libzfs_core/test/test_nvlist.py index 61a4b69..67134ce 100644 --- a/libzfs_core/test/test_nvlist.py +++ b/libzfs_core/test/test_nvlist.py @@ -7,7 +7,9 @@ The tests also check that various error conditions like unsupported value types or out of bounds values are detected. """ +from __future__ import unicode_literals +from builtins import zip import unittest from .._nvlist import nvlist_in, nvlist_out, _lib @@ -28,12 +30,12 @@ def _dict_to_nvlist_to_dict(self, props): def _assertIntDictsEqual(self, dict1, dict2): self.assertEqual(len(dict1), len(dict1), "resulting dictionary is of different size") - for key in dict1.keys(): + for key in list(dict1.keys()): self.assertEqual(int(dict1[key]), int(dict2[key])) def _assertIntArrayDictsEqual(self, dict1, dict2): self.assertEqual(len(dict1), len(dict1), "resulting dictionary is of different size") - for key in dict1.keys(): + for key in list(dict1.keys()): val1 = dict1[key] val2 = dict2[key] self.assertEqual(len(val1), len(val2), "array values of different sizes") From 5f2211400d8971343ca657b8490587b819c218fb Mon Sep 17 00:00:00 2001 From: Eshin Kunishima Date: Sun, 2 Apr 2017 20:16:04 +0900 Subject: [PATCH 3/7] [Python 2.7] fix TypeError: __name__ must be set to a string object --- libzfs_core/ctypes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libzfs_core/ctypes.py b/libzfs_core/ctypes.py index d03c536..d9acd57 100644 --- a/libzfs_core/ctypes.py +++ b/libzfs_core/ctypes.py @@ -22,7 +22,7 @@ def _func(value): else: _ffi.new(type_name + '*', value) return _ffi.cast(type_name, value) - _func.__name__ = type_name + _func.__name__ = type_name.encode() return _func From 63fb115981c02c91daf2e86508a13ad49d4183ed Mon Sep 17 00:00:00 2001 From: Eshin Kunishima Date: Sun, 2 Apr 2017 22:09:27 +0900 Subject: [PATCH 4/7] fix missing param in docstring --- libzfs_core/_libzfs_core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libzfs_core/_libzfs_core.py b/libzfs_core/_libzfs_core.py index d6bfd9a..891f7ca 100644 --- a/libzfs_core/_libzfs_core.py +++ b/libzfs_core/_libzfs_core.py @@ -754,8 +754,8 @@ def lzc_rename(source, target): ''' Rename the ZFS dataset. - :param source name: the current name of the dataset to rename. - :param target name: the new name of the dataset. + :param bytes source: the current name of the dataset to rename. + :param bytes target: the new name of the dataset. :raises NameInvalid: if either the source or target name is invalid. :raises NameTooLong: if either the source or target name is too long. :raises NameTooLong: if a snapshot of the source would get a too long From 638524fbb525b7d5b3bc0c721d5308721aa34c68 Mon Sep 17 00:00:00 2001 From: Eshin Kunishima Date: Sun, 2 Apr 2017 22:40:45 +0900 Subject: [PATCH 5/7] [Python 2.7] add support for str on Python 3 --- libzfs_core/_libzfs_core.py | 42 +++++++++++++++++----------- libzfs_core/_nvlist.py | 16 +++++++++-- libzfs_core/test/test_libzfs_core.py | 24 ++++++++-------- 3 files changed, 53 insertions(+), 29 deletions(-) diff --git a/libzfs_core/_libzfs_core.py b/libzfs_core/_libzfs_core.py index 891f7ca..2ccdd0e 100644 --- a/libzfs_core/_libzfs_core.py +++ b/libzfs_core/_libzfs_core.py @@ -14,20 +14,30 @@ """ from __future__ import unicode_literals -from builtins import next -from builtins import object import errno -import functools import fcntl +import functools import os import struct import threading -from . import exceptions + +from builtins import next +from builtins import object +from builtins import str + from . import _error_translation as errors -from .bindings import libzfs_core +from . import exceptions from ._constants import MAXNAMELEN -from .ctypes import int32_t from ._nvlist import nvlist_in, nvlist_out +from .bindings import libzfs_core +from .ctypes import int32_t + + +def _b(s): + if isinstance(s, str): + return s.encode() + else: + return s def lzc_create(name, ds_type='zfs', props=None): @@ -57,7 +67,7 @@ def lzc_create(name, ds_type='zfs', props=None): else: raise exceptions.DatasetTypeInvalid(ds_type) nvlist = nvlist_in(props) - ret = _lib.lzc_create(name, ds_type, nvlist) + ret = _lib.lzc_create(_b(name), ds_type, nvlist) errors.lzc_create_translate_error(ret, name, ds_type, props) @@ -91,7 +101,7 @@ def lzc_clone(name, origin, props=None): if props is None: props = {} nvlist = nvlist_in(props) - ret = _lib.lzc_clone(name, origin, nvlist) + ret = _lib.lzc_clone(_b(name), _b(origin), nvlist) errors.lzc_clone_translate_error(ret, name, origin, props) @@ -110,7 +120,7 @@ def lzc_rollback(name): ''' # Account for terminating NUL in C strings. snapnamep = _ffi.new('char[]', MAXNAMELEN + 1) - ret = _lib.lzc_rollback(name, snapnamep, MAXNAMELEN + 1) + ret = _lib.lzc_rollback(_b(name), snapnamep, MAXNAMELEN + 1) errors.lzc_rollback_translate_error(ret, name) return _ffi.string(snapnamep) @@ -273,7 +283,7 @@ def lzc_get_bookmarks(fsname, props=None): props_dict = {name: None for name in props} nvlist = nvlist_in(props_dict) with nvlist_out(bmarks) as bmarks_nvlist: - ret = _lib.lzc_get_bookmarks(fsname, nvlist, bmarks_nvlist) + ret = _lib.lzc_get_bookmarks(_b(fsname), nvlist, bmarks_nvlist) errors.lzc_get_bookmarks_translate_error(ret, fsname, props) return bmarks @@ -333,7 +343,7 @@ def lzc_snaprange_space(firstsnap, lastsnap): In that case ``lzc_snaprange_space`` calculates space used by the snapshot. ''' valp = _ffi.new('uint64_t *') - ret = _lib.lzc_snaprange_space(firstsnap, lastsnap, valp) + ret = _lib.lzc_snaprange_space(_b(firstsnap), _b(lastsnap), valp) errors.lzc_snaprange_space_translate_error(ret, firstsnap, lastsnap) return int(valp[0]) @@ -439,7 +449,7 @@ def lzc_get_holds(snapname): ''' holds = {} with nvlist_out(holds) as nvlist: - ret = _lib.lzc_get_holds(snapname, nvlist) + ret = _lib.lzc_get_holds(_b(snapname), nvlist) errors.lzc_get_holds_translate_error(ret, snapname) return holds @@ -517,7 +527,7 @@ def lzc_send(snapname, fromsnap, fd, flags=None): raise exceptions.UnknownStreamFeature(flag) c_flags |= c_flag - ret = _lib.lzc_send(snapname, c_fromsnap, fd, c_flags) + ret = _lib.lzc_send(_b(snapname), _b(c_fromsnap), fd, c_flags) errors.lzc_send_translate_error(ret, snapname, fromsnap, fd, flags) @@ -549,7 +559,7 @@ def lzc_send_space(snapname, fromsnap=None): else: c_fromsnap = _ffi.NULL valp = _ffi.new('uint64_t *') - ret = _lib.lzc_send_space(snapname, c_fromsnap, valp) + ret = _lib.lzc_send_space(_b(snapname), _b(c_fromsnap), valp) errors.lzc_send_space_translate_error(ret, snapname, fromsnap) return int(valp[0]) @@ -648,7 +658,7 @@ def lzc_receive(snapname, fd, force=False, origin=None, props=None): if props is None: props = {} nvlist = nvlist_in(props) - ret = _lib.lzc_receive(snapname, nvlist, c_origin, force, fd) + ret = _lib.lzc_receive(_b(snapname), nvlist, _b(c_origin), force, fd) errors.lzc_receive_translate_error(ret, snapname, fd, force, origin, props) @@ -667,7 +677,7 @@ def lzc_exists(name): .. note:: ``lzc_exists`` can not be used to check for existence of bookmarks. ''' - ret = _lib.lzc_exists(name) + ret = _lib.lzc_exists(_b(name)) return bool(ret) diff --git a/libzfs_core/_nvlist.py b/libzfs_core/_nvlist.py index e40c421..fe7e36a 100644 --- a/libzfs_core/_nvlist.py +++ b/libzfs_core/_nvlist.py @@ -32,10 +32,13 @@ """ from __future__ import unicode_literals -from builtins import range import numbers from collections import namedtuple from contextlib import contextmanager + +from builtins import range +from builtins import str + from .bindings import libnvpair from .ctypes import _type_to_suffix @@ -176,6 +179,11 @@ def _is_integer(x): for string in array: c_array.append(_ffi.new('char[]', string)) ret = _lib.nvlist_add_string_array(nvlist, key, c_array, len(c_array)) + elif isinstance(specimen, str): + c_array = [] + for string in array: + c_array.append(_ffi.new('char[]', string.encode())) + ret = _lib.nvlist_add_string_array(nvlist, key, c_array, len(c_array)) elif isinstance(specimen, bool): ret = _lib.nvlist_add_boolean_array(nvlist, key, array, len(array)) elif isinstance(specimen, numbers.Integral): @@ -231,8 +239,10 @@ def _nvlist_to_dict(nvlist, props): def _dict_to_nvlist(props, nvlist): for k, v in list(props.items()): - if not isinstance(k, bytes): + if not (isinstance(k, bytes) or isinstance(k, str)): raise TypeError('Unsupported key type ' + type(k).__name__) + if isinstance(k, str): + k = k.encode() ret = 0 if isinstance(v, dict): ret = _lib.nvlist_add_nvlist(nvlist, k, nvlist_in(v)) @@ -240,6 +250,8 @@ def _dict_to_nvlist(props, nvlist): _nvlist_add_array(nvlist, k, v) elif isinstance(v, bytes): ret = _lib.nvlist_add_string(nvlist, k, v) + elif isinstance(v, str): + ret = _lib.nvlist_add_string(nvlist, k, v.encode()) elif isinstance(v, bool): ret = _lib.nvlist_add_boolean_value(nvlist, k, v) elif v is None: diff --git a/libzfs_core/test/test_libzfs_core.py b/libzfs_core/test/test_libzfs_core.py index 1852fb9..6201c8d 100644 --- a/libzfs_core/test/test_libzfs_core.py +++ b/libzfs_core/test/test_libzfs_core.py @@ -7,16 +7,10 @@ that the operations produce expected effects or fail with expected exceptions. """ -from __future__ import print_function from __future__ import division +from __future__ import print_function from __future__ import unicode_literals -from builtins import bytes -from builtins import zip -from builtins import range -from builtins import object -from past.utils import old_div -import unittest import contextlib import errno import filecmp @@ -28,7 +22,15 @@ import subprocess import tempfile import time +import unittest import uuid + +from builtins import object +from builtins import range +from builtins import str +from builtins import zip +from past.utils import old_div + from .. import _libzfs_core as lzc from .. import exceptions as lzc_exc @@ -3451,7 +3453,7 @@ class _TempPool(object): def __init__(self, size=128 * 1024 * 1024, readonly=False, filesystems=[]): self._filesystems = filesystems self._readonly = readonly - self._pool_name = 'pool.' + bytes(uuid.uuid4()) + self._pool_name = 'pool.' + str(uuid.uuid4()) self._root = _Filesystem(self._pool_name) (fd, self._pool_file_path) = tempfile.mkstemp( suffix='.zpool', prefix='tmp-') @@ -3610,20 +3612,20 @@ def reset(self): def getFilesystem(self): self._fs_id += 1 - fsname = self._name + '/fs' + bytes(self._fs_id) + fsname = self._name + '/fs' + str(self._fs_id) fs = _Filesystem(fsname) self._children.append(fs) return fs def _makeSnapName(self, i): - return self._name + '@snap' + bytes(i) + return self._name + '@snap' + str(i) def getSnap(self): self._snap_id += 1 return self._makeSnapName(self._snap_id) def _makeBookmarkName(self, i): - return self._name + '#bmark' + bytes(i) + return self._name + '#bmark' + str(i) def getBookmark(self): self._bmark_id += 1 From 325028f39b89057227d582ac5f5062ea459f7a37 Mon Sep 17 00:00:00 2001 From: Eshin Kunishima Date: Sun, 2 Apr 2017 22:59:20 +0900 Subject: [PATCH 6/7] [Python 2.7 & Python 3.6] fix TypeError: __name__ must be set to a string object --- libzfs_core/ctypes.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libzfs_core/ctypes.py b/libzfs_core/ctypes.py index d9acd57..bd168f2 100644 --- a/libzfs_core/ctypes.py +++ b/libzfs_core/ctypes.py @@ -3,7 +3,6 @@ """ Utility functions for casting to a specific C type. """ -from __future__ import unicode_literals from .bindings.libnvpair import ffi as _ffi @@ -22,7 +21,7 @@ def _func(value): else: _ffi.new(type_name + '*', value) return _ffi.cast(type_name, value) - _func.__name__ = type_name.encode() + _func.__name__ = type_name return _func From f1f1940749588ec001b775c5f91a2a0686a315c6 Mon Sep 17 00:00:00 2001 From: Eshin Kunishima Date: Mon, 3 Apr 2017 01:01:54 +0900 Subject: [PATCH 7/7] [Python 3.6] fix incompatible types on assertEqual and f.write --- libzfs_core/test/__init__.py | 43 ++++++++++++++++++++++++++++ libzfs_core/test/test_libzfs_core.py | 39 +++++++++++++------------ libzfs_core/test/test_nvlist.py | 28 +++++++++--------- 3 files changed, 78 insertions(+), 32 deletions(-) diff --git a/libzfs_core/test/__init__.py b/libzfs_core/test/__init__.py index e69de29..4e433cb 100644 --- a/libzfs_core/test/__init__.py +++ b/libzfs_core/test/__init__.py @@ -0,0 +1,43 @@ +""" +The package that contains a module for unit testing. +""" + +from __future__ import unicode_literals + +from builtins import str + + +def _bytes(obj): + """ + Convert str in complex object to bytes. + + :param object obj: the object includes str. + :return: return a new object includes converted bytes objects. + :rtype: object + """ + + def _b(s): + if isinstance(s, str): + return s.encode() + else: + return s + + if isinstance(obj, dict): + t = {} + for k, v in obj.items(): + if isinstance(k, str): + k = _b(k) + t[k] = _bytes(v) + return t + + elif isinstance(obj, list): + t = [] + for e in obj: + t.append(_bytes(e)) + return t + + elif isinstance(obj, str): + return _b(obj) + + else: + return obj diff --git a/libzfs_core/test/test_libzfs_core.py b/libzfs_core/test/test_libzfs_core.py index 6201c8d..36e9f08 100644 --- a/libzfs_core/test/test_libzfs_core.py +++ b/libzfs_core/test/test_libzfs_core.py @@ -31,6 +31,7 @@ from builtins import zip from past.utils import old_div +from . import _bytes from .. import _libzfs_core as lzc from .. import exceptions as lzc_exc @@ -160,7 +161,7 @@ def temp_file_in_fs(fs): with zfs_mount(fs) as mntdir: with tempfile.NamedTemporaryFile(dir=mntdir) as f: for i in range(1024): - f.write('x' * 1024) + f.write(_bytes('x' * 1024)) f.flush() yield f.name @@ -888,7 +889,7 @@ def test_rollback(self): lzc.lzc_snapshot([snapname]) ret = lzc.lzc_rollback(name) - self.assertEqual(ret, snapname) + self.assertEqual(ret, _bytes(snapname)) def test_rollback_2(self): name = ZFSTest.pool.makeName("fs1") @@ -898,7 +899,7 @@ def test_rollback_2(self): lzc.lzc_snapshot([snapname1]) lzc.lzc_snapshot([snapname2]) ret = lzc.lzc_rollback(name) - self.assertEqual(ret, snapname2) + self.assertEqual(ret, _bytes(snapname2)) def test_rollback_no_snaps(self): name = ZFSTest.pool.makeName("fs1") @@ -1262,7 +1263,7 @@ def test_snaprange_space_2(self): with zfs_mount(ZFSTest.pool.makeName("fs1")) as mntdir: with tempfile.NamedTemporaryFile(dir=mntdir) as f: for i in range(1024): - f.write('x' * 1024) + f.write(_bytes('x' * 1024)) f.flush() lzc.lzc_snapshot([snap2]) lzc.lzc_snapshot([snap3]) @@ -1280,7 +1281,7 @@ def test_snaprange_space_same_snap(self): with zfs_mount(ZFSTest.pool.makeName("fs1")) as mntdir: with tempfile.NamedTemporaryFile(dir=mntdir) as f: for i in range(1024): - f.write('x' * 1024) + f.write(_bytes('x' * 1024)) f.flush() lzc.lzc_snapshot([snap]) @@ -1394,7 +1395,7 @@ def test_send_space_2(self): with zfs_mount(ZFSTest.pool.makeName("fs1")) as mntdir: with tempfile.NamedTemporaryFile(dir=mntdir) as f: for i in range(1024): - f.write('x' * 1024) + f.write(_bytes('x' * 1024)) f.flush() lzc.lzc_snapshot([snap2]) lzc.lzc_snapshot([snap3]) @@ -1514,7 +1515,7 @@ def test_send_full(self): with zfs_mount(ZFSTest.pool.makeName("fs1")) as mntdir: with tempfile.NamedTemporaryFile(dir=mntdir) as f: for i in range(1024): - f.write('x' * 1024) + f.write(_bytes('x' * 1024)) f.flush() lzc.lzc_snapshot([snap]) @@ -1535,7 +1536,7 @@ def test_send_incremental(self): with zfs_mount(ZFSTest.pool.makeName("fs1")) as mntdir: with tempfile.NamedTemporaryFile(dir=mntdir) as f: for i in range(1024): - f.write('x' * 1024) + f.write(_bytes('x' * 1024)) f.flush() lzc.lzc_snapshot([snap2]) @@ -1751,7 +1752,7 @@ def test_send_to_broken_pipe_2(self): with zfs_mount(ZFSTest.pool.makeName("fs1")) as mntdir: with tempfile.NamedTemporaryFile(dir=mntdir) as f: for i in range(1024): - f.write('x' * 1024) + f.write(_bytes('x' * 1024)) f.flush() lzc.lzc_snapshot([snap]) @@ -2253,7 +2254,7 @@ def test_force_recv_full_existing_modified_mounted_fs(self): with zfs_mount(dstfs) as mntdir: f = tempfile.NamedTemporaryFile(dir=mntdir, delete=False) for i in range(1024): - f.write('x' * 1024) + f.write(_bytes('x' * 1024)) lzc.lzc_receive(dst, stream.fileno(), force=True) # The temporary file dissappears and any access, even close(), # results in EIO. @@ -2340,7 +2341,7 @@ def test_force_recv_incremental_modified_mounted_fs(self): with zfs_mount(dstfs) as mntdir: f = tempfile.NamedTemporaryFile(dir=mntdir, delete=False) for i in range(1024): - f.write('x' * 1024) + f.write(_bytes('x' * 1024)) lzc.lzc_receive(dst2, incr.fileno(), force=True) # The temporary file dissappears and any access, even close(), # results in EIO. @@ -2708,7 +2709,7 @@ def test_hold_many_with_one_missing(self): with cleanup_fd() as fd: missing = lzc.lzc_hold({snap1: 'tag', snap2: 'tag'}, fd) self.assertEqual(len(missing), 1) - self.assertEqual(missing[0], snap2) + self.assertEqual(missing[0], _bytes(snap2)) def test_hold_many_with_all_missing(self): snap1 = ZFSTest.pool.getRoot().getSnap() @@ -2717,7 +2718,7 @@ def test_hold_many_with_all_missing(self): with cleanup_fd() as fd: missing = lzc.lzc_hold({snap1: 'tag', snap2: 'tag'}, fd) self.assertEqual(len(missing), 2) - self.assertEqual(sorted(missing), sorted([snap1, snap2])) + self.assertEqual(sorted(missing), sorted(_bytes([snap1, snap2]))) def test_hold_missing_fs(self): # XXX skip pre-created filesystems @@ -2832,8 +2833,8 @@ def test_get_holds(self): holds = lzc.lzc_get_holds(snap) self.assertEquals(len(holds), 2) - self.assertIn('tag1', holds) - self.assertIn('tag2', holds) + self.assertIn(_bytes('tag1'), holds) + self.assertIn(_bytes('tag2'), holds) self.assertIsInstance(holds['tag1'], (int, int)) def test_get_holds_after_auto_cleanup(self): @@ -2976,21 +2977,21 @@ def test_release_hold_missing_tag(self): ret = lzc.lzc_release({snap: ['tag']}) self.assertEquals(len(ret), 1) - self.assertEquals(ret[0], snap + '#tag') + self.assertEquals(ret[0], _bytes(snap + '#tag')) def test_release_hold_missing_snap(self): snap = ZFSTest.pool.getRoot().getSnap() ret = lzc.lzc_release({snap: ['tag']}) self.assertEquals(len(ret), 1) - self.assertEquals(ret[0], snap) + self.assertEquals(ret[0], _bytes(snap)) def test_release_hold_missing_snap_2(self): snap = ZFSTest.pool.getRoot().getSnap() ret = lzc.lzc_release({snap: ['tag', 'another']}) self.assertEquals(len(ret), 1) - self.assertEquals(ret[0], snap) + self.assertEquals(ret[0], _bytes(snap)) def test_release_hold_across_pools(self): snap1 = ZFSTest.pool.getRoot().getSnap() @@ -3032,7 +3033,7 @@ def test_release_hold_too_long_snap_name_2(self): lzc.lzc_release({snap: ['tag']}) for e in ctx.exception.errors: self.assertIsInstance(e, lzc_exc.NameTooLong) - self.assertEquals(e.name, snap) + self.assertEquals(e.name, _bytes(snap)) def test_release_hold_invalid_snap_name(self): snap = ZFSTest.pool.getRoot().getSnap() + '@bad' diff --git a/libzfs_core/test/test_nvlist.py b/libzfs_core/test/test_nvlist.py index 67134ce..d9e493f 100644 --- a/libzfs_core/test/test_nvlist.py +++ b/libzfs_core/test/test_nvlist.py @@ -9,9 +9,11 @@ """ from __future__ import unicode_literals -from builtins import zip import unittest +from builtins import zip + +from . import _bytes from .._nvlist import nvlist_in, nvlist_out, _lib from ..ctypes import ( uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, @@ -69,17 +71,17 @@ def test_invalid_array_of_arrays_val_type(self): def test_string_value(self): props = {"key": "value"} res = self._dict_to_nvlist_to_dict(props) - self.assertEqual(props, res) + self.assertEqual(_bytes(props), res) def test_implicit_boolean_value(self): props = {"key": None} res = self._dict_to_nvlist_to_dict(props) - self.assertEqual(props, res) + self.assertEqual(_bytes(props), res) def test_boolean_values(self): props = {"key1": True, "key2": False} res = self._dict_to_nvlist_to_dict(props) - self.assertEqual(props, res) + self.assertEqual(_bytes(props), res) def test_explicit_boolean_true_value(self): props = {"key": boolean_t(1)} @@ -104,12 +106,12 @@ def test_explicit_boolean_another_invalid_value(self): def test_uint64_value(self): props = {"key": 1} res = self._dict_to_nvlist_to_dict(props) - self.assertEqual(props, res) + self.assertEqual(_bytes(props), res) def test_uint64_max_value(self): props = {"key": 2 ** 64 - 1} res = self._dict_to_nvlist_to_dict(props) - self.assertEqual(props, res) + self.assertEqual(_bytes(props), res) def test_uint64_too_large_value(self): props = {"key": 2 ** 64} @@ -324,12 +326,12 @@ def test_explicit_int8_too_small_value(self): def test_nested_dict(self): props = {"key": {}} res = self._dict_to_nvlist_to_dict(props) - self.assertEqual(props, res) + self.assertEqual(_bytes(props), res) def test_nested_nested_dict(self): props = {"key": {"key": {}}} res = self._dict_to_nvlist_to_dict(props) - self.assertEqual(props, res) + self.assertEqual(_bytes(props), res) def test_mismatching_values_array(self): props = {"key": [1, "string"]} @@ -349,12 +351,12 @@ def test_mismatching_values_array3(self): def test_string_array(self): props = {"key": ["value", "value2"]} res = self._dict_to_nvlist_to_dict(props) - self.assertEqual(props, res) + self.assertEqual(_bytes(props), res) def test_boolean_array(self): props = {"key": [True, False]} res = self._dict_to_nvlist_to_dict(props) - self.assertEqual(props, res) + self.assertEqual(_bytes(props), res) def test_explicit_boolean_array(self): props = {"key": [boolean_t(False), boolean_t(True)]} @@ -364,7 +366,7 @@ def test_explicit_boolean_array(self): def test_uint64_array(self): props = {"key": [0, 1, 2 ** 64 - 1]} res = self._dict_to_nvlist_to_dict(props) - self.assertEqual(props, res) + self.assertEqual(_bytes(props), res) def test_uint64_array_too_large_value(self): props = {"key": [0, 2 ** 64]} @@ -519,7 +521,7 @@ def test_explict_int8_array_too_small_value(self): def test_dict_array(self): props = {"key": [{"key": 1}, {"key": None}, {"key": {}}]} res = self._dict_to_nvlist_to_dict(props) - self.assertEqual(props, res) + self.assertEqual(_bytes(props), res) def test_implicit_uint32_value(self): props = {"rewind-request": 1} @@ -608,7 +610,7 @@ def test_complex_dict(self): "pool_context": -(2 ** 31) } res = self._dict_to_nvlist_to_dict(props) - self.assertEqual(props, res) + self.assertEqual(_bytes(props), res) # vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4