summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--glusterfs/gfapi.py42
-rw-r--r--test/functional/libgfapi-python-tests.py30
-rw-r--r--test/unit/gluster/test_gfapi.py39
-rw-r--r--tox.ini2
4 files changed, 68 insertions, 45 deletions
diff --git a/glusterfs/gfapi.py b/glusterfs/gfapi.py
index 8eeb3d6..6ca2ad7 100644
--- a/glusterfs/gfapi.py
+++ b/glusterfs/gfapi.py
@@ -19,8 +19,6 @@ import os
import stat
import errno
-from contextlib import contextmanager
-
# Disclaimer: many of the helper functions (e.g., exists, isdir) where copied
# from the python source code
@@ -92,6 +90,17 @@ class File(object):
def __init__(self, fd):
self.fd = fd
+ def __enter__(self):
+ if self.fd is None:
+ # __enter__ should only be called within the context
+ # of a 'with' statement when opening a file through
+ # Volume.open()
+ raise ValueError("I/O operation on closed file")
+ return self
+
+ def __exit__(self, type, value, tb):
+ self.close()
+
def close(self):
ret = api.glfs_close(self.fd)
if ret < 0:
@@ -243,20 +252,6 @@ class Volume(object):
raise OSError(err, os.strerror(err))
return ret
- @contextmanager
- def creat(self, path, flags, mode):
- fd = api.glfs_creat(self.fs, path, flags, mode)
- if not fd:
- err = ctypes.get_errno()
- raise OSError(err, os.strerror(err))
-
- fileobj = None
- try:
- fileobj = File(fd)
- yield fileobj
- finally:
- fileobj.close()
-
def exists(self, path):
"""
Test whether a path exists.
@@ -384,19 +379,16 @@ class Volume(object):
raise OSError(err, os.strerror(err))
return ret
- @contextmanager
- def open(self, path, flags):
- fd = api.glfs_open(self.fs, path, flags)
+ def open(self, path, flags, mode=0777):
+ if (os.O_CREAT & flags) == os.O_CREAT:
+ fd = api.glfs_creat(self.fs, path, flags, mode)
+ else:
+ fd = api.glfs_open(self.fs, path, flags)
if not fd:
err = ctypes.get_errno()
raise OSError(err, os.strerror(err))
- fileobj = None
- try:
- fileobj = File(fd)
- yield fileobj
- finally:
- fileobj.close()
+ return File(fd)
def opendir(self, path):
fd = api.glfs_opendir(self.fs, path)
diff --git a/test/functional/libgfapi-python-tests.py b/test/functional/libgfapi-python-tests.py
index cdb556c..ac5c38f 100644
--- a/test/functional/libgfapi-python-tests.py
+++ b/test/functional/libgfapi-python-tests.py
@@ -17,6 +17,7 @@ import unittest
import os
import types
import loremipsum
+import errno
from glusterfs import gfapi
@@ -40,7 +41,8 @@ class BinFileOpsTest(unittest.TestCase):
def setUp(self):
self.data = bytearray([(k % 128) for k in range(0, 1024)])
self.path = self._testMethodName + ".io"
- with self.vol.creat(self.path, os.O_WRONLY | os.O_EXCL, 0644) as fd:
+ with self.vol.open(self.path, os.O_CREAT | os.O_WRONLY | os.O_EXCL,
+ 0644) as fd:
fd.write(self.data)
def test_bin_open_and_read(self):
@@ -70,7 +72,8 @@ class FileOpsTest(unittest.TestCase):
def setUp(self):
self.data = loremipsum.get_sentence()
self.path = self._testMethodName + ".io"
- with self.vol.creat(self.path, os.O_WRONLY | os.O_EXCL, 0644) as fd:
+ with self.vol.open(self.path, os.O_CREAT | os.O_WRONLY | os.O_EXCL,
+ 0644) as fd:
rc = fd.write(self.data)
self.assertEqual(rc, len(self.data))
ret = fd.fsync()
@@ -87,6 +90,26 @@ class FileOpsTest(unittest.TestCase):
self.assertFalse(isinstance(buf, types.IntType))
self.assertEqual(buf.value, self.data)
+ def test_open_file_not_exist(self):
+ try:
+ f = self.vol.open("filenotexist", os.O_WRONLY)
+ except OSError as e:
+ self.assertEqual(e.errno, errno.ENOENT)
+ else:
+ f.close()
+ self.fail("Expected a OSError with errno.ENOENT")
+
+ def test_create_file_already_exists(self):
+ try:
+ f = self.vol.open("newfile", os.O_CREAT)
+ f.close()
+ g = self.vol.open("newfile", os.O_CREAT | os.O_EXCL)
+ except OSError as e:
+ self.assertEqual(e.errno, errno.EEXIST)
+ else:
+ g.close()
+ self.fail("Expected a OSError with errno.EEXIST")
+
def test_exists(self):
e = self.vol.exists(self.path)
self.assertTrue(e)
@@ -186,7 +209,8 @@ class DirOpsTest(unittest.TestCase):
self.vol.mkdir(self.dir_path, 0755)
for x in range(0, 3):
f = os.path.join(self.dir_path, self.testfile + str(x))
- with self.vol.creat(f, os.O_WRONLY | os.O_EXCL, 0644) as fd:
+ with self.vol.open(f, os.O_CREAT | os.O_WRONLY | os.O_EXCL,
+ 0644) as fd:
rc = fd.write(self.data)
self.assertEqual(rc, len(self.data))
ret = fd.fdatasync()
diff --git a/test/unit/gluster/test_gfapi.py b/test/unit/gluster/test_gfapi.py
index 8fcf938..ed7ed45 100644
--- a/test/unit/gluster/test_gfapi.py
+++ b/test/unit/gluster/test_gfapi.py
@@ -279,23 +279,12 @@ class TestVolume(unittest.TestCase):
mock_glfs_creat.return_value = 2
with patch("glusterfs.gfapi.api.glfs_creat", mock_glfs_creat):
- with self.vol.creat("file.txt", os.O_WRONLY, 0644) as fd:
+ with self.vol.open("file.txt", os.O_CREAT, 0644) as fd:
self.assertTrue(isinstance(fd, gfapi.File))
self.assertEqual(mock_glfs_creat.call_count, 1)
mock_glfs_creat.assert_called_once_with(2,
"file.txt",
- os.O_WRONLY, 0644)
-
- def test_creat_fail_exception(self):
- mock_glfs_creat = Mock()
- mock_glfs_creat.return_value = None
-
- def assert_creat():
- with self.vol.creat("file.txt", os.O_WRONLY, 0644) as fd:
- self.assertEqual(fd, None)
-
- with patch("glusterfs.gfapi.api.glfs_creat", mock_glfs_creat):
- self.assertRaises(OSError, assert_creat)
+ os.O_CREAT, 0644)
def test_exists_true(self):
mock_glfs_stat = Mock()
@@ -430,7 +419,8 @@ class TestVolume(unittest.TestCase):
mock_Dir_next = Mock()
mock_Dir_next.side_effect = [dirent1, dirent2, dirent3, None]
- with nested(patch("glusterfs.gfapi.api.glfs_opendir", mock_glfs_opendir),
+ with nested(patch("glusterfs.gfapi.api.glfs_opendir",
+ mock_glfs_opendir),
patch("glusterfs.gfapi.Dir.next", mock_Dir_next)):
d = self.vol.listdir("testdir")
self.assertEqual(len(d), 2)
@@ -545,7 +535,7 @@ class TestVolume(unittest.TestCase):
with patch("glusterfs.gfapi.api.glfs_mkdir", mock_glfs_mkdir):
self.assertRaises(OSError, self.vol.mkdir, "testdir", 0775)
- def test_open_success(self):
+ def test_open_with_statement_success(self):
mock_glfs_open = Mock()
mock_glfs_open.return_value = 2
@@ -556,7 +546,7 @@ class TestVolume(unittest.TestCase):
mock_glfs_open.assert_called_once_with(2,
"file.txt", os.O_WRONLY)
- def test_open_fail_exception(self):
+ def test_open_with_statement_fail_exception(self):
mock_glfs_open = Mock()
mock_glfs_open.return_value = None
@@ -567,6 +557,23 @@ class TestVolume(unittest.TestCase):
with patch("glusterfs.gfapi.api.glfs_open", mock_glfs_open):
self.assertRaises(OSError, assert_open)
+ def test_open_direct_success(self):
+ mock_glfs_open = Mock()
+ mock_glfs_open.return_value = 2
+
+ with patch("glusterfs.gfapi.api.glfs_open", mock_glfs_open):
+ fd = self.vol.open("file.txt", os.O_WRONLY)
+ self.assertTrue(isinstance(fd, gfapi.File))
+ self.assertEqual(mock_glfs_open.call_count, 1)
+ mock_glfs_open.assert_called_once_with(2, "file.txt", os.O_WRONLY)
+
+ def test_open_direct_fail_exception(self):
+ mock_glfs_open = Mock()
+ mock_glfs_open.return_value = None
+
+ with patch("glusterfs.gfapi.api.glfs_open", mock_glfs_open):
+ self.assertRaises(OSError, self.vol.open, "file.txt", os.O_RDONLY)
+
def test_opendir_success(self):
mock_glfs_opendir = Mock()
mock_glfs_opendir.return_value = 2
diff --git a/tox.ini b/tox.ini
index 2e71767..5a97c9b 100644
--- a/tox.ini
+++ b/tox.ini
@@ -14,7 +14,7 @@ deps =
--download-cache={homedir}/.pipcache
-r{toxinidir}/tools/test-requires
changedir = {toxinidir}/test/unit
-commands = nosetests -v --exe --with-xunit --with-coverage --cover-package gluster --cover-erase --cover-xml --cover-html --cover-branches --with-html-output {posargs}
+commands = nosetests -v --exe --with-xunit --with-coverage --cover-package glusterfs --cover-erase --cover-xml --cover-html --cover-branches --with-html-output {posargs}
[tox:jenkins]
downloadcache = ~/cache/pip