8000 gh-115961: Add name and mode attributes for compressed file-like obje… · python/cpython@51ef89c · GitHub
[go: up one dir, main page]

Skip to content

Commit 51ef89c

Browse files
gh-115961: Add name and mode attributes for compressed file-like objects (GH-116036)
* Add name and mode attributes for compressed and archived file-like objects in modules bz2, lzma, tarfile and zipfile. * Change the value of the mode attribute of GzipFile from integer (1 or 2) to string ('rb' or 'wb'). * Change the value of the mode attribute of ZipExtFile from 'r' to 'rb'.
1 parent ccda738 commit 51ef89c

17 files changed

+246
-37
lines changed

Doc/library/bz2.rst

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ The :mod:`bz2` module contains:
9191
and :meth:`~io.IOBase.truncate`.
9292
Iteration and the :keyword:`with` statement are supported.
9393

94-
:class:`BZ2File` also provides the following methods:
94+
:class:`BZ2File` also provides the following methods and attributes:
9595

9696
.. method:: peek([n])
9797

@@ -148,6 +148,19 @@ The :mod:`bz2` module contains:
148148

149149
.. versionadded:: 3.3
150150

151+
.. attribute:: mode
152+
153+
``'rb'`` for reading and ``'wb'`` for writing.
154+
155+
.. versionadded:: 3.13
156+
157+
.. attribute:: name
158+
159+
The bzip2 file name. Equivalent to the :attr:`~io.FileIO.name`
160+
attribute of the underlying :term:`file object`.
161+
162+
.. versionadded:: 3.13
163+
151164

152165
.. versionchanged:: 3.1
153166
Support for the :keyword:`with` statement was added.

Doc/library/gzip.rst

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,13 @@ The module defines the following items:
133133

134134
.. versionadded:: 3.2
135135

136+
.. attribute:: mode
137+
138+
``'rb'`` for reading and ``'wb'`` for writing.
139+
140+
.. versionchanged:: 3.13
141+
In previous versions it was an integer ``1`` or ``2``.
142+
136143
.. attribute:: mtime
137144

138145
When decompressing, this attribute is set to the last timestamp in the most
@@ -168,14 +175,14 @@ The module defines the following items:
168175
.. versionchanged:: 3.6
169176
Accepts a :term:`path-like object`.
170177

171-
.. versionchanged:: 3.12
172-
Remove the ``filename`` attribute, use the :attr:`~GzipFile.name`
173-
attribute instead.
174-
175178
.. deprecated:: 3.9
176179
Opening :class:`GzipFile` for writing without specifying the *mode*
177180
argument is deprecated.
178181

182+
.. versionchanged:: 3.12
183+
Remove the ``filename`` attribute, use the :attr:`~GzipFile.name`
184+
attribute instead.
185+
179186

180187
.. function:: compress(data, compresslevel=9, *, mtime=None)
181188

Doc/library/lzma.rst

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ Reading and writing compressed files
104104
and :meth:`~io.IOBase.truncate`.
105105
Iteration and the :keyword:`with` statement are supported.
106106

107-
The following method is also provided:
107+
The following method and attributes are also provided:
108108

109109
.. method:: peek(size=-1)
110110

@@ -117,6 +117,20 @@ Reading and writing compressed files
117117
file object (e.g. if the :class:`LZMAFile` was constructed by passing a
118118
file object for *filename*).
119119

120+
.. attribute:: mode
121+
122+
``'rb'`` for reading and ``'wb'`` for writing.
123+
124+
.. versionadded:: 3.13
125+
126+
.. attribute:: name
127+
128+
The lzma file name. Equivalent to the :attr:`~io.FileIO.name`
129+
attribute of the underlying :term:`file object`.
130+
131+
.. versionadded:: 3.13
132+
133+
120134
.. versionchanged:: 3.4
121135
Added support for the ``"x"`` and ``"xb"`` modes.
122136

Doc/library/tarfile.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,10 @@ be finalized; only the internally used file object will be closed. See the
565565
.. versionchanged:: 3.3
566566
Return an :class:`io.BufferedReader` object.
567567

568+
.. versionchanged:: 3.13
569+
The returned :class:`io.BufferedReader` object has the :attr:`!mode`
570+
attribute which is always equal to ``'rb'``.
571+
568572
.. attribute:: TarFile.errorlevel
569573
:type: int
570574

Doc/library/zipfile.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,10 @@ ZipFile Objects
301301
attempting to read or write other files in the ZIP file will raise a
302302
:exc:`ValueError`.
303303

304+
In both cases the file-like object has also attributes :attr:`!name`,
305+
which is equivalent to the name of a file within the archive, and
306+
:attr:`!mode`, which is ``'rb'`` or ``'wb'`` depending on the input mode.
307+
304308
When writing a file, if the file size is not known in advance but may exceed
305309
2 GiB, pass ``force_zip64=True`` to ensure that the header format is
306310
capable of supporting large files. If the file size is known in advance,
@@ -325,6 +329,12 @@ ZipFile Objects
325329
Calling :meth:`.open` on a closed ZipFile will raise a :exc:`ValueError`.
326330
Previously, a :exc:`RuntimeError` was raised.
327331

332+
.. versionchanged:: 3.13
333+
Added attributes :attr:`!name` and :attr:`!mode` for the writeable
334+
file-like object.
335+
The value of the :attr:`!mode` attribute for the readable file-like
336+
object was changed from ``'r'`` to ``'rb'``.
337+
328338

329339
.. method:: ZipFile.extract(member, path=None, pwd=None)
330340

Doc/whatsnew/3.13.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ Other Language Changes
206206

207207
(Contributed by Victor Stinner in :gh:`114570`.)
208208

209+
* Added :attr:`!name` and :attr:`!mode` attributes for compressed
210+
and archived file-like objects in modules :mod:`bz2`, :mod:`lzma`,
211+
:mod:`tarfile` and :mod:`zipfile`.
212+
(Contributed by Serhiy Storchaka in :gh:`115961`.)
213+
209214
* Allow controlling Expat >=2.6.0 reparse deferral (:cve:`2023-52425`)
210215
by adding five new methods:
211216

@@ -1605,6 +1610,12 @@ Changes in the Python API
16051610
than directories only. Users may add a trailing slash to match only
16061611
directories.
16071612

1613+
* The value of the :attr:`!mode` attribute of :class:`gzip.GzipFile` was
1614+
changed from integer (``1`` or ``2``) to string (``'rb'`` or ``'wb'``).
1615+
The value of the :attr:`!mode` attribute of the readable file-like object
1616+
returned by :meth:`zipfile.ZipFile.open` was changed from ``'r'`` to ``'rb'``.
1617+
(Contributed by Serhiy Storchaka in :gh:`115961`.)
1618+
16081619
* :c:func:`!PyCode_GetFirstFree` is an unstable API now and has been renamed
16091620
to :c:func:`PyUnstable_Code_GetFirstFree`.
16101621
(Contributed by Bogdan Romanyuk in :gh:`115781`.)

Lib/bz2.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from _bz2 import BZ2Compressor, BZ2Decompressor
1818

1919

20-
_MODE_CLOSED = 0
20+
# Value 0 no longer used
2121
_MODE_READ = 1
2222
# Value 2 no longer used
2323
_MODE_WRITE = 3
@@ -54,7 +54,7 @@ def __init__(self, filename, mode="r", *, compresslevel=9):
5454
"""
5555
self._fp = None
5656
self._closefp = False
57-
self._mode = _MODE_CLOSED
57+
self._mode = None
5858

5959
if not (1 <= compresslevel <= 9):
6060
raise ValueError("compresslevel must be between 1 and 9")
@@ -100,7 +100,7 @@ def close(self):
100100
May be called more than once without error. Once the file is
101101
closed, any other operation on it will raise a ValueError.
102102
"""
103-
if self._mode == _MODE_CLOSED:
103+
if self.closed:
104104
return
105105
try:
106106
if self._mode == _MODE_READ:
@@ -115,13 +115,21 @@ def close(self):
115115
finally:
116116
self._fp = None
117117
self._closefp = False
118-
self._mode = _MODE_CLOSED
119118
self._buffer = None
120119

121120
@property
122121
def closed(self):
123122
"""True if this file is closed."""
124-
return self._mode == _MODE_CLOSED
123+
return self._fp is None
124+
125+
@property
126+
def name(self):
127+
self._check_not_closed()
128+
return self._fp.name
129+
130+
@property
131+
def mode(self):
132+
return 'wb' if self._mode == _MODE_WRITE else 'rb'
125133

126134
def fileno(self):
127135
"""Return the file descriptor for the underlying file."""

Lib/gzip.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515

1616
FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16
1717

18-
READ, WRITE = 1, 2
18+
READ = 'rb'
19+
WRITE = 'wb'
1920

2021
_COMPRESS_LEVEL_FAST = 1
2122
_COMPRESS_LEVEL_TRADEOFF = 6

Lib/lzma.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import _compression
3030

3131

32-
_MODE_CLOSED = 0
32+
# Value 0 no longer used
3333
_MODE_READ = 1
3434
# Value 2 no longer used
3535
_MODE_WRITE = 3
@@ -92,7 +92,7 @@ def __init__(self, filename=None, mode="r", *,
9292
"""
9393
self._fp = None
9494
self._closefp = False
95-
self._mode = _MODE_CLOSED
95+
self._mode = None
9696

9797
if mode in ("r", "rb"):
9898
if check != -1:
@@ -137,7 +137,7 @@ def close(self):
137137
May be called more than once without error. Once the file is
138138
closed, any other operation on it will raise a ValueError.
139139
"""
140-
if self._mode == _MODE_CLOSED:
140+
if self.closed:
141141
return
142142
try:
143143
if self._mode == _MODE_READ:
@@ -153,12 +153,20 @@ def close(self):
153153
finally:
154154
self._fp = None
155155
self._closefp = False
156-
self._mode = _MODE_CLOSED
157156

158157
@property
159158
def closed(self):
160159
"""True if this file is closed."""
161-
return self._mode == _MODE_CLOSED
160+
return self._fp is None
161+
162+
@property
163+
def name(self):
164+
self._check_not_closed()
165+
return self._fp.name
166+
167+
@property
168+
def mode(self):
169+
return 'wb' if self._mode == _MODE_WRITE else 'rb'
162170

163171
def fileno(self):
164172
"""Return the file descriptor for the underlying file."""

Lib/tarfile.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,10 @@ def __init__(self, fileobj, offset, size, name, blockinfo=None):
636636
def flush(self):
637637
pass
638638

639+
@property
640+
def mode(self):
641+
return 'rb'
642+
639643
def readable(self):
640644
return True
641645

0 commit comments

Comments
 (0)
0