Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-34097: Add support for zipping files older than 1980-01-01 #8270

Merged
merged 13 commits into from Aug 2, 2018
Merged

bpo-34097: Add support for zipping files older than 1980-01-01 #8270

merged 13 commits into from Aug 2, 2018

Conversation

ghost
Copy link

@ghost ghost commented Jul 13, 2018

This pull request adds a new option for zipping files older than 1980-01-01.
The user has to explicitly opt in by passing a keyword strict_timestamps=False to the ZipFile.write() method. This option will zip the file at the cost of setting the file timestamp to 1980-01-01 if older than zip limit.

https://bugs.python.org/issue34097

# Set atime and mtime to 1970-01-01
os.utime(TESTFN, (0, 0))
with zipfile.ZipFile(TESTFN2, "w") as zipfp:
zipfp.write(TESTFN, strict_timestamps=False)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also test the resulting timestamp is 1980-01-01 as expected.

.. versionadded:: 3.8
The *strict_timestamps* keyword argument allows zip files older
than 1/1/1980 at the cost of setting the year to 1980.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please describe the argument in the main text, then just use .. versionadded:: 3.8 The *strict_timestamps* keyword argument in the changelog. Same below.

.. versionadded:: 3.8
The *strict_timestamps* keyword argument allows zip files older
than 1/1/1980 at the cost of setting the year to 1980.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the international and unambiguous "ISO format" to refer to dates: 1980-01-01.

@bedevere-bot
Copy link

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@ghost ghost changed the title bpo-34097: Add support for zipping files older than 1/1/1980 bpo-34097: Add support for zipping files older than 1980-01-01 Jul 13, 2018
@ghost
Copy link
Author

ghost commented Jul 13, 2018

I have made the requested changes; please review again

@bedevere-bot
Copy link

Thanks for making the requested changes!

@encukou: please review the changes made to this pull request.

@@ -377,6 +377,8 @@ ZipFile Objects
the new entry. Similarly, *compresslevel* will override the constructor if
given.
The archive must be open with mode ``'w'``, ``'x'`` or ``'a'``.
The *strict_timestamps* keyword argument allows to zip files older
than 1980-01-01 at the cost of setting the timestamp to 1980-01-01.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just from the doc, I don't understand if I have to set the parameter to True or False to allow years older than 1980.

@@ -484,6 +484,8 @@ def from_file(cls, filename, arcname=None):
isdir = stat.S_ISDIR(st.st_mode)
mtime = time.localtime(st.st_mtime)
date_time = mtime[0:6]
if not strict_timestamps and date_time[0] < 1980:
date_time = (1980, 1, 1, 0, 0, 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like the largest year is 2107. Years after 2017 should also be clamped to 2017-12-31, no?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@@ -549,6 +549,14 @@ def test_add_file_before_1980(self):
with zipfile.ZipFile(TESTFN2, "w") as zipfp:
self.assertRaises(ValueError, zipfp.write, TESTFN)

def test_add_file_before_1980_no_strict_timestamps(self):
# Set atime and mtime to 1970-01-01
os.utime(TESTFN, (0, 0))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using the real filesystem which can cause troubles, maybe you can mock os.stat() intsead of return the date that you want?

It may allow to test date after year 2107.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous test is also using this. It shouldn't be a problem then.

@bedevere-bot
Copy link

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@@ -368,7 +368,7 @@ ZipFile Objects


.. method:: ZipFile.write(filename, arcname=None, compress_type=None, \
compresslevel=None)
compresslevel=None, strict_timestamps=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to use a keyword-only parameter. Same remark for other methods and functions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bikeshedding: why not just "strict_timestamp=True" (no S)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are more timestamps in the zip archive. each file has it's own.

@@ -0,0 +1,2 @@
ZipFile can zip files older than 1980-01-01 at the cost of mangling the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should mention the new timestamps parameter. And maybe explain "mangling": dates before 1980-01-01 are replaced by 1980-01-01 at 00:00.

@ghost
Copy link
Author

ghost commented Jul 31, 2018

I have made the requested changes; please review again.

@bedevere-bot
Copy link

Thanks for making the requested changes!

@vstinner, @encukou: please review the changes made to this pull request.

The *strict_timestamps* keyword argument, when set to ``False``, allows to
zip files older than 1980-01-01 at the cost of setting the
timestamp to 1980-01-01.
Same behavior occures with files older than 2107-12-31.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not the same behavior, it is not set to 1980-01-01 in that case, but rather to 2107-12-31.

Copy link
Contributor

@hroncok hroncok Jul 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe something like: "Similar behavior occurs with files older newer than 2107-12-31, the timestamp is also set to the limit."

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good.
I have also noticed I have 'older' where 'newer' should be.

The *strict_timestamps* keyword argument, when set to ``False``, allows to
zip files older than 1980-01-01 at the cost of setting the
timestamp to 1980-01-01.
Same behavior occures with files older than 2107-12-31.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

Copy link
Member

@vstinner vstinner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha, the new code now looks better! A few more comments.

@@ -400,6 +404,9 @@ ZipFile Objects
a closed ZipFile will raise a :exc:`ValueError`. Previously,
a :exc:`RuntimeError` was raised.

.. versionadded:: 3.8
The *strict_timestamps* keyword argument
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: you may write "keyword-only", and also add a final dot.

@@ -551,11 +559,19 @@ file:
If *arcname* is not specified, the name will be the same as *filename*, but
with any drive letter and leading path separators removed.

The *strict_timestamps* keyword argument, when set to ``False``, allows to
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that it's needed to repeat here that it's a keyword argument, just write "argument".

with zipfile.ZipFile(TESTFN2, "w") as zipfp:
self.assertRaises(struct.error, zipfp.write, TESTFN)

def test_add_file_after_2107_no_strict_timestamps(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO you can move this test inside test_add_file_after_2107(), no need to have two different tests.

with zipfile.ZipFile(TESTFN2, "w") as zipfp:
zipfp.write(TESTFN, strict_timestamps=False)
zinfo = zipfp.getinfo(TESTFN)
self.assertEqual(zinfo.date_time, (1980, 1, 1, 0, 0, 0))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would help to also make sure that you can add error when using strict_timestamps=True here.

@encukou encukou dismissed their stale review August 1, 2018 12:49

Code changed

Copy link
Member

@vstinner vstinner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but I would prefer to be the tests modified for my proposal.

@@ -484,6 +484,8 @@ def from_file(cls, filename, arcname=None):
isdir = stat.S_ISDIR(st.st_mode)
mtime = time.localtime(st.st_mtime)
date_time = mtime[0:6]
if not strict_timestamps and date_time[0] < 1980:
date_time = (1980, 1, 1, 0, 0, 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

os.utime(TESTFN, (4386268800, 4386268800))
with zipfile.ZipFile(TESTFN2, "w") as zipfp:
self.assertRaises(struct.error, zipfp.write, TESTFN)
zipfp.write(TESTFN, strict_timestamps=False)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to reopen the file for the second test, since it's hard to guess what happens when on error occurs. I prefer to limit side effets of unit tests.

@@ -548,6 +548,18 @@ def test_add_file_before_1980(self):
os.utime(TESTFN, (0, 0))
with zipfile.ZipFile(TESTFN2, "w") as zipfp:
self.assertRaises(ValueError, zipfp.write, TESTFN)
zipfp.write(TESTFN, strict_timestamps=False)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to reopen the file for the second test, since it's hard to guess what happens when on error occurs. I prefer to limit side effets of unit tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants