diff --git a/CHANGES b/CHANGES index 912c6aaf..8699718c 100644 --- a/CHANGES +++ b/CHANGES @@ -21,6 +21,9 @@ Version 0.10.2 (bugfix release, release date to be announced) - Fixed broken `test_appcontext_signals()` test case. +- Raise an :exc:`AttributeError` in :func:`flask.helpers.find_package` with a + useful message explaining why it is raised when a PEP 302 import hook is used + without an `is_package()` method. Version 0.10.1 -------------- diff --git a/docs/api.rst b/docs/api.rst index 75295b1e..5faccc30 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -350,7 +350,7 @@ JSON Support Flask uses ``simplejson`` for the JSON implementation. Since simplejson is provided both by the standard library as well as extension Flask will try simplejson first and then fall back to the stdlib json module. On top -of that it will delegate access to the current application's JSOn encoders +of that it will delegate access to the current application's JSON encoders and decoders for easier customization. So for starters instead of doing:: diff --git a/docs/deploying/fastcgi.rst b/docs/deploying/fastcgi.rst index 1ac1f505..430a9748 100644 --- a/docs/deploying/fastcgi.rst +++ b/docs/deploying/fastcgi.rst @@ -149,6 +149,7 @@ A basic FastCGI configuration for lighttpd looks like that:: url.rewrite-once = ( "^(/static($|/.*))$" => "$1", "^(/.*)$" => "/yourapplication.fcgi$1" + ) Remember to enable the FastCGI, alias and rewrite modules. This configuration binds the application to `/yourapplication`. If you want the application to diff --git a/flask/app.py b/flask/app.py index 805dc166..ef2af73c 100644 --- a/flask/app.py +++ b/flask/app.py @@ -1547,7 +1547,7 @@ class Flask(_PackageBoundObject): :class:`tuple` A tuple in the form ``(response, status, headers)`` where `response` is any of the types defined here, `status` is a string - or an integer and `headers` is a list of + or an integer and `headers` is a list or a dictionary with header values. ======================= =========================================== diff --git a/flask/helpers.py b/flask/helpers.py index 1e7c87f0..e59f7d3c 100644 --- a/flask/helpers.py +++ b/flask/helpers.py @@ -679,8 +679,13 @@ def find_package(import_name): filename = sys.modules[import_name].__file__ package_path = os.path.abspath(os.path.dirname(filename)) # package_path ends with __init__.py for a package - if loader.is_package(root_mod_name): - package_path = os.path.dirname(package_path) + if hasattr(loader, 'is_package'): + if loader.is_package(root_mod_name): + package_path = os.path.dirname(package_path) + else: + raise AttributeError( + ('%s.is_package() method is missing but is ' + 'required by Flask of PEP 302 import hooks') % loader.__class__.__name__) site_parent, site_folder = os.path.split(package_path) py_prefix = os.path.abspath(sys.prefix) diff --git a/flask/testsuite/config.py b/flask/testsuite/config.py index 477c6db9..13e14d85 100644 --- a/flask/testsuite/config.py +++ b/flask/testsuite/config.py @@ -16,6 +16,7 @@ import pkgutil import unittest from contextlib import contextmanager from flask.testsuite import FlaskTestCase +from flask._compat import PY2 # config keys used for the ConfigTestCase @@ -291,6 +292,18 @@ class InstanceTestCase(FlaskTestCase): if 'site_egg' in sys.modules: del sys.modules['site_egg'] + if PY2: + def test_meta_path_loader_without_is_package(self): + class Loader(object): + def find_module(self, name): + return self + sys.meta_path.append(Loader()) + try: + with self.assert_raises(AttributeError): + flask.Flask(__name__) + finally: + sys.meta_path.pop() + def suite(): suite = unittest.TestSuite()