From 94f436013792249a9bb7206c2868d4c6c21fd887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Neuha=CC=88user?= Date: Tue, 13 Aug 2013 15:53:58 +0200 Subject: [PATCH] Explain is_package AttributeError in find_package When a PEP 302 import hook is used that doesn't implement .is_package() an AttributeError is raised. This looks like a bug in Flask. This change fixes that problem in the sense that it explains, that the AttributeError is intentional. --- CHANGES | 3 +++ flask/helpers.py | 9 +++++++-- flask/testsuite/config.py | 13 +++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 89ef41d7..9e23bcfb 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,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/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()