Browse Source

Better support for namespace packages.

pull/1019/head
Armin Ronacher 11 years ago
parent
commit
d4b3d16c14
  1. 2
      CHANGES
  2. 14
      flask/app.py
  3. 6
      flask/blueprints.py
  4. 22
      flask/helpers.py

2
CHANGES

@ -24,6 +24,8 @@ Version 1.0
templates will be reloaded only if the application is running in templates will be reloaded only if the application is running in
debug mode. For higher performance it’s possible to disable that. debug mode. For higher performance it’s possible to disable that.
- Added a workaround for a limitation in Python 3.3's namespace loader. - Added a workaround for a limitation in Python 3.3's namespace loader.
- Added support for explicit root paths when using Python 3.3's namespace
packages.
Version 0.10.2 Version 0.10.2
-------------- --------------

14
flask/app.py

@ -118,6 +118,9 @@ class Flask(_PackageBoundObject):
The `instance_path` and `instance_relative_config` parameters were The `instance_path` and `instance_relative_config` parameters were
added. added.
.. versionadded:: 1.0
The `root_path` parameter was added.
:param import_name: the name of the application package :param import_name: the name of the application package
:param static_url_path: can be used to specify a different path for the :param static_url_path: can be used to specify a different path for the
static files on the web. Defaults to the name static files on the web. Defaults to the name
@ -137,6 +140,11 @@ class Flask(_PackageBoundObject):
for loading the config are assumed to for loading the config are assumed to
be relative to the instance path instead be relative to the instance path instead
of the application root. of the application root.
:param root_path: Flask by default will automatically calculate the path
to the root of the application. In certain situations
this cannot be achieved (for instance if the package
is a Python 3 namespace package) and needs to be
manually defined.
""" """
#: The class that is used for request objects. See :class:`~flask.Request` #: The class that is used for request objects. See :class:`~flask.Request`
@ -327,9 +335,11 @@ class Flask(_PackageBoundObject):
def __init__(self, import_name, static_path=None, static_url_path=None, def __init__(self, import_name, static_path=None, static_url_path=None,
static_folder='static', template_folder='templates', static_folder='static', template_folder='templates',
instance_path=None, instance_relative_config=False): instance_path=None, instance_relative_config=False,
root_path=None):
_PackageBoundObject.__init__(self, import_name, _PackageBoundObject.__init__(self, import_name,
template_folder=template_folder) template_folder=template_folder,
root_path=root_path)
if static_path is not None: if static_path is not None:
from warnings import warn from warnings import warn
warn(DeprecationWarning('static_path is now called ' warn(DeprecationWarning('static_path is now called '

6
flask/blueprints.py

@ -91,8 +91,10 @@ class Blueprint(_PackageBoundObject):
def __init__(self, name, import_name, static_folder=None, def __init__(self, name, import_name, static_folder=None,
static_url_path=None, template_folder=None, static_url_path=None, template_folder=None,
url_prefix=None, subdomain=None, url_defaults=None): url_prefix=None, subdomain=None, url_defaults=None,
_PackageBoundObject.__init__(self, import_name, template_folder) root_path=None):
_PackageBoundObject.__init__(self, import_name, template_folder,
root_path=root_path)
self.name = name self.name = name
self.url_prefix = url_prefix self.url_prefix = url_prefix
self.subdomain = subdomain self.subdomain = subdomain

22
flask/helpers.py

@ -650,7 +650,20 @@ def get_root_path(import_name):
else: else:
# Fall back to imports. # Fall back to imports.
__import__(import_name) __import__(import_name)
filepath = sys.modules[import_name].__file__ mod = sys.modules[import_name]
filepath = getattr(mod, '__file__', None)
# If we don't have a filepath it might be because we are a
# namespace package. In this case we pick the root path from the
# first module that is contained in our package.
if filepath is None:
raise RuntimeError('No root path can be found for the provided '
'module "%s". This can happen because the '
'module came from an import hook that does '
'not provide file name information or because '
'it\'s a namespace package. In this case '
'the root path needs to be explictly '
'provided.' % import_name)
# filepath is import_name.py for a module, or __init__.py for a package. # filepath is import_name.py for a module, or __init__.py for a package.
return os.path.dirname(os.path.abspath(filepath)) return os.path.dirname(os.path.abspath(filepath))
@ -762,7 +775,7 @@ class locked_cached_property(object):
class _PackageBoundObject(object): class _PackageBoundObject(object):
def __init__(self, import_name, template_folder=None): def __init__(self, import_name, template_folder=None, root_path=None):
#: The name of the package or module. Do not change this once #: The name of the package or module. Do not change this once
#: it was set by the constructor. #: it was set by the constructor.
self.import_name = import_name self.import_name = import_name
@ -771,8 +784,11 @@ class _PackageBoundObject(object):
#: exposed. #: exposed.
self.template_folder = template_folder self.template_folder = template_folder
if root_path is None:
root_path = get_root_path(self.import_name)
#: Where is the app root located? #: Where is the app root located?
self.root_path = get_root_path(self.import_name) self.root_path = root_path
self._static_folder = None self._static_folder = None
self._static_url_path = None self._static_url_path = None

Loading…
Cancel
Save