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-31602: Fix an assertion failure in zipimporter.get_source() in case of a bad zlib.decompress() #3784

Merged
merged 7 commits into from
Sep 29, 2017

Conversation

orenmn
Copy link
Contributor

@orenmn orenmn commented Sep 27, 2017

  • in zipimport.c: add a check whether zlib.decompress() returned a bytes object.
  • in test_zipimport.py: add a test to verify that the assertion failure is no more.

https://bugs.python.org/issue31602

Copy link
Member

@brettcannon brettcannon left a comment

Choose a reason for hiding this comment

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

The fix LGTM, but some tweaks to make to the test to use some specific idioms.

import zlib
def bad_decompress(*args):
return None
z = ZipFile(TEMP_ZIP, 'w')
Copy link
Member

Choose a reason for hiding this comment

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

We tend to prefer people use more descriptive variable names and avoid single-letter ones unless it's a loop counter.

self.assertRaises(TypeError, zi.get_source, 'bar')
finally:
z.close()
os.remove(TEMP_ZIP)
Copy link
Member

Choose a reason for hiding this comment

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

You can use self.addCleanup() so you don't have to specify this in the try block.

with support.swap_attr(zlib, 'decompress', bad_decompress):
self.assertRaises(TypeError, zi.get_source, 'bar')
finally:
z.close()
Copy link
Member

Choose a reason for hiding this comment

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

You also called z.close() above, so I would use my self.addCleanup() suggestion below and rework this to drop the try block and use the context manager for zipfiles:

name = 'bar.py'
data = b'spam'
with ZipFile(...) as zip_file:
    self.addCleanup(os.remove, TEMP_ZIP)
    zip_file.writestr(...)
zi = ...

def test_issue31602(self):
# There shouldn't be an assertion failure in zipimporter.get_source()
# in case of a bad zlib.decompress().
import zlib
Copy link
Member

Choose a reason for hiding this comment

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

There is no guarantee the zlib module will be available, so at the top of the module you should do:

try:
  import zlib
except ImportError:
  zlib = None

Then decorate this method with unittest.skipIf(zlib is None, "zlib not available").

Copy link
Member

Choose a reason for hiding this comment

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

Or use the test.support.requires_zlib decorator.

Copy link
Contributor Author

@orenmn orenmn Sep 28, 2017

Choose a reason for hiding this comment

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

doesn't this decorator already guarantee that zlib will be available for the test?

@support.requires_zlib
class CompressedZipImportTestCase(UncompressedZipImportTestCase):

Copy link
Member

Choose a reason for hiding this comment

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

Yes, it was just out of the visible context.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, then keep the decorator but still switch to the try block at the top for the import (importing in methods is icky).

@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 didn't expect the Spanish Inquisition!. 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.

self.assertRaises(TypeError, zi.get_source, 'bar')
finally:
z.close()
os.remove(TEMP_ZIP)
Copy link
Member

Choose a reason for hiding this comment

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

It is better to use test.support.unlink().

def test_issue31602(self):
# There shouldn't be an assertion failure in zipimporter.get_source()
# in case of a bad zlib.decompress().
import zlib
Copy link
Member

Choose a reason for hiding this comment

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

Or use the test.support.requires_zlib decorator.

@orenmn
Copy link
Contributor Author

orenmn commented Sep 28, 2017

I didn't expect the Spanish Inquisition!

@bedevere-bot
Copy link

Nobody expects the Spanish Inquisition!

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

def test_issue31602(self):
# There shouldn't be an assertion failure in zipimporter.get_source()
# in case of a bad zlib.decompress().
import zlib
Copy link
Member

Choose a reason for hiding this comment

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

Yes, it was just out of the visible context.

return None
with ZipFile(TEMP_ZIP, 'w') as zip_file:
self.addCleanup(support.unlink, TEMP_ZIP)
name = 'bar.py'
Copy link
Member

Choose a reason for hiding this comment

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

Why not inline these values? For clarity use a valid Python statement instead of 'spam'.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No idea why not. I just copied the style of all other tests in this file.

Copy link
Member

@brettcannon brettcannon left a comment

Choose a reason for hiding this comment

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

One very minor cleanup left and then this PR is ready for merging!

def test_issue31602(self):
# There shouldn't be an assertion failure in zipimporter.get_source()
# in case of a bad zlib.decompress().
import zlib
Copy link
Member

Choose a reason for hiding this comment

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

Ah, then keep the decorator but still switch to the try block at the top for the import (importing in methods is icky).

@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 didn't expect the Spanish Inquisition!. 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.

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

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

The test now looks much nicer!

@brettcannon
Copy link
Member

It's so weird to be looking at the latest update to the PR and have the latest commit from @orenmn literally land right in front of me. 😄

@orenmn
Copy link
Contributor Author

orenmn commented Sep 29, 2017

This happened only thanks to Murphy's law.
On my machine test_zipimport passed, but travis failed immediately.
I am not sure why. Maybe because testAFakeZlib() messes with zlib?

@brettcannon
Copy link
Member

The failure was from an automatic cancellation on the part of Travis; it decided to start a new build and thus cancelled the already-running one. But everything is good now!

@brettcannon brettcannon merged commit 01c6a88 into python:master Sep 29, 2017
@brettcannon
Copy link
Member

Thanks for the pull request!

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.

None yet

6 participants