Skip to content

Commit 0e7497c

Browse files
guociserhiy-storchaka
authored andcommitted
bpo-34898: Add mtime parameter to gzip.compress(). (GH-9704)
Without setting mtime, time.time() will be used as the timestamp which will end up in the compressed data and each invocation of the compress() function will vary over time.
1 parent d2b11af commit 0e7497c

File tree

6 files changed

+27
-4
lines changed

6 files changed

+27
-4
lines changed

Doc/library/gzip.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,15 @@ The module defines the following items:
157157
Accepts a :term:`path-like object`.
158158

159159

160-
.. function:: compress(data, compresslevel=9)
160+
.. function:: compress(data, compresslevel=9, *, mtime=None)
161161

162162
Compress the *data*, returning a :class:`bytes` object containing
163-
the compressed data. *compresslevel* has the same meaning as in
163+
the compressed data. *compresslevel* and *mtime* have the same meaning as in
164164
the :class:`GzipFile` constructor above.
165165

166166
.. versionadded:: 3.2
167+
.. versionchanged:: 3.8
168+
Added the *mtime* parameter for reproducible output.
167169

168170
.. function:: decompress(data)
169171

Doc/whatsnew/3.8.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,13 @@ asyncio
131131
On Windows, the default event loop is now :class:`~asyncio.ProactorEventLoop`.
132132

133133

134+
gzip
135+
----
136+
137+
Added the *mtime* parameter to :func:`gzip.compress` for reproducible output.
138+
(Contributed by Guo Ci Teo in :issue:`34898`.)
139+
140+
134141
idlelib and IDLE
135142
----------------
136143

Lib/gzip.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,12 +520,12 @@ def _rewind(self):
520520
super()._rewind()
521521
self._new_member = True
522522

523-
def compress(data, compresslevel=_COMPRESS_LEVEL_BEST):
523+
def compress(data, compresslevel=_COMPRESS_LEVEL_BEST, *, mtime=None):
524524
"""Compress data in one shot and return the compressed string.
525525
Optional argument is the compression level, in range of 0-9.
526526
"""
527527
buf = io.BytesIO()
528-
with GzipFile(fileobj=buf, mode='wb', compresslevel=compresslevel) as f:
528+
with GzipFile(fileobj=buf, mode='wb', compresslevel=compresslevel, mtime=mtime) as f:
529529
f.write(data)
530530
return buf.getvalue()
531531

Lib/test/test_gzip.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,17 @@ def test_compress(self):
499499
with gzip.GzipFile(fileobj=io.BytesIO(datac), mode="rb") as f:
500500
self.assertEqual(f.read(), data)
501501

502+
def test_compress_mtime(self):
503+
mtime = 123456789
504+
for data in [data1, data2]:
505+
for args in [(), (1,), (6,), (9,)]:
506+
with self.subTest(data=data, args=args):
507+
datac = gzip.compress(data, *args, mtime=mtime)
508+
self.assertEqual(type(datac), bytes)
509+
with gzip.GzipFile(fileobj=io.BytesIO(datac), mode="rb") as f:
510+
f.read(1) # to set mtime attribute
511+
self.assertEqual(f.mtime, mtime)
512+
502513
def test_decompress(self):
503514
for data in (data1, data2):
504515
buf = io.BytesIO()

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,7 @@ Monty Taylor
16151615
Anatoly Techtonik
16161616
Martin Teichmann
16171617
Gustavo Temple
1618+
Guo Ci Teo
16181619
Mikhail Terekhov
16191620
Victor Terrón
16201621
Pablo Galindo
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add `mtime` argument to `gzip.compress` for reproducible output.
2+
Patch by Guo Ci Teo.

0 commit comments

Comments
 (0)