[Python-checkins] cpython: Issue #19201: Add support for the 'x' mode to the lzma module.

nadeem.vawda python-checkins at python.org
Sat Oct 19 00:11:39 CEST 2013


http://hg.python.org/cpython/rev/b7948aaca1dd
changeset:   86450:b7948aaca1dd
user:        Nadeem Vawda <nadeem.vawda at gmail.com>
date:        Sat Oct 19 00:06:19 2013 +0200
summary:
  Issue #19201: Add support for the 'x' mode to the lzma module.

Patch by Tim Heaney and Vajrasky Kok.

files:
  Doc/library/lzma.rst  |  15 ++++++++++---
  Lib/lzma.py           |  13 ++++++-----
  Lib/test/test_lzma.py |  32 ++++++++++++++++++++++++++++--
  Misc/ACKS             |   1 +
  Misc/NEWS             |   3 ++
  5 files changed, 51 insertions(+), 13 deletions(-)


diff --git a/Doc/library/lzma.rst b/Doc/library/lzma.rst
--- a/Doc/library/lzma.rst
+++ b/Doc/library/lzma.rst
@@ -39,8 +39,8 @@
    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"``,
-   ``"a"`` or ``"ab"`` for binary mode, or ``"rt"``, ``"wt"``, or ``"at"`` for
-   text mode. The default is ``"rb"``.
+   ``"x"``, ``"xb"``, ``"a"`` or ``"ab"`` for binary mode, or ``"rt"``,
+   ``"wt"``, ``"xt"``, or ``"at"`` for text mode. The default is ``"rb"``.
 
    When opening a file for reading, the *format* and *filters* arguments have
    the same meanings as for :class:`LZMADecompressor`. In this case, the *check*
@@ -57,6 +57,9 @@
    :class:`io.TextIOWrapper` instance with the specified encoding, error
    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)
 
@@ -69,8 +72,9 @@
    file will not be closed when the :class:`LZMAFile` is closed.
 
    The *mode* argument can be either ``"r"`` for reading (default), ``"w"`` for
-   overwriting, or ``"a"`` for appending. These can equivalently be given as
-   ``"rb"``, ``"wb"``, and ``"ab"`` respectively.
+   overwriting, ``"x"`` for exclusive creation, or ``"a"`` for appending. These
+   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
    ``"w"`` does not truncate the file, and is instead equivalent to ``"a"``.
@@ -98,6 +102,9 @@
       byte of data will be returned, unless EOF has been reached. The exact
       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
 --------------------------------------------
diff --git a/Lib/lzma.py b/Lib/lzma.py
--- a/Lib/lzma.py
+++ b/Lib/lzma.py
@@ -54,9 +54,9 @@
         bytes object), in which case the named file is opened, or it can
         be an existing file object to read from or write to.
 
-        mode can be "r" for reading (default), "w" for (over)writing, or
-        "a" for appending. These can equivalently be given as "rb", "wb"
-        and "ab" respectively.
+        mode can be "r" for reading (default), "w" for (over)writing,
+        "x" for creating exclusively, or "a" for appending. These can
+        equivalently be given as "rb", "wb", "xb" and "ab" respectively.
 
         format specifies the container format to use for the file.
         If mode is "r", this defaults to FORMAT_AUTO. Otherwise, the
@@ -112,7 +112,7 @@
             self._decompressor = LZMADecompressor(**self._init_args)
             self._buffer = b""
             self._buffer_offset = 0
-        elif mode in ("w", "wb", "a", "ab"):
+        elif mode in ("w", "wb", "a", "ab", "x", "xb"):
             if format is None:
                 format = FORMAT_XZ
             mode_code = _MODE_WRITE
@@ -426,8 +426,9 @@
     object), in which case the named file is opened, or it can be an
     existing file object to read from or write to.
 
-    The mode argument can be "r", "rb" (default), "w", "wb", "a" or "ab"
-    for binary mode, or "rt", "wt" or "at" for text mode.
+    The mode argument can be "r", "rb" (default), "w", "wb", "x", "xb",
+    "a", or "ab" for binary mode, or "rt", "wt", "xt", or "at" for text
+    mode.
 
     The format, check, preset and filters arguments specify the
     compression settings, as for LZMACompressor, LZMADecompressor and
diff --git a/Lib/test/test_lzma.py b/Lib/test/test_lzma.py
--- a/Lib/test/test_lzma.py
+++ b/Lib/test/test_lzma.py
@@ -362,6 +362,8 @@
             pass
         with LZMAFile(BytesIO(), "w") as f:
             pass
+        with LZMAFile(BytesIO(), "x") as f:
+            pass
         with LZMAFile(BytesIO(), "a") as f:
             pass
 
@@ -389,13 +391,29 @@
             with LZMAFile(TESTFN, "ab"):
                 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):
         with self.assertRaises(ValueError):
             LZMAFile(BytesIO(COMPRESSED_XZ), (3, "x"))
         with self.assertRaises(ValueError):
             LZMAFile(BytesIO(COMPRESSED_XZ), "")
         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):
             LZMAFile(BytesIO(COMPRESSED_XZ), "rt")
         with self.assertRaises(ValueError):
@@ -1022,8 +1040,6 @@
         with self.assertRaises(ValueError):
             lzma.open(TESTFN, "")
         with self.assertRaises(ValueError):
-            lzma.open(TESTFN, "x")
-        with self.assertRaises(ValueError):
             lzma.open(TESTFN, "rbt")
         with self.assertRaises(ValueError):
             lzma.open(TESTFN, "rb", encoding="utf-8")
@@ -1072,6 +1088,16 @@
             with lzma.open(bio, "rt", newline="\r") as f:
                 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):
 
diff --git a/Misc/ACKS b/Misc/ACKS
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -506,6 +506,7 @@
 Rycharde Hawkes
 Ben Hayden
 Jochen Hayek
+Tim Heaney
 Henrik Heimbuerger
 Christian Heimes
 Thomas Heller
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -54,6 +54,9 @@
 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.
 
 - Issue #19262: Initial check in of the 'asyncio' package (a.k.a. Tulip,

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list