mirror of https://github.com/python/cpython
Issue #19223: Add support for the 'x' mode to the bz2 module.
Patch by Tim Heaney and Vajrasky Kok.
This commit is contained in:
parent
42ca98217c
commit
8a9e99cffc
|
@ -37,8 +37,8 @@ All of the classes in this module may safely be accessed from multiple threads.
|
||||||
file object to read from or write to.
|
file object to read from or write to.
|
||||||
|
|
||||||
The *mode* argument can be any of ``'r'``, ``'rb'``, ``'w'``, ``'wb'``,
|
The *mode* argument can be any of ``'r'``, ``'rb'``, ``'w'``, ``'wb'``,
|
||||||
``'a'``, or ``'ab'`` for binary mode, or ``'rt'``, ``'wt'``, or ``'at'`` for
|
``'x'``, ``'xb'``, ``'a'`` or ``'ab'`` for binary mode, or ``'rt'``,
|
||||||
text mode. The default is ``'rb'``.
|
``'wt'``, ``'xt'``, or ``'at'`` for text mode. The default is ``'rb'``.
|
||||||
|
|
||||||
The *compresslevel* argument is an integer from 1 to 9, as for the
|
The *compresslevel* argument is an integer from 1 to 9, as for the
|
||||||
:class:`BZ2File` constructor.
|
:class:`BZ2File` constructor.
|
||||||
|
@ -54,6 +54,9 @@ All of the classes in this module may safely be accessed from multiple threads.
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
.. versionchanged:: 3.4
|
||||||
|
The ``'x'`` (exclusive creation) mode was added.
|
||||||
|
|
||||||
|
|
||||||
.. class:: BZ2File(filename, mode='r', buffering=None, compresslevel=9)
|
.. class:: BZ2File(filename, mode='r', buffering=None, compresslevel=9)
|
||||||
|
|
||||||
|
@ -64,8 +67,9 @@ All of the classes in this module may safely be accessed from multiple threads.
|
||||||
be used to read or write the compressed data.
|
be used to read or write the compressed data.
|
||||||
|
|
||||||
The *mode* argument can be either ``'r'`` for reading (default), ``'w'`` for
|
The *mode* argument can be either ``'r'`` for reading (default), ``'w'`` for
|
||||||
overwriting, or ``'a'`` for appending. These can equivalently be given as
|
overwriting, ``'x'`` for exclusive creation, or ``'a'`` for appending. These
|
||||||
``'rb'``, ``'wb'``, and ``'ab'`` respectively.
|
can equivalently be given as ``'rb'``, ``'wb'``, ``'xb'`` and ``'ab'``
|
||||||
|
respectively.
|
||||||
|
|
||||||
If *filename* is a file object (rather than an actual file name), a mode of
|
If *filename* is a file object (rather than an actual file name), a mode of
|
||||||
``'w'`` does not truncate the file, and is instead equivalent to ``'a'``.
|
``'w'`` does not truncate the file, and is instead equivalent to ``'a'``.
|
||||||
|
@ -108,6 +112,9 @@ All of the classes in this module may safely be accessed from multiple threads.
|
||||||
The ``'a'`` (append) mode was added, along with support for reading
|
The ``'a'`` (append) mode was added, along with support for reading
|
||||||
multi-stream files.
|
multi-stream files.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.4
|
||||||
|
The ``'x'`` (exclusive creation) mode was added.
|
||||||
|
|
||||||
|
|
||||||
Incremental (de)compression
|
Incremental (de)compression
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
16
Lib/bz2.py
16
Lib/bz2.py
|
@ -49,12 +49,12 @@ class BZ2File(io.BufferedIOBase):
|
||||||
which will be used to read or write the compressed data.
|
which will be used to read or write the compressed data.
|
||||||
|
|
||||||
mode can be 'r' for reading (default), 'w' for (over)writing,
|
mode can be 'r' for reading (default), 'w' for (over)writing,
|
||||||
or 'a' for appending. These can equivalently be given as 'rb',
|
'x' for creating exclusively, or 'a' for appending. These can
|
||||||
'wb', and 'ab'.
|
equivalently be given as 'rb', 'wb', 'xb', and 'ab'.
|
||||||
|
|
||||||
buffering is ignored. Its use is deprecated.
|
buffering is ignored. Its use is deprecated.
|
||||||
|
|
||||||
If mode is 'w' or 'a', compresslevel can be a number between 1
|
If mode is 'w', 'x' or 'a', compresslevel can be a number between 1
|
||||||
and 9 specifying the level of compression: 1 produces the least
|
and 9 specifying the level of compression: 1 produces the least
|
||||||
compression, and 9 (default) produces the most compression.
|
compression, and 9 (default) produces the most compression.
|
||||||
|
|
||||||
|
@ -87,6 +87,10 @@ class BZ2File(io.BufferedIOBase):
|
||||||
mode = "wb"
|
mode = "wb"
|
||||||
mode_code = _MODE_WRITE
|
mode_code = _MODE_WRITE
|
||||||
self._compressor = BZ2Compressor(compresslevel)
|
self._compressor = BZ2Compressor(compresslevel)
|
||||||
|
elif mode in ("x", "xb"):
|
||||||
|
mode = "xb"
|
||||||
|
mode_code = _MODE_WRITE
|
||||||
|
self._compressor = BZ2Compressor(compresslevel)
|
||||||
elif mode in ("a", "ab"):
|
elif mode in ("a", "ab"):
|
||||||
mode = "ab"
|
mode = "ab"
|
||||||
mode_code = _MODE_WRITE
|
mode_code = _MODE_WRITE
|
||||||
|
@ -443,9 +447,9 @@ def open(filename, mode="rb", compresslevel=9,
|
||||||
The filename argument can be an actual filename (a str or bytes
|
The filename argument can be an actual filename (a str or bytes
|
||||||
object), or an existing file object to read from or write to.
|
object), or an existing file object to read from or write to.
|
||||||
|
|
||||||
The mode argument can be "r", "rb", "w", "wb", "a" or "ab" for
|
The mode argument can be "r", "rb", "w", "wb", "x", "xb", "a" or
|
||||||
binary mode, or "rt", "wt" or "at" for text mode. The default mode
|
"ab" for binary mode, or "rt", "wt", "xt" or "at" for text mode.
|
||||||
is "rb", and the default compresslevel is 9.
|
The default mode is "rb", and the default compresslevel is 9.
|
||||||
|
|
||||||
For binary mode, this function is equivalent to the BZ2File
|
For binary mode, this function is equivalent to the BZ2File
|
||||||
constructor: BZ2File(filename, mode, compresslevel). In this case,
|
constructor: BZ2File(filename, mode, compresslevel). In this case,
|
||||||
|
|
|
@ -8,6 +8,7 @@ import os
|
||||||
import random
|
import random
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
from test.support import unlink
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import threading
|
import threading
|
||||||
|
@ -715,7 +716,10 @@ class OpenTest(BaseTest):
|
||||||
return bz2.open(*args, **kwargs)
|
return bz2.open(*args, **kwargs)
|
||||||
|
|
||||||
def test_binary_modes(self):
|
def test_binary_modes(self):
|
||||||
with self.open(self.filename, "wb") as f:
|
for mode in ("wb", "xb"):
|
||||||
|
if mode == "xb":
|
||||||
|
unlink(self.filename)
|
||||||
|
with self.open(self.filename, mode) as f:
|
||||||
f.write(self.TEXT)
|
f.write(self.TEXT)
|
||||||
with open(self.filename, "rb") as f:
|
with open(self.filename, "rb") as f:
|
||||||
file_data = self.decompress(f.read())
|
file_data = self.decompress(f.read())
|
||||||
|
@ -730,7 +734,10 @@ class OpenTest(BaseTest):
|
||||||
|
|
||||||
def test_implicit_binary_modes(self):
|
def test_implicit_binary_modes(self):
|
||||||
# Test implicit binary modes (no "b" or "t" in mode string).
|
# Test implicit binary modes (no "b" or "t" in mode string).
|
||||||
with self.open(self.filename, "w") as f:
|
for mode in ("w", "x"):
|
||||||
|
if mode == "x":
|
||||||
|
unlink(self.filename)
|
||||||
|
with self.open(self.filename, mode) as f:
|
||||||
f.write(self.TEXT)
|
f.write(self.TEXT)
|
||||||
with open(self.filename, "rb") as f:
|
with open(self.filename, "rb") as f:
|
||||||
file_data = self.decompress(f.read())
|
file_data = self.decompress(f.read())
|
||||||
|
@ -746,7 +753,10 @@ class OpenTest(BaseTest):
|
||||||
def test_text_modes(self):
|
def test_text_modes(self):
|
||||||
text = self.TEXT.decode("ascii")
|
text = self.TEXT.decode("ascii")
|
||||||
text_native_eol = text.replace("\n", os.linesep)
|
text_native_eol = text.replace("\n", os.linesep)
|
||||||
with self.open(self.filename, "wt") as f:
|
for mode in ("wt", "xt"):
|
||||||
|
if mode == "xt":
|
||||||
|
unlink(self.filename)
|
||||||
|
with self.open(self.filename, mode) as f:
|
||||||
f.write(text)
|
f.write(text)
|
||||||
with open(self.filename, "rb") as f:
|
with open(self.filename, "rb") as f:
|
||||||
file_data = self.decompress(f.read()).decode("ascii")
|
file_data = self.decompress(f.read()).decode("ascii")
|
||||||
|
@ -759,6 +769,15 @@ class OpenTest(BaseTest):
|
||||||
file_data = self.decompress(f.read()).decode("ascii")
|
file_data = self.decompress(f.read()).decode("ascii")
|
||||||
self.assertEqual(file_data, text_native_eol * 2)
|
self.assertEqual(file_data, text_native_eol * 2)
|
||||||
|
|
||||||
|
def test_x_mode(self):
|
||||||
|
for mode in ("x", "xb", "xt"):
|
||||||
|
unlink(self.filename)
|
||||||
|
with self.open(self.filename, mode) as f:
|
||||||
|
pass
|
||||||
|
with self.assertRaises(FileExistsError):
|
||||||
|
with self.open(self.filename, mode) as f:
|
||||||
|
pass
|
||||||
|
|
||||||
def test_fileobj(self):
|
def test_fileobj(self):
|
||||||
with self.open(BytesIO(self.DATA), "r") as f:
|
with self.open(BytesIO(self.DATA), "r") as f:
|
||||||
self.assertEqual(f.read(), self.TEXT)
|
self.assertEqual(f.read(), self.TEXT)
|
||||||
|
@ -772,6 +791,8 @@ class OpenTest(BaseTest):
|
||||||
# Test invalid parameter combinations.
|
# Test invalid parameter combinations.
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError,
|
||||||
self.open, self.filename, "wbt")
|
self.open, self.filename, "wbt")
|
||||||
|
self.assertRaises(ValueError,
|
||||||
|
self.open, self.filename, "xbt")
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError,
|
||||||
self.open, self.filename, "rb", encoding="utf-8")
|
self.open, self.filename, "rb", encoding="utf-8")
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError,
|
||||||
|
|
|
@ -54,8 +54,8 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
- Issue #19201: Add "x" mode (exclusive creation) in opening file to lzma
|
- Issues #19201, #19223: Add "x" mode (exclusive creation) in opening file to
|
||||||
module. Patch by Tim Heaney and Vajrasky Kok.
|
bz2 and lzma modules. Patches by Tim Heaney and Vajrasky Kok.
|
||||||
|
|
||||||
- Fix a reference count leak in _sre.
|
- Fix a reference count leak in _sre.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue