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

Add AssertImportHook.is_package() method #136

Closed
wants to merge 10 commits into from
Closed

Conversation

dahlia
Copy link

@dahlia dahlia commented Jul 10, 2012

Although implementing .is_package() is optional according to PEP 302, it makes several Python codes that assume every import hook implements this method (e.g. Flask) to work well with Attest.

Implementing .is_package() is optional according to PEP 302,
but it makes several Python codes that assume import hook has
this method (e.g. Flask) to work well with Attest.
@SimonSapin
Copy link
Collaborator

@dahlia , thanks for working on this but nobody really is maintaining Attest at the moment, see #131

@bradleyayers
Copy link
Collaborator

I'll have a look over this.

@bradleyayers
Copy link
Collaborator

After reading PEP 302 (thanks for the link) it appears that your patch doesn't properly implement the spec.

It says "All three methods should raise ImportError if the module wasn't found.". If you have a look at the existing code for get_source you'll find:

try:
    (fd, fn, info), path = self._cache[name]
except KeyError:
    raise ImportError(name)

I think this pattern should be repeated for is_package.

It would also seem that we should add support for get_code, as per "… each of which should be implemented, or none at all". While were at it it's probably worth adding get_filename too.

@dahlia
Copy link
Author

dahlia commented Jul 13, 2012

Thanks for your review. AssertImportHook.get_source() method currently returns a triple of (code, filename, newpath) instead of a source string. Should it be changed too?

@bradleyayers
Copy link
Collaborator

From reading the PEP, that definitely seems to be the case. I wonder why it was originally written to return (code, filename, newpath), and ideas?

@dahlia
Copy link
Author

dahlia commented Jul 13, 2012

As I guessed from 5109379, this method was originally written for internal use, not for implementing the loader protocol, and it chose the name get_source by accident.

We can simply rename this method. Any suggestions for its new name?

@bradleyayers
Copy link
Collaborator

I think we could probably get away with just implementing the other methods (get_filename, etc) and refactor load_module to use those. Then we can make get_source just return the file contents as it's suppose to.

@dahlia
Copy link
Author

dahlia commented Jul 13, 2012

Implemented get_filename(), get_code() methods, and refactored load_module(), get_source() methods.

@@ -300,19 +307,50 @@ def get_source(self, name):
except KeyError:
raise ImportError(name)

code = filename = newpath = None
code = None
Copy link
Collaborator

Choose a reason for hiding this comment

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

Instead of storing to code and returning at the end, you could just return from within each if/elif, would save a couple of lines.

Copy link
Author

Choose a reason for hiding this comment

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

Actually I firstly wrote to return from within each case, but when I saw the original code it was written in such way (returning at th end), so I followed the way. Okay, I’ll change this anyway. Thank you!

@bradleyayers
Copy link
Collaborator

Overall I really like this, my only criticism now is the lack of tests. I'm not sure the best strategy for testing it, any thoughts?

@dahlia
Copy link
Author

dahlia commented Jul 13, 2012

Actually I have no idea how to test it correctly and well.

try:
(fd, fn, info), path = self._cache[name]
except KeyError:
return ImportError(name)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should be raise, not return.

@bradleyayers
Copy link
Collaborator

The loader.get_code(fullname) method should return the code object associated with the module, or None if it's a built-in or extension module.

How should we handle this? How do we determine if a fullname refers to a built-in or extension module?

@bradleyayers
Copy link
Collaborator

So where should we go from here? I haven't had a chance to test this with anything that's likely to expose problems (e.g. with Flask) and I'd like to do that before merging. Have you had any great ideas on how to automated test this?

@dahlia
Copy link
Author

dahlia commented Jul 16, 2012

I wrote a small test for get_code() and made it to return None when the name is a builtin or an extension. Is this test too naive?

@leiserfg
Copy link

leiserfg commented Feb 2, 2013

I resolve this problem by adding the method is_package to the AssertImportHook in the hook.py file, this is my snippet:

    def is_package(self, name):
        try:
            info = self._cache[name][0][2]
        except KeyError:
            raise ImportError(name)
        return info[2] == imp.PKG_DIRECTORY

It's work fine with flask, please add it to the next Attest version.

@dahlia dahlia closed this Sep 20, 2016
vthriller added a commit to vthriller/flask-genshi that referenced this pull request Mar 27, 2018
…to, but at lease I can work around some test failures

> AttributeError: AssertImportHook.is_package() method is missing but is required by Flask of PEP 302 import hooks.  If you do not use import hooks and you encounter this error please file a bug against Flask.

See also:
pallets/flask#569
dag/attest#136
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.

4 participants