Repository: jmcgeheeiv/pyfakefs
Pull request #663 (2022-01-30 12:44:52)

Correctly handle full disk after append
- do not update flush position before disk size is checked
- see #660


Patch:
diff --git a/CHANGES.md b/CHANGES.md
index 9cbfb8d..ed1d9c8 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -57,6 +57,8 @@ This is a bugfix release.
 * handle `pathlib.Path.owner()` and `pathlib.Path.group` by returning 
   the current user/group name (see [#629](../../issues/629))
 * fixed handling of `use_known_patches=False` (could cause an exception)  
+* removed Python 3.5 from metadata to disable installation for that version
+  (see [#615](../../issues/615))
 
 ### Infrastructure
 * added test dependency check (see [#608](../../issues/608))
@@ -66,6 +68,9 @@ This is a bugfix release.
 ## [Version 4.5.0](https://pypi.python.org/pypi/pyfakefs/4.5.0) (2021-06-04)
 Adds some support for Python 3.10 and basic type checking.
 
+_Note_: This version has been yanked from PyPi as it erroneously allowed
+installation under Python 3.5.
+
 ### New Features
   * added support for some Python 3.10 features:
     * new method `pathlib.Path.hardlink_to` 
@@ -232,8 +237,8 @@ This is a bugfix release that fixes a regression issue.
 ## [Version 4.0.2](https://pypi.python.org/pypi/pyfakefs/4.0.2) (2020-03-04)
 
 This as a patch release that only builds for Python 3. Note that 
-versions 4.0.0 and 4.0.1 will be removed from PyPi to not to be able to
-install them under Python 2. 
+versions 4.0.0 and 4.0.1 will be removed from PyPi to disable
+installing them under Python 2. 
 
 #### Fixes
   * Do not build for Python 2 (see [#524](../../issues/524))
@@ -242,14 +247,19 @@ install them under Python 2.
 
 This as a bug fix release for a regression bug.
 
+_Note_: This version has been yanked from PyPi as it erroneously allowed
+installation under Python 2. This has been fixed in version 4.0.2.
+
 #### Fixes
   * Avoid exception if using `flask-restx` (see [#523](../../issues/523))
 
 ## [Version 4.0.0](https://pypi.python.org/pypi/pyfakefs/4.0.0) (2020-03-03)
+pyfakefs 4.0.0 drops support for Python 2.7. If you still need
+Python 2.7, you can continue to use pyfakefs 3.7.x.
+
+_Note_: This version has been yanked from PyPi as it erroneously allowed
+installation under Python 2. This has been fixed in version 4.0.2.
 
-  * pyfakefs 4.0.0 drops support for Python 2.7. If you still need
-    Python 2.7, you can continue to use pyfakefs 3.7.x. 
-    
 #### Changes
   * Removed Python 2.7 and 3.4 support (see [#492](../../issues/492))
   
diff --git a/pyfakefs/fake_filesystem.py b/pyfakefs/fake_filesystem.py
index 758e46f..2e2d129 100644
--- a/pyfakefs/fake_filesystem.py
+++ b/pyfakefs/fake_filesystem.py
@@ -455,6 +455,9 @@ class FakeFile:
                     if they are a unicode string.
                     If not given, the locale preferred encoding is used.
 
+        Returns:
+            True if the contents have been changed.
+
         Raises:
           OSError: if `st_size` is not a non-negative integer,
                    or if it exceeds the available file system space.
@@ -5049,8 +5052,9 @@ class FakeFileWrapper:
                 self._set_stream_contents(contents)
             else:
                 self._io.flush()
+            changed = self.file_object.set_contents(contents, self._encoding)
             self.update_flush_pos()
-            if self.file_object.set_contents(contents, self._encoding):
+            if changed:
                 if self._filesystem.is_windows_fs:
                     self._changed = True
                 else:


Test patch:
diff --git a/pyfakefs/tests/fake_filesystem_test.py b/pyfakefs/tests/fake_filesystem_test.py
index 95953f1..b95db8f 100644
--- a/pyfakefs/tests/fake_filesystem_test.py
+++ b/pyfakefs/tests/fake_filesystem_test.py
@@ -1790,7 +1790,7 @@ class DiskSpaceTest(TestCase):
         self.filesystem.create_file('d:!foo!bar!baz', st_size=100)
         self.filesystem.create_file('d:!foo!baz', st_size=100)
         self.filesystem.set_disk_usage(total_size=1000, path='d:')
-        self.assertEqual(self.filesystem.get_disk_usage('d:!foo').free, 800)
+        self.assertEqual(800, self.filesystem.get_disk_usage('d:!foo').free)
 
     def test_copying_preserves_byte_contents(self):
         source_file = self.filesystem.create_file('foo', contents=b'somebytes')
@@ -1802,16 +1802,30 @@ class DiskSpaceTest(TestCase):
         with self.open('bar.txt', 'w') as f:
             f.write('a' * 60)
             f.flush()
-        self.assertEqual(self.filesystem.get_disk_usage()[1], 60)
+        self.assertEqual(60, self.filesystem.get_disk_usage()[1])
 
     def test_disk_full_after_reopened(self):
         with self.open('bar.txt', 'w') as f:
             f.write('a' * 60)
         with self.open('bar.txt') as f:
-            self.assertEqual(f.read(), 'a' * 60)
+            self.assertEqual('a' * 60, f.read())
         with self.raises_os_error(errno.ENOSPC):
             with self.open('bar.txt', 'w') as f:
                 f.write('b' * 110)
+                with self.raises_os_error(errno.ENOSPC):
+                    f.flush()
+
+    def test_disk_full_append(self):
+        file_path = 'bar.txt'
+        with self.open(file_path, 'w') as f:
+            f.write('a' * 60)
+        with self.open(file_path) as f:
+            self.assertEqual('a' * 60, f.read())
+        with self.raises_os_error(errno.ENOSPC):
+            with self.open(file_path, 'a') as f:
+                f.write('b' * 41)
+                with self.raises_os_error(errno.ENOSPC):
+                    f.flush()
 
     def test_disk_full_after_reopened_rplus_seek(self):
         with self.open('bar.txt', 'w') as f:
@@ -1822,6 +1836,8 @@ class DiskSpaceTest(TestCase):
             with self.open('bar.txt', 'r+') as f:
                 f.seek(50)
                 f.write('b' * 60)
+                with self.raises_os_error(errno.ENOSPC):
+                    f.flush()
 
 
 class MountPointTest(TestCase):