From 5e852ffddf92cca53eb79449460acc3ca5dc52f8 Mon Sep 17 00:00:00 2001 From: barneygale Date: Wed, 10 Sep 2025 20:18:39 +0100 Subject: [PATCH] Sync from upstream --- CHANGES.rst | 2 +- docs/api.rst | 2 +- pathlib_abc/_glob.py | 15 --------------- pathlib_abc/_os.py | 25 +++++++++++++++---------- tests/test_read.py | 6 ++++++ tests/test_write.py | 6 ++++++ 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index a1f3e1d..97d93bc 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,7 @@ Version History Unreleased ---------- -- Nothing yet +- Make ``vfsopen()`` try to call ``open()``, like it did before 0.5.0. v0.5.0 ------ diff --git a/docs/api.rst b/docs/api.rst index 6be34bf..b411a2d 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -20,7 +20,7 @@ This package offers the following functions: encoding=None, errors=None, newline=None) Open the given object and return a file object. Unlike the built-in - ``open()`` function, this function calls the object's + ``open()`` function, this function additionally calls the object's :meth:`~ReadablePath.__open_reader__`, :meth:`~WritablePath.__open_writer__` or :meth:`!__open_updater__` method, as appropriate for the given mode. diff --git a/pathlib_abc/_glob.py b/pathlib_abc/_glob.py index df536dc..7ae54d6 100644 --- a/pathlib_abc/_glob.py +++ b/pathlib_abc/_glob.py @@ -122,21 +122,6 @@ def _glob0(dirname, basename, dir_fd, dironly, include_hidden=False): return [basename] return [] -_deprecated_function_message = ( - "{name} is deprecated and will be removed in Python {remove}. Use " - "glob.glob and pass a directory to its root_dir argument instead." -) - -def glob0(dirname, pattern): - import warnings - warnings._deprecated("glob.glob0", _deprecated_function_message, remove=(3, 15)) - return _glob0(dirname, pattern, None, False) - -def glob1(dirname, pattern): - import warnings - warnings._deprecated("glob.glob1", _deprecated_function_message, remove=(3, 15)) - return _glob1(dirname, pattern, None, False) - # This helper function recursively yields relative pathnames inside a literal # directory. diff --git a/pathlib_abc/_os.py b/pathlib_abc/_os.py index eb637de..d8b54b7 100644 --- a/pathlib_abc/_os.py +++ b/pathlib_abc/_os.py @@ -210,8 +210,8 @@ def vfsopen(obj, mode='r', buffering=-1, encoding=None, errors=None, Open the file pointed to by this path and return a file object, as the built-in open() function does. - Unlike the built-in open() function, this function accepts 'openable' - objects, which are objects with any of these special methods: + Unlike the built-in open() function, this function additionally accepts + 'openable' objects, which are objects with any of these special methods: __open_reader__() __open_writer__(mode) @@ -221,19 +221,24 @@ def vfsopen(obj, mode='r', buffering=-1, encoding=None, errors=None, and 'x' modes; and '__open_updater__' for 'r+' and 'w+' modes. If text mode is requested, the result is wrapped in an io.TextIOWrapper object. """ - text = 'b' not in mode if buffering != -1: raise ValueError("buffer size can't be customized") - elif text: + text = 'b' not in mode + if text: # Call io.text_encoding() here to ensure any warning is raised at an # appropriate stack level. encoding = text_encoding(encoding) - elif encoding is not None: - raise ValueError("binary mode doesn't take an encoding argument") - elif errors is not None: - raise ValueError("binary mode doesn't take an errors argument") - elif newline is not None: - raise ValueError("binary mode doesn't take a newline argument") + try: + return open(obj, mode, buffering, encoding, errors, newline) + except TypeError: + pass + if not text: + if encoding is not None: + raise ValueError("binary mode doesn't take an encoding argument") + if errors is not None: + raise ValueError("binary mode doesn't take an errors argument") + if newline is not None: + raise ValueError("binary mode doesn't take a newline argument") mode = ''.join(sorted(c for c in mode if c not in 'bt')) if mode == 'r': stream = _open_reader(obj) diff --git a/tests/test_read.py b/tests/test_read.py index 41ca279..16fb555 100644 --- a/tests/test_read.py +++ b/tests/test_read.py @@ -36,6 +36,12 @@ def test_open_r(self): self.assertIsInstance(f, io.TextIOBase) self.assertEqual(f.read(), 'this is file A\n') + def test_open_r_buffering_error(self): + p = self.root / 'fileA' + self.assertRaises(ValueError, vfsopen, p, 'r', buffering=0) + self.assertRaises(ValueError, vfsopen, p, 'r', buffering=1) + self.assertRaises(ValueError, vfsopen, p, 'r', buffering=1024) + @unittest.skipIf( not getattr(sys.flags, 'warn_default_encoding', 0), "Requires warn_default_encoding", diff --git a/tests/test_write.py b/tests/test_write.py index 2a25501..c9c1d64 100644 --- a/tests/test_write.py +++ b/tests/test_write.py @@ -36,6 +36,12 @@ def test_open_w(self): f.write('this is file A\n') self.assertEqual(self.ground.readtext(p), 'this is file A\n') + def test_open_w_buffering_error(self): + p = self.root / 'fileA' + self.assertRaises(ValueError, vfsopen, p, 'w', buffering=0) + self.assertRaises(ValueError, vfsopen, p, 'w', buffering=1) + self.assertRaises(ValueError, vfsopen, p, 'w', buffering=1024) + @unittest.skipIf( not getattr(sys.flags, 'warn_default_encoding', 0), "Requires warn_default_encoding",