Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 42ca982

Browse files
committed
Issue #19201: Add support for the 'x' mode to the lzma module.
Patch by Tim Heaney and Vajrasky Kok.
1 parent c516815 commit 42ca982

5 files changed

Lines changed: 51 additions & 13 deletions

File tree

Doc/library/lzma.rst

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ Reading and writing compressed files
3939
opened, or it can be an existing file object to read from or write to.
4040

4141
The *mode* argument can be any of ``"r"``, ``"rb"``, ``"w"``, ``"wb"``,
42-
``"a"`` or ``"ab"`` for binary mode, or ``"rt"``, ``"wt"``, or ``"at"`` for
43-
text mode. The default is ``"rb"``.
42+
``"x"``, ``"xb"``, ``"a"`` or ``"ab"`` for binary mode, or ``"rt"``,
43+
``"wt"``, ``"xt"``, or ``"at"`` for text mode. The default is ``"rb"``.
4444

4545
When opening a file for reading, the *format* and *filters* arguments have
4646
the same meanings as for :class:`LZMADecompressor`. In this case, the *check*
@@ -57,6 +57,9 @@ Reading and writing compressed files
5757
:class:`io.TextIOWrapper` instance with the specified encoding, error
5858
handling behavior, and line ending(s).
5959

60+
.. versionchanged:: 3.4
61+
Added support for the ``"x"``, ``"xb"`` and ``"xt"`` modes.
62+
6063

6164
.. class:: LZMAFile(filename=None, mode="r", \*, format=None, check=-1, preset=None, filters=None)
6265

@@ -69,8 +72,9 @@ Reading and writing compressed files
6972
file will not be closed when the :class:`LZMAFile` is closed.
7073

7174
The *mode* argument can be either ``"r"`` for reading (default), ``"w"`` for
72-
overwriting, or ``"a"`` for appending. These can equivalently be given as
73-
``"rb"``, ``"wb"``, and ``"ab"`` respectively.
75+
overwriting, ``"x"`` for exclusive creation, or ``"a"`` for appending. These
76+
can equivalently be given as ``"rb"``, ``"wb"``, ``"xb"`` and ``"ab"``
77+
respectively.
7478

7579
If *filename* is a file object (rather than an actual file name), a mode of
7680
``"w"`` does not truncate the file, and is instead equivalent to ``"a"``.
@@ -98,6 +102,9 @@ Reading and writing compressed files
98102
byte of data will be returned, unless EOF has been reached. The exact
99103
number of bytes returned is unspecified (the *size* argument is ignored).
100104

105+
.. versionchanged:: 3.4
106+
Added support for the ``"x"`` and ``"xb"`` modes.
107+
101108

102109
Compressing and decompressing data in memory
103110
--------------------------------------------

Lib/lzma.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ def __init__(self, filename=None, mode="r", *,
5454
bytes object), in which case the named file is opened, or it can
5555
be an existing file object to read from or write to.
5656
57-
mode can be "r" for reading (default), "w" for (over)writing, or
58-
"a" for appending. These can equivalently be given as "rb", "wb"
59-
and "ab" respectively.
57+
mode can be "r" for reading (default), "w" for (over)writing,
58+
"x" for creating exclusively, or "a" for appending. These can
59+
equivalently be given as "rb", "wb", "xb" and "ab" respectively.
6060
6161
format specifies the container format to use for the file.
6262
If mode is "r", this defaults to FORMAT_AUTO. Otherwise, the
@@ -112,7 +112,7 @@ def __init__(self, filename=None, mode="r", *,
112112
self._decompressor = LZMADecompressor(**self._init_args)
113113
self._buffer = b""
114114
self._buffer_offset = 0
115-
elif mode in ("w", "wb", "a", "ab"):
115+
elif mode in ("w", "wb", "a", "ab", "x", "xb"):
116116
if format is None:
117117
format = FORMAT_XZ
118118
mode_code = _MODE_WRITE
@@ -426,8 +426,9 @@ def open(filename, mode="rb", *,
426426
object), in which case the named file is opened, or it can be an
427427
existing file object to read from or write to.
428428
429-
The mode argument can be "r", "rb" (default), "w", "wb", "a" or "ab"
430-
for binary mode, or "rt", "wt" or "at" for text mode.
429+
The mode argument can be "r", "rb" (default), "w", "wb", "x", "xb",
430+
"a", or "ab" for binary mode, or "rt", "wt", "xt", or "at" for text
431+
mode.
431432
432433
The format, check, preset and filters arguments specify the
433434
compression settings, as for LZMACompressor, LZMADecompressor and

Lib/test/test_lzma.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,8 @@ def test_init(self):
362362
pass
363363
with LZMAFile(BytesIO(), "w") as f:
364364
pass
365+
with LZMAFile(BytesIO(), "x") as f:
366+
pass
365367
with LZMAFile(BytesIO(), "a") as f:
366368
pass
367369

@@ -389,13 +391,29 @@ def test_init_mode(self):
389391
with LZMAFile(TESTFN, "ab"):
390392
pass
391393

394+
def test_init_with_x_mode(self):
395+
self.addCleanup(unlink, TESTFN)
396+
for mode in ("x", "xb"):
397+
unlink(TESTFN)
398+
with LZMAFile(TESTFN, mode):
399+
pass
400+
with self.assertRaises(FileExistsError):
401+
with LZMAFile(TESTFN, mode):
402+
pass
403+
392404
def test_init_bad_mode(self):
393405
with self.assertRaises(ValueError):
394406
LZMAFile(BytesIO(COMPRESSED_XZ), (3, "x"))
395407
with self.assertRaises(ValueError):
396408
LZMAFile(BytesIO(COMPRESSED_XZ), "")
397409
with self.assertRaises(ValueError):
398-
LZMAFile(BytesIO(COMPRESSED_XZ), "x")
410+
LZMAFile(BytesIO(COMPRESSED_XZ), "xt")
411+
with self.assertRaises(ValueError):
412+
LZMAFile(BytesIO(COMPRESSED_XZ), "x+")
413+
with self.assertRaises(ValueError):
414+
LZMAFile(BytesIO(COMPRESSED_XZ), "rx")
415+
with self.assertRaises(ValueError):
416+
LZMAFile(BytesIO(COMPRESSED_XZ), "wx")
399417
with self.assertRaises(ValueError):
400418
LZMAFile(BytesIO(COMPRESSED_XZ), "rt")
401419
with self.assertRaises(ValueError):
@@ -1021,8 +1039,6 @@ def test_bad_params(self):
10211039
# Test invalid parameter combinations.
10221040
with self.assertRaises(ValueError):
10231041
lzma.open(TESTFN, "")
1024-
with self.assertRaises(ValueError):
1025-
lzma.open(TESTFN, "x")
10261042
with self.assertRaises(ValueError):
10271043
lzma.open(TESTFN, "rbt")
10281044
with self.assertRaises(ValueError):
@@ -1072,6 +1088,16 @@ def test_newline(self):
10721088
with lzma.open(bio, "rt", newline="\r") as f:
10731089
self.assertEqual(f.readlines(), [text])
10741090

1091+
def test_x_mode(self):
1092+
self.addCleanup(unlink, TESTFN)
1093+
for mode in ("x", "xb", "xt"):
1094+
unlink(TESTFN)
1095+
with lzma.open(TESTFN, mode):
1096+
pass
1097+
with self.assertRaises(FileExistsError):
1098+
with lzma.open(TESTFN, mode):
1099+
pass
1100+
10751101

10761102
class MiscellaneousTestCase(unittest.TestCase):
10771103

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ Janko Hauser
506506
Rycharde Hawkes
507507
Ben Hayden
508508
Jochen Hayek
509+
Tim Heaney
509510
Henrik Heimbuerger
510511
Christian Heimes
511512
Thomas Heller

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ Core and Builtins
5454
Library
5555
-------
5656

57+
- Issue #19201: Add "x" mode (exclusive creation) in opening file to lzma
58+
module. Patch by Tim Heaney and Vajrasky Kok.
59+
5760
- Fix a reference count leak in _sre.
5861

5962
- Issue #19262: Initial check in of the 'asyncio' package (a.k.a. Tulip,

0 commit comments

Comments
 (0)