summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Cecile <adam.cecile@hitec.lu>2018-04-19 22:11:55 +0200
committerPrashanth Pai <ppai@redhat.com>2018-06-12 11:29:09 +0530
commitd5e4a0362a08ca3c0e7a33ea8caafccb22b906b2 (patch)
tree3670768441bf11b74139084322a10f97e355a4c5
parent7bf9472939a41ac92514d9bfec55f45a53cfba6b (diff)
Port to Python 3.x
Based on PR sent by Adam C├ęcile (eLvErDe on GitHub): https://github.com/gluster/libgfapi-python/pull/21 Additional changes to original PR: * Make it pep8 compliant * Fix comment in getcwd() * Add functest36 env to tox.ini Change-Id: I45c4056333c12a82814cf8adcfa87e6687365366 Signed-off-by: Prashanth Pai <ppai@redhat.com>
-rw-r--r--gluster/gfapi/__init__.py2
-rw-r--r--gluster/gfapi/gfapi.py181
-rw-r--r--setup.py5
-rw-r--r--test/__init__.py7
-rw-r--r--test/functional/libgfapi-python-tests.py105
-rw-r--r--test/unit/gluster/test_gfapi.py214
-rw-r--r--tox.ini12
7 files changed, 311 insertions, 215 deletions
diff --git a/gluster/gfapi/__init__.py b/gluster/gfapi/__init__.py
index 785b3e7..e3aa4d3 100644
--- a/gluster/gfapi/__init__.py
+++ b/gluster/gfapi/__init__.py
@@ -10,5 +10,5 @@
__version__ = '1.1'
-from gfapi import File, Dir, DirEntry, Volume
+from .gfapi import File, Dir, DirEntry, Volume
__all__ = ['File', 'Dir', 'DirEntry', 'Volume']
diff --git a/gluster/gfapi/gfapi.py b/gluster/gfapi/gfapi.py
index eedc03b..5078c00 100644
--- a/gluster/gfapi/gfapi.py
+++ b/gluster/gfapi/gfapi.py
@@ -8,7 +8,10 @@
# later), or the GNU General Public License, version 2 (GPLv2), in all
# cases as published by the Free Software Foundation.
+from __future__ import unicode_literals
+
import ctypes
+import sys
import os
import math
import time
@@ -25,6 +28,13 @@ from gluster.gfapi.utils import validate_mount, validate_glfd
python_mode_to_os_flags = {}
+PY3 = sys.version_info >= (3, 0)
+if PY3:
+ string_types = (str,)
+else:
+ string_types = (str, unicode)
+
+
def _populate_mode_to_flags_dict():
# http://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html
for mode in ['r', 'rb']:
@@ -43,6 +53,32 @@ def _populate_mode_to_flags_dict():
_populate_mode_to_flags_dict()
+def decode_to_bytes(text):
+ """
+ Decode unicode object to bytes
+ or return original object if already bytes
+ """
+ if isinstance(text, string_types):
+ return text.encode('utf-8')
+ elif isinstance(text, bytes):
+ return text
+ else:
+ raise ValueError('Cannot convert object with type %s' % type(text))
+
+
+def encode_to_string(text):
+ """
+ Encode bytes objects to unicode str
+ or return original object if already unicode
+ """
+ if isinstance(text, string_types):
+ return text
+ elif isinstance(text, bytes):
+ return text.decode('utf-8')
+ else:
+ raise ValueError('Cannot convert object with type %s' % type(text))
+
+
class File(object):
def __init__(self, fd, path=None, mode=None):
@@ -238,17 +274,18 @@ class File(object):
:raises: OSError on failure
"""
if size == 0:
- size = api.glfs_fgetxattr(self.fd, key, None, size)
+ size = api.glfs_fgetxattr(self.fd, decode_to_bytes(key),
+ None, size)
if size < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
buf = ctypes.create_string_buffer(size)
- rc = api.glfs_fgetxattr(self.fd, key, buf, size)
+ rc = api.glfs_fgetxattr(self.fd, decode_to_bytes(key), buf, size)
if rc < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
- return buf.value[:rc]
+ return encode_to_string(buf.value[:rc])
@validate_glfd
def flistxattr(self, size=0):
@@ -279,17 +316,23 @@ class File(object):
# buffer" format.
i = 0
while i < rc:
- new_xa = buf.raw[i]
+ if PY3:
+ new_xa = str(bytes([buf.raw[i]]), 'utf-8')
+ else:
+ new_xa = buf.raw[i]
i += 1
while i < rc:
- next_char = buf.raw[i]
+ if PY3:
+ next_char = str(bytes([buf.raw[i]]), 'utf-8')
+ else:
+ next_char = buf.raw[i]
i += 1
if next_char == '\0':
xattrs.append(new_xa)
break
new_xa += next_char
xattrs.sort()
- return xattrs
+ return [encode_to_string(x) for x in xattrs]
@validate_glfd
def fsetxattr(self, key, value, flags=0):
@@ -307,7 +350,9 @@ class File(object):
does not already exist.
:raises: OSError on failure
"""
- ret = api.glfs_fsetxattr(self.fd, key, value, len(value), flags)
+ ret = api.glfs_fsetxattr(self.fd, decode_to_bytes(key),
+ decode_to_bytes(value),
+ len(decode_to_bytes(value)), flags)
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -320,7 +365,7 @@ class File(object):
:param key: The key of extended attribute.
:raises: OSError on failure
"""
- ret = api.glfs_fremovexattr(self.fd, key)
+ ret = api.glfs_fremovexattr(self.fd, decode_to_bytes(key))
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -488,7 +533,7 @@ class Dir(Iterator):
self._api.glfs_closedir(self.fd)
self._api = None
- def next(self):
+ def __next__(self):
entry = api.Dirent()
entry.d_reclen = 256
@@ -514,6 +559,8 @@ class Dir(Iterator):
else:
return entry
+ next = __next__ # Python 2
+
class DirEntry(object):
"""
@@ -532,11 +579,11 @@ class DirEntry(object):
__slots__ = ('_name', '_vol', '_lstat', '_stat', '_path')
def __init__(self, vol, scandir_path, name, lstat):
- self._name = name
+ self._name = encode_to_string(name)
self._vol = vol
self._lstat = lstat
self._stat = None
- self._path = os.path.join(scandir_path, name)
+ self._path = os.path.join(scandir_path, self._name)
@property
def name(self):
@@ -662,7 +709,7 @@ class Volume(object):
raise LibgfapiException("Host and Volume name should not be None.")
if proto not in ('tcp', 'rdma', 'unix'):
raise LibgfapiException("Invalid protocol specified.")
- if not isinstance(port, (int, long)):
+ if not isinstance(port, int):
raise LibgfapiException("Invalid port specified.")
self.host = host
@@ -690,14 +737,16 @@ class Volume(object):
# Already mounted
return
- self.fs = api.glfs_new(self.volname)
+ self.fs = api.glfs_new(decode_to_bytes(self.volname))
if not self.fs:
err = ctypes.get_errno()
raise LibgfapiException("glfs_new(%s) failed: %s" %
(self.volname, os.strerror(err)))
- ret = api.glfs_set_volfile_server(self.fs, self.protocol,
- self.host, self.port)
+ ret = api.glfs_set_volfile_server(self.fs,
+ decode_to_bytes(self.protocol),
+ decode_to_bytes(self.host),
+ self.port)
if ret < 0:
err = ctypes.get_errno()
raise LibgfapiException("glfs_set_volfile_server(%s, %s, %s, "
@@ -762,7 +811,8 @@ class Volume(object):
Higher the value, more verbose the logging.
"""
if self.fs:
- ret = api.glfs_set_logging(self.fs, log_file, log_level)
+ ret = api.glfs_set_logging(self.fs, decode_to_bytes(log_file),
+ log_level)
if ret < 0:
err = ctypes.get_errno()
raise LibgfapiException("glfs_set_logging(%s, %s) failed: %s" %
@@ -805,7 +855,7 @@ class Volume(object):
and X_OK to test permissions
:returns: True if access is allowed, False if not
"""
- ret = api.glfs_access(self.fs, path, mode)
+ ret = api.glfs_access(self.fs, decode_to_bytes(path), mode)
if ret == 0:
return True
else:
@@ -819,7 +869,7 @@ class Volume(object):
:param path: Path to change current working directory to
:raises: OSError on failure
"""
- ret = api.glfs_chdir(self.fs, path)
+ ret = api.glfs_chdir(self.fs, decode_to_bytes(path))
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -833,7 +883,7 @@ class Volume(object):
:param mode: new mode
:raises: OSError on failure
"""
- ret = api.glfs_chmod(self.fs, path, mode)
+ ret = api.glfs_chmod(self.fs, decode_to_bytes(path), mode)
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -848,7 +898,7 @@ class Volume(object):
:param gid: new group id for path
:raises: OSError on failure
"""
- ret = api.glfs_chown(self.fs, path, uid, gid)
+ ret = api.glfs_chown(self.fs, decode_to_bytes(path), uid, gid)
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -888,10 +938,9 @@ class Volume(object):
PATH_MAX = 4096
buf = ctypes.create_string_buffer(PATH_MAX)
ret = api.glfs_getcwd(self.fs, buf, PATH_MAX)
- if ret < 0:
- err = ctypes.get_errno()
- raise OSError(err, os.strerror(err))
- return buf.value
+ if not ret:
+ raise OSError(errno.ENOENT, os.strerror(errno.ENOENT))
+ return encode_to_string(buf.value)
def getmtime(self, path):
"""
@@ -922,17 +971,19 @@ class Volume(object):
:raises: OSError on failure
"""
if size == 0:
- size = api.glfs_getxattr(self.fs, path, key, None, 0)
+ size = api.glfs_getxattr(self.fs, decode_to_bytes(path),
+ decode_to_bytes(key), None, 0)
if size < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
buf = ctypes.create_string_buffer(size)
- rc = api.glfs_getxattr(self.fs, path, key, buf, size)
+ rc = api.glfs_getxattr(self.fs, decode_to_bytes(path),
+ decode_to_bytes(key), buf, size)
if rc < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
- return buf.value[:rc]
+ return encode_to_string(buf.value[:rc])
def isdir(self, path):
"""
@@ -983,7 +1034,7 @@ class Volume(object):
for entry in self.opendir(path):
if not isinstance(entry, api.Dirent):
break
- name = entry.d_name[:entry.d_reclen]
+ name = encode_to_string(entry.d_name[:entry.d_reclen])
if name not in (".", ".."):
dir_list.append(name)
return dir_list
@@ -1007,7 +1058,7 @@ class Volume(object):
if not (isinstance(entry, api.Dirent) and
isinstance(stat_info, api.Stat)):
break
- name = entry.d_name[:entry.d_reclen]
+ name = encode_to_string(entry.d_name[:entry.d_reclen])
if name not in (".", ".."):
entries_with_stat.append((name, stat_info))
return entries_with_stat
@@ -1034,7 +1085,7 @@ class Volume(object):
"""
for (entry, lstat) in self.opendir(path, readdirplus=True):
name = entry.d_name[:entry.d_reclen]
- if name not in (".", ".."):
+ if name not in (b".", b".."):
yield DirEntry(self, path, name, lstat)
@validate_mount
@@ -1051,13 +1102,13 @@ class Volume(object):
:raises: OSError on failure
"""
if size == 0:
- size = api.glfs_listxattr(self.fs, path, None, 0)
+ size = api.glfs_listxattr(self.fs, decode_to_bytes(path), None, 0)
if size < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
buf = ctypes.create_string_buffer(size)
- rc = api.glfs_listxattr(self.fs, path, buf, size)
+ rc = api.glfs_listxattr(self.fs, decode_to_bytes(path), buf, size)
if rc < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -1067,17 +1118,23 @@ class Volume(object):
# buffer" format.
i = 0
while i < rc:
- new_xa = buf.raw[i]
+ if PY3:
+ new_xa = str(bytes([buf.raw[i]]), 'utf-8')
+ else:
+ new_xa = buf.raw[i]
i += 1
while i < rc:
- next_char = buf.raw[i]
+ if PY3:
+ next_char = str(bytes([buf.raw[i]]), 'utf-8')
+ else:
+ next_char = buf.raw[i]
i += 1
if next_char == '\0':
xattrs.append(new_xa)
break
new_xa += next_char
xattrs.sort()
- return xattrs
+ return [encode_to_string(x) for x in xattrs]
@validate_mount
def lstat(self, path):
@@ -1089,13 +1146,13 @@ class Volume(object):
:raises: OSError on failure
"""
s = api.Stat()
- rc = api.glfs_lstat(self.fs, path, ctypes.byref(s))
+ rc = api.glfs_lstat(self.fs, decode_to_bytes(path), ctypes.byref(s))
if rc < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
return s
- def makedirs(self, path, mode=0777):
+ def makedirs(self, path, mode=0o777):
"""
Recursive directory creation function. Like mkdir(), but makes all
intermediate-level directories needed to contain the leaf directory.
@@ -1119,14 +1176,14 @@ class Volume(object):
self.mkdir(path, mode)
@validate_mount
- def mkdir(self, path, mode=0777):
+ def mkdir(self, path, mode=0o777):
"""
Create a directory named path with numeric mode mode.
The default mode is 0777 (octal).
:raises: OSError on failure
"""
- ret = api.glfs_mkdir(self.fs, path, mode)
+ ret = api.glfs_mkdir(self.fs, decode_to_bytes(path), mode)
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -1156,7 +1213,7 @@ class Volume(object):
:raises: OSError on failure to create/open file.
TypeError and ValueError if mode is invalid.
"""
- if not isinstance(mode, basestring):
+ if not isinstance(mode, string_types):
raise TypeError("Mode must be a string")
try:
flags = python_mode_to_os_flags[mode]
@@ -1164,16 +1221,17 @@ class Volume(object):
raise ValueError("Invalid mode")
else:
if (os.O_CREAT & flags) == os.O_CREAT:
- fd = api.glfs_creat(self.fs, path, flags, 0666)
+ fd = api.glfs_creat(self.fs, decode_to_bytes(path),
+ flags, 0o666)
else:
- fd = api.glfs_open(self.fs, path, flags)
+ fd = api.glfs_open(self.fs, decode_to_bytes(path), flags)
if not fd:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
return File(fd, path=path, mode=mode)
@validate_mount
- def open(self, path, flags, mode=0777):
+ def open(self, path, flags, mode=0o777):
"""
Similar to Python's os.open()
@@ -1193,9 +1251,9 @@ class Volume(object):
raise TypeError("flags must evaluate to an integer")
if (os.O_CREAT & flags) == os.O_CREAT:
- fd = api.glfs_creat(self.fs, path, flags, mode)
+ fd = api.glfs_creat(self.fs, decode_to_bytes(path), flags, mode)
else:
- fd = api.glfs_open(self.fs, path, flags)
+ fd = api.glfs_open(self.fs, decode_to_bytes(path), flags)
if not fd:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -1213,7 +1271,7 @@ class Volume(object):
:returns: Returns a instance of Dir class
:raises: OSError on failure
"""
- fd = api.glfs_opendir(self.fs, path)
+ fd = api.glfs_opendir(self.fs, decode_to_bytes(path))
if not fd:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -1231,11 +1289,11 @@ class Volume(object):
"""
PATH_MAX = 4096
buf = ctypes.create_string_buffer(PATH_MAX)
- ret = api.glfs_readlink(self.fs, path, buf, PATH_MAX)
+ ret = api.glfs_readlink(self.fs, decode_to_bytes(path), buf, PATH_MAX)
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
- return buf.value[:ret]
+ return encode_to_string(buf.value[:ret])
def remove(self, path):
"""
@@ -1255,7 +1313,8 @@ class Volume(object):
:param key: The key of extended attribute.
:raises: OSError on failure
"""
- ret = api.glfs_removexattr(self.fs, path, key)
+ ret = api.glfs_removexattr(self.fs, decode_to_bytes(path),
+ decode_to_bytes(key))
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -1269,7 +1328,8 @@ class Volume(object):
:raises: OSError on failure
"""
- ret = api.glfs_rename(self.fs, src, dst)
+ ret = api.glfs_rename(self.fs, decode_to_bytes(src),
+ decode_to_bytes(dst))
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -1283,7 +1343,7 @@ class Volume(object):
:raises: OSError on failure
"""
- ret = api.glfs_rmdir(self.fs, path)
+ ret = api.glfs_rmdir(self.fs, decode_to_bytes(path))
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -1377,7 +1437,9 @@ class Volume(object):
:raises: OSError on failure
"""
- ret = api.glfs_setxattr(self.fs, path, key, value, len(value), flags)
+ ret = api.glfs_setxattr(self.fs, decode_to_bytes(path),
+ decode_to_bytes(key), decode_to_bytes(value),
+ len(decode_to_bytes(value)), flags)
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -1390,7 +1452,7 @@ class Volume(object):
:raises: OSError on failure
"""
s = api.Stat()
- rc = api.glfs_stat(self.fs, path, ctypes.byref(s))
+ rc = api.glfs_stat(self.fs, decode_to_bytes(path), ctypes.byref(s))
if rc < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -1411,7 +1473,7 @@ class Volume(object):
:raises: OSError on failure
"""
s = api.Statvfs()
- rc = api.glfs_statvfs(self.fs, path, ctypes.byref(s))
+ rc = api.glfs_statvfs(self.fs, decode_to_bytes(path), ctypes.byref(s))
if rc < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -1424,7 +1486,8 @@ class Volume(object):
:raises: OSError on failure
"""
- ret = api.glfs_link(self.fs, source, link_name)
+ ret = api.glfs_link(self.fs, decode_to_bytes(source),
+ decode_to_bytes(link_name))
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -1436,7 +1499,8 @@ class Volume(object):
:raises: OSError on failure
"""
- ret = api.glfs_symlink(self.fs, source, link_name)
+ ret = api.glfs_symlink(self.fs, decode_to_bytes(source),
+ decode_to_bytes(link_name))
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -1448,7 +1512,7 @@ class Volume(object):
:raises: OSError on failure
"""
- ret = api.glfs_unlink(self.fs, path)
+ ret = api.glfs_unlink(self.fs, decode_to_bytes(path))
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -1486,7 +1550,7 @@ class Volume(object):
timespec_array[1].tv_sec = int(whole)
timespec_array[1].tv_nsec = int(decimal * 1e9)
- ret = api.glfs_utimens(self.fs, path, timespec_array)
+ ret = api.glfs_utimens(self.fs, decode_to_bytes(path), timespec_array)
if ret < 0:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
@@ -1727,6 +1791,7 @@ class Volume(object):
self.makedirs(dst)
errors = []
for (name, st) in names_with_stat:
+ name = encode_to_string(name)
if name in ignored_names:
continue
srcpath = os.path.join(src, name)
diff --git a/setup.py b/setup.py
index b1645ea..853515c 100644
--- a/setup.py
+++ b/setup.py
@@ -51,8 +51,11 @@ setup(
'Operating System :: POSIX :: Linux',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
'Topic :: System :: Filesystems',
],
)
diff --git a/test/__init__.py b/test/__init__.py
index b00eb23..4186ad0 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -9,7 +9,10 @@
# cases as published by the Free Software Foundation.
import os
-import ConfigParser
+try:
+ from configparser import ConfigParser
+except ImportError:
+ from ConfigParser import ConfigParser
def get_test_config():
@@ -22,7 +25,7 @@ def get_test_config():
dirname = os.path.dirname(__file__)
conf_file = dirname + "/test.conf"
if os.path.exists(conf_file):
- config = ConfigParser.ConfigParser()
+ config = ConfigParser()
config.read(conf_file)
return config
return None
diff --git a/test/functional/libgfapi-python-tests.py b/test/functional/libgfapi-python-tests.py
index a64dbc2..be2801f 100644
--- a/test/functional/libgfapi-python-tests.py
+++ b/test/functional/libgfapi-python-tests.py
@@ -8,8 +8,11 @@
# later), or the GNU General Public License, version 2 (GPLv2), in all
# cases as published by the Free Software Foundation.
+from __future__ import unicode_literals
+
import unittest
import os
+import sys
import stat
import types
import errno
@@ -18,13 +21,18 @@ import threading
import uuid
from nose import SkipTest
from test import get_test_config
-from ConfigParser import NoSectionError, NoOptionError
+try:
+ from configparser import NoSectionError, NoOptionError
+except ImportError:
+ from ConfigParser import NoSectionError, NoOptionError
from uuid import uuid4
from gluster.gfapi.api import Stat
from gluster.gfapi import File, Volume, DirEntry
from gluster.gfapi.exceptions import LibgfapiException, Error
+PY3 = sys.version_info >= (3, 0)
+
config = get_test_config()
if config:
try:
@@ -66,7 +74,7 @@ class BinFileOpsTest(unittest.TestCase):
payload = bytearray(data, "ascii")
path = self._testMethodName + ".io"
with File(self.vol.open(path,
- os.O_CREAT | os.O_WRONLY | os.O_EXCL, 0644)) as f:
+ os.O_CREAT | os.O_WRONLY | os.O_EXCL, 0o644)) as f:
f.write(payload)
# Read binary data
with File(self.vol.open(path, os.O_RDONLY)) as f:
@@ -94,10 +102,10 @@ class FileOpsTest(unittest.TestCase):
cls.vol = None
def setUp(self):
- self.data = "gluster is awesome"
+ self.data = b"gluster is awesome"
self.path = self._testMethodName + ".io"
with File(self.vol.open(self.path,
- os.O_CREAT | os.O_WRONLY | os.O_EXCL, 0644),
+ os.O_CREAT | os.O_WRONLY | os.O_EXCL, 0o644),
path=self.path) as f:
rc = f.write(self.data)
self.assertEqual(rc, len(self.data))
@@ -112,7 +120,7 @@ class FileOpsTest(unittest.TestCase):
with File(self.vol.open(self.path, os.O_RDONLY)) as f:
self.assertTrue(isinstance(f, File))
buf = f.read(len(self.data))
- self.assertFalse(isinstance(buf, types.IntType))
+ self.assertFalse(isinstance(buf, int))
self.assertEqual(buf, self.data)
def test_open_file_not_exist(self):
@@ -171,11 +179,11 @@ class FileOpsTest(unittest.TestCase):
def test_fopen(self):
# Default permission should be 0666
name = uuid4().hex
- data = "Gluster is so awesome"
+ data = b"Gluster is so awesome"
with self.vol.fopen(name, 'w') as f:
f.write(data)
- perms = self.vol.stat(name).st_mode & 0777
- self.assertEqual(perms, int(0666))
+ perms = self.vol.stat(name).st_mode & 0o777
+ self.assertEqual(perms, int(0o666))
# 'r': Open file for reading.
# If not specified, mode should default to 'r'
@@ -218,18 +226,18 @@ class FileOpsTest(unittest.TestCase):
with self.vol.fopen(name, 'a') as f:
self.assertEqual('a', f.mode)
# This should be appended at the end
- f.write("hello")
+ f.write(b"hello")
with self.vol.fopen(name) as f:
- self.assertEqual(f.read(), data + "hello")
+ self.assertEqual(f.read(), data + b"hello")
# 'a+': Open for reading and appending (writing at end of file)
with self.vol.fopen(name, 'a+') as f:
self.assertEqual('a+', f.mode)
# This should be appended at the end
- f.write(" world")
+ f.write(b" world")
f.fsync()
f.lseek(0, os.SEEK_SET)
- self.assertEqual(f.read(), data + "hello world")
+ self.assertEqual(f.read(), data + b"hello world")
def test_fopen_in_thread(self):
def gluster_fopen():
@@ -256,7 +264,7 @@ class FileOpsTest(unittest.TestCase):
def test_write_file_dup_lseek_read(self):
try:
f = File(self.vol.open("dune", os.O_CREAT | os.O_EXCL | os.O_RDWR))
- f.write("I must not fear. Fear is the mind-killer.")
+ f.write(b"I must not fear. Fear is the mind-killer.")
fdup = f.dup()
self.assertTrue(isinstance(fdup, File))
f.close()
@@ -264,13 +272,13 @@ class FileOpsTest(unittest.TestCase):
self.assertEqual(ret, 0)
buf = fdup.read(15)
- self.assertEqual(buf, "I must not fear")
+ self.assertEqual(buf, b"I must not fear")
ret = fdup.lseek(29, os.SEEK_SET)
self.assertEqual(ret, 29)
buf = fdup.read(11)
- self.assertEqual(buf, "mind-killer")
+ self.assertEqual(buf, b"mind-killer")
fdup.close()
except OSError as e:
@@ -278,12 +286,18 @@ class FileOpsTest(unittest.TestCase):
def test_chmod(self):
stat = self.vol.stat(self.path)
- orig_mode = oct(stat.st_mode & 0777)
- self.assertEqual(orig_mode, '0644L')
- self.vol.chmod(self.path, 0600)
+ orig_mode = oct(stat.st_mode & 0o777)
+ if PY3:
+ self.assertEqual(orig_mode, '0o644')
+ else:
+ self.assertEqual(orig_mode, '0644L')
+ self.vol.chmod(self.path, 0o600)
stat = self.vol.stat(self.path)
- new_mode = oct(stat.st_mode & 0777)
- self.assertEqual(new_mode, '0600L')
+ new_mode = oct(stat.st_mode & 0o777)
+ if PY3:
+ self.assertEqual(new_mode, '0o600')
+ else:
+ self.assertEqual(new_mode, '0600L')
def test_exists(self):
e = self.vol.exists(self.path)
@@ -317,7 +331,7 @@ class FileOpsTest(unittest.TestCase):
def test_lstat(self):
sb = self.vol.lstat(self.path)
- self.assertFalse(isinstance(sb, types.IntType))
+ self.assertFalse(isinstance(sb, int))
self.assertEqual(sb.st_size, len(self.data))
def test_rename(self):
@@ -333,7 +347,7 @@ class FileOpsTest(unittest.TestCase):
def test_stat(self):
sb = self.vol.stat(self.path)
- self.assertFalse(isinstance(sb, types.IntType))
+ self.assertFalse(isinstance(sb, int))
self.assertEqual(sb.st_size, len(self.data))
def test_unlink(self):
@@ -461,14 +475,14 @@ class FileOpsTest(unittest.TestCase):
def test_ftruncate(self):
name = uuid4().hex
with File(self.vol.open(name, os.O_WRONLY | os.O_CREAT)) as f:
- f.write("123456789")
+ f.write(b"123456789")
f.ftruncate(5)
f.fsync()
with File(self.vol.open(name, os.O_RDONLY)) as f:
# The size should be reduced
self.assertEqual(f.fgetsize(), 5)
# So should be the content.
- self.assertEqual(f.read(), "12345")
+ self.assertEqual(f.read(), b"12345")
def test_fallocate(self):
name = uuid4().hex
@@ -492,15 +506,15 @@ class FileOpsTest(unittest.TestCase):
def test_zerofill(self):
name = uuid4().hex
with File(self.vol.open(name, os.O_RDWR | os.O_CREAT)) as f:
- f.write('0123456789')
+ f.write(b'0123456789')
f.fsync()
self.assertEqual(f.fstat().st_size, 10)
f.lseek(0, os.SEEK_SET)
- self.assertEqual(f.read(), '0123456789')
+ self.assertEqual(f.read(), b'0123456789')
f.zerofill(3, 6)
f.lseek(0, os.SEEK_SET)
data = f.read()
- self.assertEqual(data, '012\x00\x00\x00\x00\x00\x009')
+ self.assertEqual(data, b'012\x00\x00\x00\x00\x00\x009')
self.assertEqual(len(data), 10)
def test_utime(self):
@@ -589,17 +603,20 @@ class FileOpsTest(unittest.TestCase):
def test_readinto(self):
file_name = uuid4().hex
with File(self.vol.open(file_name, os.O_WRONLY | os.O_CREAT)) as f:
- s = ''.join([str(i) for i in xrange(10)])
- f.write(s)
+ s = ''.join([str(i) for i in range(10)])
+ f.write(bytearray(s, "ascii"))
f.fsync()
buf = bytearray(1)
with File(self.vol.open(file_name, os.O_RDONLY)) as f:
- for i in xrange(10):
+ for i in range(10):
# Read one character at a time into buf
f.readinto(buf)
self.assertEqual(len(buf), 1)
- self.assertEqual(buf, bytearray(str(i)))
+ if PY3:
+ self.assertEqual(buf, bytes(str(i), 'ascii'))
+ else:
+ self.assertEqual(buf, bytearray(str(i)))
with File(self.vol.open(file_name, os.O_RDONLY)) as f:
self.assertRaises(TypeError, f.readinto, str("buf"))
@@ -622,7 +639,7 @@ class FileOpsTest(unittest.TestCase):
# Create source file.
src_file = uuid4().hex
with self.vol.fopen(src_file, 'wb') as f:
- for i in xrange(2):
+ for i in range(2):
f.write(os.urandom(128 * 1024))
f.write(os.urandom(25 * 1024))
# Change/set atime and mtime
@@ -697,11 +714,11 @@ class FileOpsTest(unittest.TestCase):
def test_copymode(self):
src_file = uuid4().hex
self.vol.fopen(src_file, 'w').close()
- self.vol.chmod(src_file, 0644)
+ self.vol.chmod(src_file, 0o644)
dest_file = uuid4().hex
self.vol.fopen(dest_file, 'w').close()
- self.vol.chmod(dest_file, 0640)
+ self.vol.chmod(dest_file, 0o640)
self.vol.copymode(src_file, dest_file)
self.assertEqual(self.vol.stat(src_file).st_mode,
@@ -711,7 +728,7 @@ class FileOpsTest(unittest.TestCase):
# Create source file and set mode, atime, mtime
src_file = uuid4().hex
self.vol.fopen(src_file, 'w').close()
- self.vol.chmod(src_file, 0640)
+ self.vol.chmod(src_file, 0o640)
(atime, mtime) = (692884800, 692884800)
self.vol.utime(src_file, (atime, mtime))
@@ -733,7 +750,7 @@ class FileOpsTest(unittest.TestCase):
# Create source file.
src_file = uuid4().hex
with self.vol.fopen(src_file, 'wb') as f:
- for i in xrange(2):
+ for i in range(2):
f.write(os.urandom(128 * 1024))
f.write(os.urandom(25 * 1024))
@@ -766,7 +783,7 @@ class FileOpsTest(unittest.TestCase):
# Create source file.
src_file = uuid4().hex
with self.vol.fopen(src_file, 'wb') as f:
- for i in xrange(2):
+ for i in range(2):
f.write(os.urandom(128 * 1024))
f.write(os.urandom(25 * 1024))
(atime, mtime) = (692884800, 692884800)
@@ -820,7 +837,7 @@ class DirOpsTest(unittest.TestCase):
# Create a filesystem tree
self.data = "gluster is awesome"
self.dir_path = self._testMethodName + "_dir"
- self.vol.mkdir(self.dir_path, 0755)
+ self.vol.mkdir(self.dir_path, 0o755)
for x in range(0, 3):
d = os.path.join(self.dir_path, 'testdir' + str(x))
self.vol.mkdir(d)
@@ -926,23 +943,21 @@ class DirOpsTest(unittest.TestCase):
def test_makedirs(self):
name = self.dir_path + "/subd1/subd2/subd3"
- self.vol.makedirs(name, 0755)
+ self.vol.makedirs(name, 0o755)
self.assertTrue(self.vol.isdir(name))
def test_statvfs(self):
sb = self.vol.statvfs("/")
- self.assertFalse(isinstance(sb, types.IntType))
- self.assertEqual(sb.f_namemax, 255L)
+ self.assertFalse(isinstance(sb, int))
+ self.assertEqual(sb.f_namemax, 255)
# creating a dir, checking Total number of free inodes
# is reduced
- self.vol.makedirs("statvfs_dir1", 0755)
+ self.vol.makedirs("statvfs_dir1", 0o755)
sb2 = self.vol.statvfs("/")
self.assertTrue(sb2.f_ffree < sb.f_ffree)
def test_rmtree(self):
- """
- by testing rmtree, we are also testing unlink and rmdir
- """
+ # By testing rmtree, we are also testing unlink and rmdir
f = os.path.join(self.dir_path, "testdir0", "nestedfile0")
self.vol.exists(f)
d = os.path.join(self.dir_path, "testdir0")
diff --git a/test/unit/gluster/test_gfapi.py b/test/unit/gluster/test_gfapi.py
index 4216f96..d35d7e1 100644
--- a/test/unit/gluster/test_gfapi.py
+++ b/test/unit/gluster/test_gfapi.py
@@ -8,6 +8,8 @@
# later), or the GNU General Public License, version 2 (GPLv2), in all
# cases as published by the Free Software Foundation.
+from __future__ import unicode_literals
+
import unittest
import gluster
import inspect
@@ -22,7 +24,6 @@ from gluster.gfapi import api
from gluster.gfapi.exceptions import LibgfapiException
from nose import SkipTest
from mock import Mock, MagicMock, patch
-from contextlib import nested
def _mock_glfs_close(fd):
@@ -105,14 +106,14 @@ class TestFile(unittest.TestCase):
mock_glfs_fchmod.return_value = 0
with patch("gluster.gfapi.api.glfs_fchmod", mock_glfs_fchmod):
- self.fd.fchmod(0600)
+ self.fd.fchmod(0o600)
def test_fchmod_fail_exception(self):
mock_glfs_fchmod = Mock()
mock_glfs_fchmod.return_value = -1
with patch("gluster.gfapi.api.glfs_fchmod", mock_glfs_fchmod):
- self.assertRaises(OSError, self.fd.fchmod, 0600)
+ self.assertRaises(OSError, self.fd.fchmod, 0o600)
def test_fchown_success(self):
mock_glfs_fchown = Mock()
@@ -169,6 +170,7 @@ class TestFile(unittest.TestCase):
def test_fsync_success(self):
mock_glfs_fsync = Mock()
+ mock_glfs_fsync.return_value = 0
with patch("gluster.gfapi.api.glfs_fsync", mock_glfs_fsync):
self.fd.fsync()
@@ -190,12 +192,12 @@ class TestFile(unittest.TestCase):
def test_read_success(self):
def _mock_glfs_read(fd, rbuf, buflen, flags):
- rbuf.value = "hello"
+ rbuf.value = b"hello"
return 5
with patch("gluster.gfapi.api.glfs_read", _mock_glfs_read):
b = self.fd.read(5)
- self.assertEqual(b, "hello")
+ self.assertEqual(b, b"hello")
def test_read_fail_exception(self):
mock_glfs_read = Mock()
@@ -311,7 +313,7 @@ class TestDir(unittest.TestCase):
with patch("gluster.gfapi.api.glfs_readdir_r", mock_glfs_readdir_r):
fd = Dir(2)
- ent = fd.next()
+ ent = next(fd)
self.assertTrue(isinstance(ent, api.Dirent))
@@ -387,7 +389,7 @@ class TestVolume(unittest.TestCase):
with patch("gluster.gfapi.api.glfs_new", _m_glfs_new):
# Mounting for first time
v.mount()
- _m_glfs_new.assert_called_once_with("vol")
+ _m_glfs_new.assert_called_once_with(b"vol")
_m_glfs_new.reset_mock()
for i in range(0, 5):
v.mount()
@@ -402,7 +404,7 @@ class TestVolume(unittest.TestCase):
self.assertRaises(LibgfapiException, v.mount)
self.assertFalse(v.fs)
self.assertFalse(v.mounted)
- _m_glfs_new.assert_called_once_with("vol")
+ _m_glfs_new.assert_called_once_with(b"vol")
# glfs_set_volfile_server() failed
_m_set_vol = Mock(return_value=-1)
@@ -410,9 +412,9 @@ class TestVolume(unittest.TestCase):
with patch("gluster.gfapi.api.glfs_set_volfile_server", _m_set_vol):
self.assertRaises(LibgfapiException, v.mount)
self.assertFalse(v.mounted)
- _m_glfs_new.assert_called_once_with("vol")
- _m_set_vol.assert_called_once_with(v.fs, v.protocol,
- v.host, v.port)
+ _m_glfs_new.assert_called_once_with(b"vol")
+ _m_set_vol.assert_called_once_with(v.fs, v.protocol.encode('utf-8'),
+ v.host.encode('utf-8'), v.port)
# glfs_init() failed
_m_glfs_init = Mock(return_value=-1)
@@ -433,7 +435,7 @@ class TestVolume(unittest.TestCase):
self.assertTrue(v.mounted)
def test_set_logging(self):
- _m_set_logging = Mock()
+ _m_set_logging = Mock(return_value=0)
# Called after mount()
v = Volume("host", "vol")
@@ -449,21 +451,21 @@ class TestVolume(unittest.TestCase):
_m_set_logging = Mock(return_value=-1)
with patch("gluster.gfapi.api.glfs_set_logging", _m_set_logging):
self.assertRaises(LibgfapiException, v.set_logging, "/dev/null", 7)
- _m_set_logging.assert_called_once_with(v.fs, "/dev/null", 7)
+ _m_set_logging.assert_called_once_with(v.fs, b"/dev/null", 7)
def test_chmod_success(self):
mock_glfs_chmod = Mock()
mock_glfs_chmod.return_value = 0
with patch("gluster.gfapi.api.glfs_chmod", mock_glfs_chmod):
- self.vol.chmod("file.txt", 0600)
+ self.vol.chmod("file.txt", 0o600)
def test_chmod_fail_exception(self):
mock_glfs_chmod = Mock()
mock_glfs_chmod.return_value = -1
with patch("gluster.gfapi.api.glfs_chmod", mock_glfs_chmod):
- self.assertRaises(OSError, self.vol.chmod, "file.txt", 0600)
+ self.assertRaises(OSError, self.vol.chmod, "file.txt", 0o600)
def test_chown_success(self):
mock_glfs_chown = Mock()
@@ -484,12 +486,12 @@ class TestVolume(unittest.TestCase):
mock_glfs_creat.return_value = 2
with patch("gluster.gfapi.api.glfs_creat", mock_glfs_creat):
- with File(self.vol.open("file.txt", os.O_CREAT, 0644)) as f:
+ with File(self.vol.open("file.txt", os.O_CREAT, 0o644)) as f:
self.assertTrue(isinstance(f, File))
self.assertEqual(mock_glfs_creat.call_count, 1)
mock_glfs_creat.assert_called_once_with(12345,
- "file.txt",
- os.O_CREAT, 0644)
+ b"file.txt",
+ os.O_CREAT, 0o644)
def test_exists_true(self):
mock_glfs_stat = Mock()
@@ -593,12 +595,12 @@ class TestVolume(unittest.TestCase):
def test_getxattr_success(self):
def mock_glfs_getxattr(fs, path, key, buf, maxlen):
- buf.value = "fake_xattr"
+ buf.value = b"fake_xattr"
return 10
with patch("gluster.gfapi.api.glfs_getxattr", mock_glfs_getxattr):
buf = self.vol.getxattr("file.txt", "key1", 32)
- self.assertEquals("fake_xattr", buf)
+ self.assertEqual("fake_xattr", buf)
def test_getxattr_fail_exception(self):
mock_glfs_getxattr = Mock()
@@ -613,23 +615,23 @@ class TestVolume(unittest.TestCase):
mock_glfs_opendir.return_value = 2
dirent1 = api.Dirent()
- dirent1.d_name = "mockfile"
+ dirent1.d_name = b"mockfile"
dirent1.d_reclen = 8
dirent2 = api.Dirent()
- dirent2.d_name = "mockdir"
+ dirent2.d_name = b"mockdir"
dirent2.d_reclen = 7
dirent3 = api.Dirent()
- dirent3.d_name = "."
+ dirent3.d_name = b"."
dirent3.d_reclen = 1
mock_Dir_next = Mock()
mock_Dir_next.side_effect = [dirent1, dirent2, dirent3, StopIteration]
- with nested(patch("gluster.gfapi.api.glfs_opendir",
- mock_glfs_opendir),
- patch("gluster.gfapi.Dir.next", mock_Dir_next)):
- d = self.vol.listdir("testdir")
- self.assertEqual(len(d), 2)
- self.assertEqual(d[0], 'mockfile')
+ with patch("gluster.gfapi.api.glfs_opendir", mock_glfs_opendir):
+ with patch("gluster.gfapi.Dir.__next__", mock_Dir_next):
+ with patch("gluster.gfapi.Dir.next", mock_Dir_next):
+ d = self.vol.listdir("testdir")
+ self.assertEqual(len(d), 2)
+ self.assertEqual(d[0], 'mockfile')
def test_listdir_fail_exception(self):
mock_glfs_opendir = Mock()
@@ -643,17 +645,17 @@ class TestVolume(unittest.TestCase):
mock_glfs_opendir.return_value = 2
dirent1 = api.Dirent()
- dirent1.d_name = "mockfile"
+ dirent1.d_name = b"mockfile"
dirent1.d_reclen = 8
stat1 = api.Stat()
stat1.st_nlink = 1
dirent2 = api.Dirent()
- dirent2.d_name = "mockdir"
+ dirent2.d_name = b"mockdir"
dirent2.d_reclen = 7
stat2 = api.Stat()
stat2.st_nlink = 2
dirent3 = api.Dirent()
- dirent3.d_name = "."
+ dirent3.d_name = b"."
dirent3.d_reclen = 1
stat3 = api.Stat()
stat3.n_link = 2
@@ -663,15 +665,15 @@ class TestVolume(unittest.TestCase):
(dirent3, stat3),
StopIteration]
- with nested(patch("gluster.gfapi.api.glfs_opendir",
- mock_glfs_opendir),
- patch("gluster.gfapi.Dir.next", mock_Dir_next)):
- d = self.vol.listdir_with_stat("testdir")
- self.assertEqual(len(d), 2)
- self.assertEqual(d[0][0], 'mockfile')
- self.assertEqual(d[0][1].st_nlink, 1)
- self.assertEqual(d[1][0], 'mockdir')
- self.assertEqual(d[1][1].st_nlink, 2)
+ with patch("gluster.gfapi.api.glfs_opendir", mock_glfs_opendir):
+ with patch("gluster.gfapi.Dir.__next__", mock_Dir_next):
+ with patch("gluster.gfapi.Dir.next", mock_Dir_next):
+ d = self.vol.listdir_with_stat("testdir")
+ self.assertEqual(len(d), 2)
+ self.assertEqual(d[0][0], 'mockfile')
+ self.assertEqual(d[0][1].st_nlink, 1)
+ self.assertEqual(d[1][0], 'mockdir')
+ self.assertEqual(d[1][1].st_nlink, 2)
def test_listdir_with_stat_fail_exception(self):
mock_glfs_opendir = Mock()
@@ -684,19 +686,19 @@ class TestVolume(unittest.TestCase):
mock_glfs_opendir.return_value = 2
dirent1 = api.Dirent()
- dirent1.d_name = "mockfile"
+ dirent1.d_name = b"mockfile"
dirent1.d_reclen = 8
stat1 = api.Stat()
stat1.st_nlink = 1
stat1.st_mode = 33188
dirent2 = api.Dirent()
- dirent2.d_name = "mockdir"
+ dirent2.d_name = b"mockdir"
dirent2.d_reclen = 7
stat2 = api.Stat()
stat2.st_nlink = 2
stat2.st_mode = 16877
dirent3 = api.Dirent()
- dirent3.d_name = "."
+ dirent3.d_name = b"."
dirent3.d_reclen = 1
stat3 = api.Stat()
stat3.n_link = 2
@@ -707,31 +709,31 @@ class TestVolume(unittest.TestCase):
(dirent3, stat3),
StopIteration]
- with nested(patch("gluster.gfapi.api.glfs_opendir",
- mock_glfs_opendir),
- patch("gluster.gfapi.Dir.next", mock_Dir_next)):
- i = 0
- for entry in self.vol.scandir("testdir"):
- self.assertTrue(isinstance(entry, DirEntry))
- if entry.name == 'mockfile':
- self.assertEqual(entry.path, 'testdir/mockfile')
- self.assertTrue(entry.is_file())
- self.assertFalse(entry.is_dir())
- self.assertEqual(entry.stat().st_nlink, 1)
- elif entry.name == 'mockdir':
- self.assertEqual(entry.path, 'testdir/mockdir')
- self.assertTrue(entry.is_dir())
- self.assertFalse(entry.is_file())
- self.assertEqual(entry.stat().st_nlink, 2)
- else:
- self.fail("Unexpected entry")
- i = i + 1
- self.assertEqual(i, 2)
+ with patch("gluster.gfapi.api.glfs_opendir", mock_glfs_opendir):
+ with patch("gluster.gfapi.Dir.__next__", mock_Dir_next):
+ with patch("gluster.gfapi.Dir.next", mock_Dir_next):
+ i = 0
+ for entry in self.vol.scandir("testdir"):
+ self.assertTrue(isinstance(entry, DirEntry))
+ if entry.name == 'mockfile':
+ self.assertEqual(entry.path, 'testdir/mockfile')
+ self.assertTrue(entry.is_file())
+ self.assertFalse(entry.is_dir())
+ self.assertEqual(entry.stat().st_nlink, 1)
+ elif entry.name == 'mockdir':
+ self.assertEqual(entry.path, 'testdir/mockdir')
+ self.assertTrue(entry.is_dir())
+ self.assertFalse(entry.is_file())
+ self.assertEqual(entry.stat().st_nlink, 2)
+ else:
+ self.fail("Unexpected entry")
+ i = i + 1
+ self.assertEqual(i, 2)
def test_listxattr_success(self):
def mock_glfs_listxattr(fs, path, buf, buflen):
if buf:
- buf.raw = "key1\0key2\0"
+ buf.raw = b"key1\0key2\0"
return 10
with patch("gluster.gfapi.api.glfs_listxattr", mock_glfs_listxattr):
@@ -798,11 +800,11 @@ class TestVolume(unittest.TestCase):
mock_exists = Mock()
mock_exists.side_effect = (False, True, False)
- with nested(patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir),
- patch("gluster.gfapi.Volume.exists", mock_exists)):
- self.vol.makedirs("dir1/", 0775)
- self.assertEqual(mock_glfs_mkdir.call_count, 1)
- mock_glfs_mkdir.assert_any_call(self.vol.fs, "dir1/", 0775)
+ with patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir):
+ with patch("gluster.gfapi.Volume.exists", mock_exists):
+ self.vol.makedirs("dir1/", 0o775)
+ self.assertEqual(mock_glfs_mkdir.call_count, 1)
+ mock_glfs_mkdir.assert_any_call(self.vol.fs, b"dir1/", 0o775)
def test_makedirs_success_EEXIST(self):
err = errno.EEXIST
@@ -812,13 +814,13 @@ class TestVolume(unittest.TestCase):
mock_exists = Mock()
mock_exists.side_effect = [False, True, False]
- with nested(patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir),
- patch("gluster.gfapi.Volume.exists", mock_exists)):
- self.vol.makedirs("./dir1/dir2", 0775)
- self.assertEqual(mock_glfs_mkdir.call_count, 2)
- mock_glfs_mkdir.assert_any_call(self.vol.fs, "./dir1", 0775)
- mock_glfs_mkdir.assert_called_with(self.vol.fs, "./dir1/dir2",
- 0775)
+ with patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir):
+ with patch("gluster.gfapi.Volume.exists", mock_exists):
+ self.vol.makedirs("./dir1/dir2", 0o775)
+ self.assertEqual(mock_glfs_mkdir.call_count, 2)
+ mock_glfs_mkdir.assert_any_call(self.vol.fs, b"./dir1", 0o775)
+ mock_glfs_mkdir.assert_called_with(self.vol.fs, b"./dir1/dir2",
+ 0o775)
def test_makedirs_fail_exception(self):
mock_glfs_mkdir = Mock()
@@ -827,23 +829,23 @@ class TestVolume(unittest.TestCase):
mock_exists = Mock()
mock_exists.return_value = False
- with nested(patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir),
- patch("gluster.gfapi.Volume.exists", mock_exists)):
- self.assertRaises(OSError, self.vol.makedirs, "dir1/dir2", 0775)
+ with patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir):
+ with patch("gluster.gfapi.Volume.exists", mock_exists):
+ self.assertRaises(OSError, self.vol.makedirs, "dir1/dir2", 0o775)
def test_mkdir_success(self):
mock_glfs_mkdir = Mock()
mock_glfs_mkdir.return_value = 0
with patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir):
- self.vol.mkdir("testdir", 0775)
+ self.vol.mkdir("testdir", 0o775)
def test_mkdir_fail_exception(self):
mock_glfs_mkdir = Mock()
mock_glfs_mkdir.return_value = -1
with patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir):
- self.assertRaises(OSError, self.vol.mkdir, "testdir", 0775)
+ self.assertRaises(OSError, self.vol.mkdir, "testdir", 0o775)
def test_open_with_statement_success(self):
mock_glfs_open = Mock()
@@ -854,7 +856,7 @@ class TestVolume(unittest.TestCase):
self.assertTrue(isinstance(f, File))
self.assertEqual(mock_glfs_open.call_count, 1)
mock_glfs_open.assert_called_once_with(12345,
- "file.txt", os.O_WRONLY)
+ b"file.txt", os.O_WRONLY)
def test_open_with_statement_fail_exception(self):
mock_glfs_open = Mock()
@@ -875,7 +877,7 @@ class TestVolume(unittest.TestCase):
f = File(self.vol.open("file.txt", os.O_WRONLY))
self.assertTrue(isinstance(f, File))
self.assertEqual(mock_glfs_open.call_count, 1)
- mock_glfs_open.assert_called_once_with(12345, "file.txt",
+ mock_glfs_open.assert_called_once_with(12345, b"file.txt",
os.O_WRONLY)
def test_open_direct_fail_exception(self):
@@ -971,11 +973,11 @@ class TestVolume(unittest.TestCase):
mock_rmdir = Mock()
mock_islink = Mock(return_value=False)
- with nested(patch("gluster.gfapi.Volume.scandir", mock_scandir),
- patch("gluster.gfapi.Volume.islink", mock_islink),
- patch("gluster.gfapi.Volume.unlink", mock_unlink),
- patch("gluster.gfapi.Volume.rmdir", mock_rmdir)):
- self.vol.rmtree("dirpath")
+ with patch("gluster.gfapi.Volume.scandir", mock_scandir):
+ with patch("gluster.gfapi.Volume.islink", mock_islink):
+ with patch("gluster.gfapi.Volume.unlink", mock_unlink):
+ with patch("gluster.gfapi.Volume.rmdir", mock_rmdir):
+ self.vol.rmtree("dirpath")
mock_islink.assert_called_once_with("dirpath")
mock_unlink.assert_called_once_with("dirpath/file1")
@@ -988,9 +990,9 @@ class TestVolume(unittest.TestCase):
mock_islink = Mock()
mock_islink.return_value = False
- with nested(patch("gluster.gfapi.Volume.scandir", mock_scandir),
- patch("gluster.gfapi.Volume.islink", mock_islink)):
- self.assertRaises(OSError, self.vol.rmtree, "dir1")
+ with patch("gluster.gfapi.Volume.scandir", mock_scandir):
+ with patch("gluster.gfapi.Volume.islink", mock_islink):
+ self.assertRaises(OSError, self.vol.rmtree, "dir1")
def test_rmtree_islink_exception(self):
mock_islink = Mock()
@@ -1010,11 +1012,11 @@ class TestVolume(unittest.TestCase):
mock_rmdir = Mock(side_effect=OSError)
mock_islink = Mock(return_value=False)
- with nested(patch("gluster.gfapi.Volume.scandir", mock_scandir),
- patch("gluster.gfapi.Volume.islink", mock_islink),
- patch("gluster.gfapi.Volume.unlink", mock_unlink),
- patch("gluster.gfapi.Volume.rmdir", mock_rmdir)):
- self.vol.rmtree("dirpath", True)
+ with patch("gluster.gfapi.Volume.scandir", mock_scandir):
+ with patch("gluster.gfapi.Volume.islink", mock_islink):
+ with patch("gluster.gfapi.Volume.unlink", mock_unlink):
+ with patch("gluster.gfapi.Volume.rmdir", mock_rmdir):
+ self.vol.rmtree("dirpath", True)
mock_islink.assert_called_once_with("dirpath")
mock_unlink.assert_called_once_with("dirpath/file1")
@@ -1131,14 +1133,14 @@ class TestVolume(unittest.TestCase):
m_utime = Mock()
m_chmod = Mock()
m_copystat = Mock()
- with nested(patch("gluster.gfapi.Volume.listdir_with_stat", m_list_s),
- patch("gluster.gfapi.Volume.makedirs", m_makedirs),
- patch("gluster.gfapi.Volume.fopen", m_fopen),
- patch("gluster.gfapi.Volume.copyfileobj", m_copyfileobj),
- patch("gluster.gfapi.Volume.utime", m_utime),
- patch("gluster.gfapi.Volume.chmod", m_chmod),
- patch("gluster.gfapi.Volume.copystat", m_copystat)):
- self.vol.copytree('/source', '/destination')
+ with patch("gluster.gfapi.Volume.listdir_with_stat", m_list_s):
+ with patch("gluster.gfapi.Volume.makedirs", m_makedirs):
+ with patch("gluster.gfapi.Volume.fopen", m_fopen):
+ with patch("gluster.gfapi.Volume.copyfileobj", m_copyfileobj):
+ with patch("gluster.gfapi.Volume.utime", m_utime):
+ with patch("gluster.gfapi.Volume.chmod", m_chmod):
+ with patch("gluster.gfapi.Volume.copystat", m_copystat):
+ self.vol.copytree('/source', '/destination')
# Assert that listdir_with_stat() was called on all directories
self.assertEqual(m_list_s.call_count, 3 + 1)
@@ -1176,7 +1178,7 @@ class TestVolume(unittest.TestCase):
with patch("gluster.gfapi.api.glfs_utimens", mock_glfs_utimens):
self.vol.utime('/path', (atime, mtime))
self.assertTrue(mock_glfs_utimens.called)
- self.assertEqual(mock_glfs_utimens.call_args[0][1], '/path')
+ self.assertEqual(mock_glfs_utimens.call_args[0][1], b'/path')
# verify atime and mtime
self.assertEqual(mock_glfs_utimens.call_args[0][2][0].tv_sec,
int(atime))
diff --git a/tox.ini b/tox.ini
index b9213ba..b702b3a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = py26,py27,pep8
+envlist = py26,py27,py36,pep8
minversion = 1.6
[testenv]
@@ -14,7 +14,15 @@ deps =
commands = nosetests -v {posargs:test/unit}
[testenv:functest]
-commands = ./.functests {posargs}
+commands = nosetests -s -v {posargs:test/functional}
+
+[testenv:functest27]
+basepython = python2.7
+commands = nosetests -s -v {posargs:test/functional}
+
+[testenv:functest36]
+basepython = python3.6
+commands = nosetests -s -v {posargs:test/functional}
[testenv:pep8]
commands =