Several people have noted issues when installing/updating Flask extensions that use the new style flask.ext path, specifically in Google AppEngine environments.
Relevant discussion and troubleshooting here: thadeusb/flask-cache#38
What is happening (my understanding):
Any assistance is highly appreciated.
To cause the problem, the extension must be a package, and attempt to import another file from within that package.
If an import statement in the init.py file is defined as
from flask.ext.mything.util import some_useful_function
imports within util will fail.
This "can" be fixed from the extension by using relative imports instead of absolute. Such as:
from .util import some_useful_function
will cause the extension to load properly.
However, the proper thing for Flask to do is to not raise an exception, it should return None as is required in the python documentation -> http://docs.python.org/2/library/sys.html#sys.meta_path (The method returns None if the module cannot be found, else returns a loader.)
Has anyone tried using the experimental devappserver2 (http://code.google.com/p/appengine-devappserver2-experiment/) and see if it still has the same issues?
I think that is a GAE issue. If someone can reproduce that without GAE please reopen that ticket. The fix for GAE would be to not use the rename imports for the actual module names.
There is a GAE issue open for this here - http://goo.gl/rrCGh
I fail to see how this is a GAE issue when Flask's meta path importer is doing the wrong thing. Flask would fail in other systems that added their own importers to sys.meta_path.
A list of finder objects that have their find_module() methods called to see if one of the objects can find the module to be imported. The find_module() method is called at least with the absolute name of the module being imported. If the module to be imported is contained in package then the parent package’s path attribute is passed in as a second argument. The method returns None if the module cannot be found, else returns a loader.
sys.meta_path is searched before any implicit default finders or sys.path.
See PEP 302 for the original specification.
Flask's find_module() method from the ExtensionImporter behaves as it should. Here it is:
def find_module(self, fullname, path=None):
Seems like it's returning a loader (or None, if the prefix doesn't match) as the documentation says it should. By the way, the documentation references the PEP because there is more information in there. Here is a more complete version of what should happen:
As far as I can see, the only place where Flask doesn't meet PEP 302 is in load_module() setting the attributes like __file__ and such explicitly which is probably OK since it uses __import__() to perform the actual import.