summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYves Weissig <yves@weissig.me>2023-08-18 17:52:57 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-09-11 06:07:47 +0200
commit369b498219be791ebec8233208f08f07621b8359 (patch)
tree01bfdce78ebd133857950290e979694bd64b57d3
parentecb6085f6fdb6319656b54cc92e6a91c1df47f23 (diff)
Fixed #34642 -- Added File.open() support for *args and **kwargs.
-rw-r--r--AUTHORS1
-rw-r--r--django/core/files/base.py4
-rw-r--r--docs/ref/files/file.txt9
-rw-r--r--docs/releases/5.0.txt3
-rw-r--r--tests/files/tests.py15
5 files changed, 27 insertions, 5 deletions
diff --git a/AUTHORS b/AUTHORS
index 6593f0889f..1f51cff05c 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1053,6 +1053,7 @@ answer newbie questions, and generally made Django that much better:
Yoong Kang Lim <yoongkang.lim@gmail.com>
Yury V. Zaytsev <yury@shurup.com>
Yusuke Miyazaki <miyazaki.dev@gmail.com>
+ Yves Weissig <yves@weissig.me>
yyyyyyyan <contact@yyyyyyyan.tech>
Zac Hatfield-Dodds <zac.hatfield.dodds@gmail.com>
Zachary Voase <zacharyvoase@gmail.com>
diff --git a/django/core/files/base.py b/django/core/files/base.py
index 3ca43ec254..9682467afa 100644
--- a/django/core/files/base.py
+++ b/django/core/files/base.py
@@ -105,11 +105,11 @@ class File(FileProxyMixin):
def __exit__(self, exc_type, exc_value, tb):
self.close()
- def open(self, mode=None):
+ def open(self, mode=None, *args, **kwargs):
if not self.closed:
self.seek(0)
elif self.name and os.path.exists(self.name):
- self.file = open(self.name, mode or self.mode)
+ self.file = open(self.name, mode or self.mode, *args, **kwargs)
else:
raise ValueError("The file cannot be reopened.")
return self
diff --git a/docs/ref/files/file.txt b/docs/ref/files/file.txt
index 650bbb7079..ea9bf0968e 100644
--- a/docs/ref/files/file.txt
+++ b/docs/ref/files/file.txt
@@ -46,11 +46,12 @@ The ``File`` class
The read/write mode for the file.
- .. method:: open(mode=None)
+ .. method:: open(mode=None, *args, **kwargs)
Open or reopen the file (which also does ``File.seek(0)``).
The ``mode`` argument allows the same values
- as Python's built-in :func:`python:open()`.
+ as Python's built-in :func:`python:open()`. ``*args`` and ``**kwargs``
+ are passed after ``mode`` to Python's built-in :func:`python:open`.
When reopening a file, ``mode`` will override whatever mode the file
was originally opened with; ``None`` means to reopen with the original
@@ -58,6 +59,10 @@ The ``File`` class
It can be used as a context manager, e.g. ``with file.open() as f:``.
+ .. versionchanged:: 5.0
+
+ Support for passing ``*args`` and ``**kwargs`` was added.
+
.. method:: __iter__()
Iterate over the file yielding one line at a time.
diff --git a/docs/releases/5.0.txt b/docs/releases/5.0.txt
index b9a871c8e9..2e23e40cbf 100644
--- a/docs/releases/5.0.txt
+++ b/docs/releases/5.0.txt
@@ -352,7 +352,8 @@ Error Reporting
File Storage
~~~~~~~~~~~~
-* ...
+* :meth:`.File.open` now passes all positional (``*args``) and keyword
+ arguments (``**kwargs``) to Python's built-in :func:`python:open`.
File Uploads
~~~~~~~~~~~~
diff --git a/tests/files/tests.py b/tests/files/tests.py
index b3478d2732..7dc5c04668 100644
--- a/tests/files/tests.py
+++ b/tests/files/tests.py
@@ -200,6 +200,21 @@ class FileTests(unittest.TestCase):
self.assertIs(locks.unlock(f1), True)
self.assertIs(locks.unlock(f2), True)
+ def test_open_supports_full_signature(self):
+ called = False
+
+ def opener(path, flags):
+ nonlocal called
+ called = True
+ return os.open(path, flags)
+
+ file_path = Path(__file__).parent / "test.png"
+ with open(file_path) as f:
+ test_file = File(f)
+
+ with test_file.open(opener=opener):
+ self.assertIs(called, True)
+
class NoNameFileTestCase(unittest.TestCase):
"""