mirror of https://github.com/pallets/flask.git
Implemented instance paths
This commit is contained in:
parent
63876614b6
commit
153ecbc920
5
CHANGES
5
CHANGES
|
@ -26,6 +26,11 @@ Relase date to be decided, codename to be chosen.
|
||||||
- Malformed JSON data will now trigger a bad request HTTP exception instead
|
- Malformed JSON data will now trigger a bad request HTTP exception instead
|
||||||
of a value error which usually would result in a 500 internal server
|
of a value error which usually would result in a 500 internal server
|
||||||
error if not handled. This is a backwards incompatible change.
|
error if not handled. This is a backwards incompatible change.
|
||||||
|
- Applications now not only have a root path where the resources and modules
|
||||||
|
are located but also an instane path which is the designated place to
|
||||||
|
drop files that are modified at runtime (uploads etc.). Also this is
|
||||||
|
conceptionally only instance depending and outside version control so it's
|
||||||
|
the perfect place to put configuration files etc.
|
||||||
|
|
||||||
Version 0.7.3
|
Version 0.7.3
|
||||||
-------------
|
-------------
|
||||||
|
|
79
flask/app.py
79
flask/app.py
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
@ -103,14 +104,33 @@ class Flask(_PackageBoundObject):
|
||||||
pick up SQL queries in `yourapplication.app` and not
|
pick up SQL queries in `yourapplication.app` and not
|
||||||
`yourapplication.views.frontend`)
|
`yourapplication.views.frontend`)
|
||||||
|
|
||||||
.. versionadded:: 0.5
|
.. versionadded:: 0.7
|
||||||
The `static_path` parameter was added.
|
The `static_url_path`, `static_folder`, and `template_folder`
|
||||||
|
parameters were added.
|
||||||
|
|
||||||
|
.. versionadded:: 0.8
|
||||||
|
The `instance_path` and `instance_relative_config` parameters were
|
||||||
|
added.
|
||||||
|
|
||||||
:param import_name: the name of the application package
|
:param import_name: the name of the application package
|
||||||
:param static_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 ``/static``.
|
static files on the web. Defaults to the name
|
||||||
This does not affect the folder the files are served
|
of the `static_folder` folder.
|
||||||
*from*.
|
:param static_folder: the folder with static files that should be served
|
||||||
|
at `static_url_path`. Defaults to the ``'static'``
|
||||||
|
folder in the root path of the application.
|
||||||
|
:param template_folder: the folder that contains the templates that should
|
||||||
|
be used by the application. Defaults to
|
||||||
|
``'templates'`` folder in the root path of the
|
||||||
|
application.
|
||||||
|
:param instance_path: An alternative instance path for the application.
|
||||||
|
By default the folder ``'instance'`` next to the
|
||||||
|
package or module is assumed to be the instance
|
||||||
|
path.
|
||||||
|
:param instance_relative_config: if set to `True` relative filenames
|
||||||
|
for loading the config are assumed to
|
||||||
|
be relative to the instance path instead
|
||||||
|
of the application root.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#: The class that is used for request objects. See :class:`~flask.Request`
|
#: The class that is used for request objects. See :class:`~flask.Request`
|
||||||
|
@ -238,7 +258,8 @@ class Flask(_PackageBoundObject):
|
||||||
session_interface = SecureCookieSessionInterface()
|
session_interface = SecureCookieSessionInterface()
|
||||||
|
|
||||||
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):
|
||||||
_PackageBoundObject.__init__(self, import_name,
|
_PackageBoundObject.__init__(self, import_name,
|
||||||
template_folder=template_folder)
|
template_folder=template_folder)
|
||||||
if static_path is not None:
|
if static_path is not None:
|
||||||
|
@ -251,11 +272,21 @@ class Flask(_PackageBoundObject):
|
||||||
self.static_url_path = static_url_path
|
self.static_url_path = static_url_path
|
||||||
if static_folder is not None:
|
if static_folder is not None:
|
||||||
self.static_folder = static_folder
|
self.static_folder = static_folder
|
||||||
|
if instance_path is None:
|
||||||
|
instance_path = self.auto_find_instance_path()
|
||||||
|
elif not os.path.isabs(instance_path):
|
||||||
|
raise ValueError('If an instance path is provided it must be '
|
||||||
|
'absolute. A relative path was given instead.')
|
||||||
|
|
||||||
|
#: Holds the path to the instance folder.
|
||||||
|
#:
|
||||||
|
#: .. versionadded:: 0.8
|
||||||
|
self.instance_path = instance_path
|
||||||
|
|
||||||
#: The configuration dictionary as :class:`Config`. This behaves
|
#: The configuration dictionary as :class:`Config`. This behaves
|
||||||
#: exactly like a regular dictionary but supports additional methods
|
#: exactly like a regular dictionary but supports additional methods
|
||||||
#: to load a config from files.
|
#: to load a config from files.
|
||||||
self.config = Config(self.root_path, self.default_config)
|
self.config = self.make_config(instance_relative_config)
|
||||||
|
|
||||||
# Prepare the deferred setup of the logger.
|
# Prepare the deferred setup of the logger.
|
||||||
self._logger = None
|
self._logger = None
|
||||||
|
@ -491,6 +522,38 @@ class Flask(_PackageBoundObject):
|
||||||
"""
|
"""
|
||||||
return self._got_first_request
|
return self._got_first_request
|
||||||
|
|
||||||
|
def make_config(self, instance_relative=False):
|
||||||
|
"""Used to create the config attribute by the Flask constructor.
|
||||||
|
The `instance_relative` parameter is passed in from the constructor
|
||||||
|
of Flask (there named `instance_relative_config`) and indicates if
|
||||||
|
the config should be relative to the instance path or the root path
|
||||||
|
of the application.
|
||||||
|
|
||||||
|
.. versionadded:: 0.8
|
||||||
|
"""
|
||||||
|
root_path = self.root_path
|
||||||
|
if instance_relative:
|
||||||
|
root_path = self.instance_path
|
||||||
|
return Config(root_path, self.default_config)
|
||||||
|
|
||||||
|
def auto_find_instance_path(self):
|
||||||
|
"""Tries to locate the instance path if it was not provided to the
|
||||||
|
constructor of the application class. It will basically calculate
|
||||||
|
the path to a folder named ``instance`` next to your main file or
|
||||||
|
the package.
|
||||||
|
|
||||||
|
.. versionadded:: 0.8
|
||||||
|
"""
|
||||||
|
root_mod = sys.modules[self.import_name.split('.')[0]]
|
||||||
|
instance_path = None
|
||||||
|
if hasattr(root_mod, '__path__'):
|
||||||
|
package_dir = os.path.dirname(root_mod.__file__)
|
||||||
|
instance_path = os.path.join(package_dir, os.path.pardir)
|
||||||
|
else:
|
||||||
|
instance_path = os.path.dirname(root_mod.__file__)
|
||||||
|
basedir = os.path.normpath(os.path.abspath(instance_path))
|
||||||
|
return os.path.join(basedir, 'instance')
|
||||||
|
|
||||||
def create_jinja_environment(self):
|
def create_jinja_environment(self):
|
||||||
"""Creates the Jinja2 environment based on :attr:`jinja_options`
|
"""Creates the Jinja2 environment based on :attr:`jinja_options`
|
||||||
and :meth:`select_jinja_autoescape`. Since 0.7 this also adds
|
and :meth:`select_jinja_autoescape`. Since 0.7 this also adds
|
||||||
|
|
|
@ -1005,6 +1005,24 @@ class BasicFunctionalityTestCase(unittest.TestCase):
|
||||||
rv = c.post('/foo', data={}, follow_redirects=True)
|
rv = c.post('/foo', data={}, follow_redirects=True)
|
||||||
self.assertEqual(rv.data, 'success')
|
self.assertEqual(rv.data, 'success')
|
||||||
|
|
||||||
|
def test_basic_instance_paths(self):
|
||||||
|
here = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
self.assertEqual(app.instance_path, os.path.join(here, 'instance'))
|
||||||
|
|
||||||
|
app = flask.Flask(__name__, instance_path=here)
|
||||||
|
self.assertEqual(app.instance_path, here)
|
||||||
|
|
||||||
|
try:
|
||||||
|
flask.Flask(__name__, instance_path='instance')
|
||||||
|
except ValueError, e:
|
||||||
|
self.assert_('must be absolute' in str(e))
|
||||||
|
else:
|
||||||
|
self.fail('Expected value error')
|
||||||
|
|
||||||
|
from blueprintapp import app
|
||||||
|
self.assertEqual(app.instance_path, os.path.join(here, 'instance'))
|
||||||
|
|
||||||
|
|
||||||
class JSONTestCase(unittest.TestCase):
|
class JSONTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue