diff options
| author | Thiago da Silva <thiago@redhat.com> | 2014-03-19 11:09:10 -0400 | 
|---|---|---|
| committer | Thiago da Silva <thiago@redhat.com> | 2014-03-21 11:47:43 -0400 | 
| commit | df17e0bc245ce3c7e58f384a3a2f6e02b999d50b (patch) | |
| tree | cc87a1b80f85ed3b7e2226cec37731cb54976ce8 | |
| parent | c268302dd4dcd22a503e21f30d5bbfb2df3013f6 (diff) | |
merging creat and open function to be more pythonic
the os python module does not offer a creat function,
new files are created using the open function and
by passing O_CREAT flag. We are changing gfapi.py to
function the same way.
Change-Id: I5e084b200bb657e3124d3e620a47160e790cd1fe
Signed-off-by: Thiago da Silva <thiago@redhat.com>
| -rw-r--r-- | glusterfs/gfapi.py | 42 | ||||
| -rw-r--r-- | test/functional/libgfapi-python-tests.py | 30 | ||||
| -rw-r--r-- | test/unit/gluster/test_gfapi.py | 39 | ||||
| -rw-r--r-- | tox.ini | 2 | 
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 @@ -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  | 
