Clarify GitFile docstrings and disallow r+w modes.
authorDave Borowitz <dborowitz@google.com>
Thu, 21 Jan 2010 23:00:30 +0000 (15:00 -0800)
committerDave Borowitz <dborowitz@google.com>
Tue, 9 Feb 2010 17:45:03 +0000 (09:45 -0800)
Change-Id: I9a23ede0d7a3c93b0eb6c55aebf487a34d7cf875

dulwich/file.py
dulwich/tests/test_file.py

index 20accf0e4ffc087bf00cf6daaa0643b1cfa8934f..ec67ad9cb8580ff09d51e69d9dbba86e082e8c21 100644 (file)
@@ -25,8 +25,38 @@ import os
 
 
 def GitFile(filename, mode='r', bufsize=-1):
+    """Create a file object that obeys the git file locking protocol.
+
+    See _GitFile for a description of the file locking protocol.
+
+    Only read-only and write-only (binary) modes are supported; r+, w+, and a
+    are not.  To read and write from the same file, you can take advantage of
+    the fact that opening a file for write does not actually open the file you
+    request:
+
+    >>> write_file = GitFile('filename', 'wb')
+    >>> read_file = GitFile('filename', 'rb')
+    >>> read_file.readlines()
+    ['contents\n', 'of\n', 'the\n', 'file\n']
+    >>> write_file.write('foo')
+    >>> read_file.close()
+    >>> write_file.close()
+    >>> new_file = GitFile('filename', 'rb')
+    'foo'
+    >>> new_file.close()
+    >>> other_file = GitFile('filename', 'wb')
+    Traceback (most recent call last):
+        ...
+    OSError: [Errno 17] File exists: 'filename.lock'
+
+    :return: a builtin file object or a _GitFile object
+    """
     if 'a' in mode:
         raise IOError('append mode not supported for Git files')
+    if '+' in mode:
+        raise IOError('read/write mode not supported for Git files')
+    if 'b' not in mode:
+        raise IOError('text mode not supported for Git files')
     if 'w' in mode:
         return _GitFile(filename, mode, bufsize)
     else:
index 9773fd42a4d92ceb6b939e53b2372033cb468f9f..ad1e0fbc6b808feaa05971a626baf9bc6a845e0b 100644 (file)
@@ -38,6 +38,14 @@ class GitFileTests(unittest.TestCase):
     def path(self, filename):
         return os.path.join(self._tempdir, filename)
 
+    def test_invalid(self):
+        foo = self.path('foo')
+        self.assertRaises(IOError, GitFile, foo, mode='r')
+        self.assertRaises(IOError, GitFile, foo, mode='ab')
+        self.assertRaises(IOError, GitFile, foo, mode='r+b')
+        self.assertRaises(IOError, GitFile, foo, mode='w+b')
+        self.assertRaises(IOError, GitFile, foo, mode='a+bU')
+
     def test_readonly(self):
         f = GitFile(self.path('foo'), 'rb')
         self.assertTrue(isinstance(f, file))