Issue #19201: Add support for the 'x' mode to the lzma module.

Patch by Tim Heaney and Vajrasky Kok.
This commit is contained in:
Nadeem Vawda 2013-10-19 00:06:19 +02:00
parent c516815353
commit 42ca98217c
5 changed files with 51 additions and 13 deletions

View File

@ -39,8 +39,8 @@ Reading and writing compressed files
opened, or it can be an existing file object to read from or write to. opened, or it can be an existing 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"``.
When opening a file for reading, the *format* and *filters* arguments have When opening a file for reading, the *format* and *filters* arguments have
the same meanings as for :class:`LZMADecompressor`. In this case, the *check* the same meanings as for :class:`LZMADecompressor`. In this case, the *check*
@ -57,6 +57,9 @@ Reading and writing compressed files
:class:`io.TextIOWrapper` instance with the specified encoding, error :class:`io.TextIOWrapper` instance with the specified encoding, error
handling behavior, and line ending(s). handling behavior, and line ending(s).
.. versionchanged:: 3.4
Added support for the ``"x"``, ``"xb"`` and ``"xt"`` modes.
.. class:: LZMAFile(filename=None, mode="r", \*, format=None, check=-1, preset=None, filters=None) .. class:: LZMAFile(filename=None, mode="r", \*, format=None, check=-1, preset=None, filters=None)
@ -69,8 +72,9 @@ Reading and writing compressed files
file will not be closed when the :class:`LZMAFile` is closed. file will not be closed when the :class:`LZMAFile` is closed.
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"``.
@ -98,6 +102,9 @@ Reading and writing compressed files
byte of data will be returned, unless EOF has been reached. The exact byte of data will be returned, unless EOF has been reached. The exact
number of bytes returned is unspecified (the *size* argument is ignored). number of bytes returned is unspecified (the *size* argument is ignored).
.. versionchanged:: 3.4
Added support for the ``"x"`` and ``"xb"`` modes.
Compressing and decompressing data in memory Compressing and decompressing data in memory
-------------------------------------------- --------------------------------------------

View File

@ -54,9 +54,9 @@ class LZMAFile(io.BufferedIOBase):
bytes object), in which case the named file is opened, or it can bytes object), in which case the named file is opened, or it can
be an existing file object to read from or write to. be an existing file object to read from or write to.
mode can be "r" for reading (default), "w" for (over)writing, or mode can be "r" for reading (default), "w" for (over)writing,
"a" for appending. These can equivalently be given as "rb", "wb" "x" for creating exclusively, or "a" for appending. These can
and "ab" respectively. equivalently be given as "rb", "wb", "xb" and "ab" respectively.
format specifies the container format to use for the file. format specifies the container format to use for the file.
If mode is "r", this defaults to FORMAT_AUTO. Otherwise, the If mode is "r", this defaults to FORMAT_AUTO. Otherwise, the
@ -112,7 +112,7 @@ class LZMAFile(io.BufferedIOBase):
self._decompressor = LZMADecompressor(**self._init_args) self._decompressor = LZMADecompressor(**self._init_args)
self._buffer = b"" self._buffer = b""
self._buffer_offset = 0 self._buffer_offset = 0
elif mode in ("w", "wb", "a", "ab"): elif mode in ("w", "wb", "a", "ab", "x", "xb"):
if format is None: if format is None:
format = FORMAT_XZ format = FORMAT_XZ
mode_code = _MODE_WRITE mode_code = _MODE_WRITE
@ -426,8 +426,9 @@ def open(filename, mode="rb", *,
object), in which case the named file is opened, or it can be an object), in which case the named file is opened, or it can be an
existing file object to read from or write to. existing file object to read from or write to.
The mode argument can be "r", "rb" (default), "w", "wb", "a" or "ab" The mode argument can be "r", "rb" (default), "w", "wb", "x", "xb",
for binary mode, or "rt", "wt" or "at" for text mode. "a", or "ab" for binary mode, or "rt", "wt", "xt", or "at" for text
mode.
The format, check, preset and filters arguments specify the The format, check, preset and filters arguments specify the
compression settings, as for LZMACompressor, LZMADecompressor and compression settings, as for LZMACompressor, LZMADecompressor and

View File

@ -362,6 +362,8 @@ class FileTestCase(unittest.TestCase):
pass pass
with LZMAFile(BytesIO(), "w") as f: with LZMAFile(BytesIO(), "w") as f:
pass pass
with LZMAFile(BytesIO(), "x") as f:
pass
with LZMAFile(BytesIO(), "a") as f: with LZMAFile(BytesIO(), "a") as f:
pass pass
@ -389,13 +391,29 @@ class FileTestCase(unittest.TestCase):
with LZMAFile(TESTFN, "ab"): with LZMAFile(TESTFN, "ab"):
pass pass
def test_init_with_x_mode(self):
self.addCleanup(unlink, TESTFN)
for mode in ("x", "xb"):
unlink(TESTFN)
with LZMAFile(TESTFN, mode):
pass
with self.assertRaises(FileExistsError):
with LZMAFile(TESTFN, mode):
pass
def test_init_bad_mode(self): def test_init_bad_mode(self):
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
LZMAFile(BytesIO(COMPRESSED_XZ), (3, "x")) LZMAFile(BytesIO(COMPRESSED_XZ), (3, "x"))
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
LZMAFile(BytesIO(COMPRESSED_XZ), "") LZMAFile(BytesIO(COMPRESSED_XZ), "")
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
LZMAFile(BytesIO(COMPRESSED_XZ), "x") LZMAFile(BytesIO(COMPRESSED_XZ), "xt")
with self.assertRaises(ValueError):
LZMAFile(BytesIO(COMPRESSED_XZ), "x+")
with self.assertRaises(ValueError):
LZMAFile(BytesIO(COMPRESSED_XZ), "rx")
with self.assertRaises(ValueError):
LZMAFile(BytesIO(COMPRESSED_XZ), "wx")
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
LZMAFile(BytesIO(COMPRESSED_XZ), "rt") LZMAFile(BytesIO(COMPRESSED_XZ), "rt")
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
@ -1021,8 +1039,6 @@ class OpenTestCase(unittest.TestCase):
# Test invalid parameter combinations. # Test invalid parameter combinations.
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
lzma.open(TESTFN, "") lzma.open(TESTFN, "")
with self.assertRaises(ValueError):
lzma.open(TESTFN, "x")
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
lzma.open(TESTFN, "rbt") lzma.open(TESTFN, "rbt")
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
@ -1072,6 +1088,16 @@ class OpenTestCase(unittest.TestCase):
with lzma.open(bio, "rt", newline="\r") as f: with lzma.open(bio, "rt", newline="\r") as f:
self.assertEqual(f.readlines(), [text]) self.assertEqual(f.readlines(), [text])
def test_x_mode(self):
self.addCleanup(unlink, TESTFN)
for mode in ("x", "xb", "xt"):
unlink(TESTFN)
with lzma.open(TESTFN, mode):
pass
with self.assertRaises(FileExistsError):
with lzma.open(TESTFN, mode):
pass
class MiscellaneousTestCase(unittest.TestCase): class MiscellaneousTestCase(unittest.TestCase):

View File

@ -506,6 +506,7 @@ Janko Hauser
Rycharde Hawkes Rycharde Hawkes
Ben Hayden Ben Hayden
Jochen Hayek Jochen Hayek
Tim Heaney
Henrik Heimbuerger Henrik Heimbuerger
Christian Heimes Christian Heimes
Thomas Heller Thomas Heller

View File

@ -54,6 +54,9 @@ Core and Builtins
Library Library
------- -------
- Issue #19201: Add "x" mode (exclusive creation) in opening file to lzma
module. Patch by Tim Heaney and Vajrasky Kok.
- Fix a reference count leak in _sre. - Fix a reference count leak in _sre.
- Issue #19262: Initial check in of the 'asyncio' package (a.k.a. Tulip, - Issue #19262: Initial check in of the 'asyncio' package (a.k.a. Tulip,