diff --git a/Doc/library/gzip.rst b/Doc/library/gzip.rst index 3349a94446d..33c40676f74 100644 --- a/Doc/library/gzip.rst +++ b/Doc/library/gzip.rst @@ -88,7 +88,8 @@ The module defines the following items: The *mode* argument can be any of ``'r'``, ``'rb'``, ``'a'``, ``'ab'``, ``'w'``, ``'wb'``, ``'x'``, or ``'xb'``, depending on whether the file will be read or written. The default is the mode of *fileobj* if discernible; otherwise, the - default is ``'rb'``. + default is ``'rb'``. In future Python releases the mode of *fileobj* will + not be used. It is better to always specify *mode* for writing. Note that the file is always opened in binary mode. To open a compressed file in text mode, use :func:`.open` (or wrap your :class:`GzipFile` with an @@ -164,6 +165,10 @@ The module defines the following items: .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. deprecated:: 3.9 + Opening :class:`GzipFile` for writing without specifying the *mode* + argument is deprecated. + .. function:: compress(data, compresslevel=9, *, mtime=None) diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 6e9ddc56840..ddb295f845c 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -239,6 +239,12 @@ Deprecated the module will restrict its seeds to :const:`None`, :class:`int`, :class:`float`, :class:`str`, :class:`bytes`, and :class:`bytearray`. +* Opening the :class:`~gzip.GzipFile` file for writing without specifying + the *mode* argument is deprecated. In future Python versions it will always + be opened for reading by default. Specify the *mode* argument for opening + it for writing and silencing a warning. + (Contributed by Serhiy Storchaka in :issue:`28286`.) + * Deprecated the ``split()`` method of :class:`_tkinter.TkappType` in favour of the ``splitlist()`` method which has more consistent and predicable behavior. diff --git a/Lib/gzip.py b/Lib/gzip.py index 2968f475efa..e60d8ad5995 100644 --- a/Lib/gzip.py +++ b/Lib/gzip.py @@ -177,6 +177,7 @@ class GzipFile(_compression.BaseStream): filename = '' else: filename = os.fspath(filename) + origmode = mode if mode is None: mode = getattr(fileobj, 'mode', 'rb') @@ -187,6 +188,13 @@ class GzipFile(_compression.BaseStream): self.name = filename elif mode.startswith(('w', 'a', 'x')): + if origmode is None: + import warnings + warnings.warn( + "GzipFile was opened for writing, but this will " + "change in future Python releases. " + "Specify the mode argument for opening it for writing.", + FutureWarning, 2) self.mode = WRITE self._init_write(filename) self.compress = zlib.compressobj(compresslevel, diff --git a/Lib/test/test_gzip.py b/Lib/test/test_gzip.py index 48a36a30913..57d851cf9cf 100644 --- a/Lib/test/test_gzip.py +++ b/Lib/test/test_gzip.py @@ -469,7 +469,9 @@ class TestGzip(BaseTest): if "x" in mode: support.unlink(self.filename) with open(self.filename, mode) as f: - with gzip.GzipFile(fileobj=f) as g: + with self.assertWarns(FutureWarning): + g = gzip.GzipFile(fileobj=f) + with g: self.assertEqual(g.mode, gzip.WRITE) def test_bytes_filename(self): diff --git a/Misc/NEWS.d/next/Library/2019-09-26-12-16-30.bpo-28286.LdSsrN.rst b/Misc/NEWS.d/next/Library/2019-09-26-12-16-30.bpo-28286.LdSsrN.rst new file mode 100644 index 00000000000..ee9721587ee --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-09-26-12-16-30.bpo-28286.LdSsrN.rst @@ -0,0 +1,2 @@ +Deprecate opening :class:`~gzip.GzipFile` for writing implicitly. Always +specify the *mode* argument for writing.