forked from orbit-oss/flask
Merge branch 'master' of github.com:mitsuhiko/flask
This commit is contained in:
commit
5fd81f702c
20 changed files with 163 additions and 58 deletions
4
CHANGES
4
CHANGES
|
|
@ -21,6 +21,10 @@ Version 1.0
|
||||||
- Added :attr:`flask.Flask.config_class`.
|
- Added :attr:`flask.Flask.config_class`.
|
||||||
- Added :meth:`flask.config.Config.get_namespace`.
|
- Added :meth:`flask.config.Config.get_namespace`.
|
||||||
|
|
||||||
|
- Added ``TEMPLATES_AUTO_RELOAD`` config key. If disabled the
|
||||||
|
templates will be reloaded only if the application is running in
|
||||||
|
debug mode. For higher performance it’s possible to disable that.
|
||||||
|
|
||||||
Version 0.10.2
|
Version 0.10.2
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -202,3 +202,18 @@ you can use relative redirects by prefixing the endpoint with a dot only::
|
||||||
|
|
||||||
This will link to ``admin.index`` for instance in case the current request
|
This will link to ``admin.index`` for instance in case the current request
|
||||||
was dispatched to any other admin blueprint endpoint.
|
was dispatched to any other admin blueprint endpoint.
|
||||||
|
|
||||||
|
Error Handlers
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Blueprints support the errorhandler decorator just like the :class:`Flask`
|
||||||
|
application object, so it is easy to make Blueprint-specific custom error
|
||||||
|
pages.
|
||||||
|
|
||||||
|
Here is an example for a "404 Page Not Found" exception::
|
||||||
|
|
||||||
|
@simple_page.errorhandler(404)
|
||||||
|
def page_not_found(e):
|
||||||
|
return render_template('pages/404.html')
|
||||||
|
|
||||||
|
More information on error handling see :ref:`errorpages`.
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,12 @@ The following configuration values are used internally by Flask:
|
||||||
if they are not requested by an
|
if they are not requested by an
|
||||||
XMLHttpRequest object (controlled by
|
XMLHttpRequest object (controlled by
|
||||||
the ``X-Requested-With`` header)
|
the ``X-Requested-With`` header)
|
||||||
|
``TEMPLATES_AUTO_RELOAD`` Flask checks if template was modified each
|
||||||
|
time it is requested and reloads it if
|
||||||
|
necessary. But disk I/O is costly and it may
|
||||||
|
be viable to disable this feature by setting
|
||||||
|
this key to ``False``. This option does not
|
||||||
|
affect debug mode.
|
||||||
================================= =========================================
|
================================= =========================================
|
||||||
|
|
||||||
.. admonition:: More on ``SERVER_NAME``
|
.. admonition:: More on ``SERVER_NAME``
|
||||||
|
|
@ -222,6 +228,9 @@ The following configuration values are used internally by Flask:
|
||||||
.. versionadded:: 1.0
|
.. versionadded:: 1.0
|
||||||
``SESSION_REFRESH_EACH_REQUEST``
|
``SESSION_REFRESH_EACH_REQUEST``
|
||||||
|
|
||||||
|
.. versionadded:: 1.0
|
||||||
|
``TEMPLATES_AUTO_RELOAD``
|
||||||
|
|
||||||
Configuring from Files
|
Configuring from Files
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
Flask depends on two external libraries, `Werkzeug
|
Flask depends on some external libraries, like `Werkzeug
|
||||||
<http://werkzeug.pocoo.org/>`_ and `Jinja2 <http://jinja.pocoo.org/2/>`_.
|
<http://werkzeug.pocoo.org/>`_ and `Jinja2 <http://jinja.pocoo.org/2/>`_.
|
||||||
Werkzeug is a toolkit for WSGI, the standard Python interface between web
|
Werkzeug is a toolkit for WSGI, the standard Python interface between web
|
||||||
applications and a variety of servers for both development and deployment.
|
applications and a variety of servers for both development and deployment.
|
||||||
|
|
@ -13,7 +13,7 @@ So how do you get all that on your computer quickly? There are many ways you
|
||||||
could do that, but the most kick-ass method is virtualenv, so let's have a look
|
could do that, but the most kick-ass method is virtualenv, so let's have a look
|
||||||
at that first.
|
at that first.
|
||||||
|
|
||||||
You will need Python 2.6 or higher to get started, so be sure to have an
|
You will need Python 2.6 or newer to get started, so be sure to have an
|
||||||
up-to-date Python 2.x installation. For using Flask with Python 3 have a
|
up-to-date Python 2.x installation. For using Flask with Python 3 have a
|
||||||
look at :ref:`python3-support`.
|
look at :ref:`python3-support`.
|
||||||
|
|
||||||
|
|
@ -67,7 +67,7 @@ folder within::
|
||||||
$ cd myproject
|
$ cd myproject
|
||||||
$ virtualenv venv
|
$ virtualenv venv
|
||||||
New python executable in venv/bin/python
|
New python executable in venv/bin/python
|
||||||
Installing distribute............done.
|
Installing setuptools, pip............done.
|
||||||
|
|
||||||
Now, whenever you want to work on a project, you only have to activate the
|
Now, whenever you want to work on a project, you only have to activate the
|
||||||
corresponding environment. On OS X and Linux, do the following::
|
corresponding environment. On OS X and Linux, do the following::
|
||||||
|
|
@ -113,9 +113,9 @@ Get the git checkout in a new virtualenv and run in development mode::
|
||||||
$ git clone http://github.com/mitsuhiko/flask.git
|
$ git clone http://github.com/mitsuhiko/flask.git
|
||||||
Initialized empty Git repository in ~/dev/flask/.git/
|
Initialized empty Git repository in ~/dev/flask/.git/
|
||||||
$ cd flask
|
$ cd flask
|
||||||
$ virtualenv venv --distribute
|
$ virtualenv venv
|
||||||
New python executable in venv/bin/python
|
New python executable in venv/bin/python
|
||||||
Installing distribute............done.
|
Installing setuptools, pip............done.
|
||||||
$ . venv/bin/activate
|
$ . venv/bin/activate
|
||||||
$ python setup.py develop
|
$ python setup.py develop
|
||||||
...
|
...
|
||||||
|
|
@ -129,45 +129,53 @@ To just get the development version without git, do this instead::
|
||||||
|
|
||||||
$ mkdir flask
|
$ mkdir flask
|
||||||
$ cd flask
|
$ cd flask
|
||||||
$ virtualenv venv --distribute
|
$ virtualenv venv
|
||||||
$ . venv/bin/activate
|
$ . venv/bin/activate
|
||||||
New python executable in venv/bin/python
|
New python executable in venv/bin/python
|
||||||
Installing distribute............done.
|
Installing setuptools, pip............done.
|
||||||
$ pip install Flask==dev
|
$ pip install Flask==dev
|
||||||
...
|
...
|
||||||
Finished processing dependencies for Flask==dev
|
Finished processing dependencies for Flask==dev
|
||||||
|
|
||||||
.. _windows-easy-install:
|
.. _windows-easy-install:
|
||||||
|
|
||||||
`pip` and `distribute` on Windows
|
`pip` and `setuptools` on Windows
|
||||||
-----------------------------------
|
---------------------------------
|
||||||
|
|
||||||
On Windows, installation of `easy_install` is a little bit trickier, but still
|
Sometimes getting the standard "Python packaging tools" like *pip*, *setuptools*
|
||||||
quite easy. The easiest way to do it is to download the
|
and *virtualenv* can be a little trickier, but nothing very hard. The two crucial
|
||||||
`distribute_setup.py`_ file and run it. The easiest way to run the file is to
|
packages you will need are setuptools and pip - these will let you install
|
||||||
open your downloads folder and double-click on the file.
|
anything else (like virtualenv). Fortunately there are two "bootstrap scripts"
|
||||||
|
you can run to install either.
|
||||||
|
|
||||||
Next, add the `easy_install` command and other Python scripts to the
|
If you don't currently have either, then `get-pip.py` will install both for you
|
||||||
command search path, by adding your Python installation's Scripts folder
|
(you won't need to run ez_setup.py).
|
||||||
to the `PATH` environment variable. To do that, right-click on the
|
|
||||||
"Computer" icon on the Desktop or in the Start menu, and choose "Properties".
|
|
||||||
Then click on "Advanced System settings" (in Windows XP, click on the
|
|
||||||
"Advanced" tab instead). Then click on the "Environment variables" button.
|
|
||||||
Finally, double-click on the "Path" variable in the "System variables" section,
|
|
||||||
and add the path of your Python interpreter's Scripts folder. Be sure to
|
|
||||||
delimit it from existing values with a semicolon. Assuming you are using
|
|
||||||
Python 2.7 on the default path, add the following value::
|
|
||||||
|
|
||||||
|
`get-pip.py`_
|
||||||
|
|
||||||
;C:\Python27\Scripts
|
To install the latest setuptools, you can use its bootstrap file:
|
||||||
|
|
||||||
And you are done! To check that it worked, open the Command Prompt and execute
|
`ez_setup.py`_
|
||||||
``easy_install``. If you have User Account Control enabled on Windows Vista or
|
|
||||||
Windows 7, it should prompt you for administrator privileges.
|
|
||||||
|
|
||||||
Now that you have ``easy_install``, you can use it to install ``pip``::
|
Either should be double-clickable once you download them. If you already have pip,
|
||||||
|
you can upgrade them by running::
|
||||||
|
|
||||||
> easy_install pip
|
> pip install --upgrade pip setuptools
|
||||||
|
|
||||||
|
Most often, once you pull up a command prompt you want to be able to type ``pip``
|
||||||
|
and ``python`` which will run those things, but this might not automatically happen
|
||||||
|
on Windows, because it doesn't know where those executables are (give either a try!).
|
||||||
|
|
||||||
.. _distribute_setup.py: http://python-distribute.org/distribute_setup.py
|
To fix this, you should be able to navigate to your Python install directory
|
||||||
|
(e.g ``C:\Python27``), then go to ``Tools``, then ``Scripts``; then find the
|
||||||
|
``win_add2path.py`` file and run that. Open a **new** Command Prompt and
|
||||||
|
check that you can now just type ``python`` to bring up the interpreter.
|
||||||
|
|
||||||
|
Finally, to install `virtualenv`_, you can simply run::
|
||||||
|
|
||||||
|
> pip install virtualenv
|
||||||
|
|
||||||
|
Then you can be off on your way following the installation instructions above.
|
||||||
|
|
||||||
|
.. _get-pip.py: https://raw.github.com/pypa/pip/master/contrib/get-pip.py
|
||||||
|
.. _ez_setup.py: https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,8 @@ you basically only need the engine::
|
||||||
Then you can either declare the tables in your code like in the examples
|
Then you can either declare the tables in your code like in the examples
|
||||||
above, or automatically load them::
|
above, or automatically load them::
|
||||||
|
|
||||||
|
from sqlalchemy import Table
|
||||||
|
|
||||||
users = Table('users', metadata, autoload=True)
|
users = Table('users', metadata, autoload=True)
|
||||||
|
|
||||||
To insert data you can use the `insert` method. We have to get a
|
To insert data you can use the `insert` method. We have to get a
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Unicode in Flask
|
Unicode in Flask
|
||||||
================
|
================
|
||||||
|
|
||||||
Flask like Jinja2 and Werkzeug is totally Unicode based when it comes to
|
Flask, like Jinja2 and Werkzeug, is totally Unicode based when it comes to
|
||||||
text. Not only these libraries, also the majority of web related Python
|
text. Not only these libraries, also the majority of web related Python
|
||||||
libraries that deal with text. If you don't know Unicode so far, you
|
libraries that deal with text. If you don't know Unicode so far, you
|
||||||
should probably read `The Absolute Minimum Every Software Developer
|
should probably read `The Absolute Minimum Every Software Developer
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,5 @@ drop table if exists entries;
|
||||||
create table entries (
|
create table entries (
|
||||||
id integer primary key autoincrement,
|
id integer primary key autoincrement,
|
||||||
title text not null,
|
title text not null,
|
||||||
text text not null
|
'text' text not null
|
||||||
);
|
);
|
||||||
|
|
|
||||||
12
flask/app.py
12
flask/app.py
|
|
@ -305,6 +305,7 @@ class Flask(_PackageBoundObject):
|
||||||
'JSON_AS_ASCII': True,
|
'JSON_AS_ASCII': True,
|
||||||
'JSON_SORT_KEYS': True,
|
'JSON_SORT_KEYS': True,
|
||||||
'JSONIFY_PRETTYPRINT_REGULAR': True,
|
'JSONIFY_PRETTYPRINT_REGULAR': True,
|
||||||
|
'TEMPLATES_AUTO_RELOAD': True,
|
||||||
})
|
})
|
||||||
|
|
||||||
#: The rule object to use for URL rules created. This is used by
|
#: The rule object to use for URL rules created. This is used by
|
||||||
|
|
@ -655,10 +656,16 @@ class Flask(_PackageBoundObject):
|
||||||
this function to customize the behavior.
|
this function to customize the behavior.
|
||||||
|
|
||||||
.. versionadded:: 0.5
|
.. versionadded:: 0.5
|
||||||
|
.. versionchanged:: 1.0
|
||||||
|
``Environment.auto_reload`` set in accordance with
|
||||||
|
``TEMPLATES_AUTO_RELOAD`` configuration option.
|
||||||
"""
|
"""
|
||||||
options = dict(self.jinja_options)
|
options = dict(self.jinja_options)
|
||||||
if 'autoescape' not in options:
|
if 'autoescape' not in options:
|
||||||
options['autoescape'] = self.select_jinja_autoescape
|
options['autoescape'] = self.select_jinja_autoescape
|
||||||
|
if 'auto_reload' not in options:
|
||||||
|
options['auto_reload'] = self.debug \
|
||||||
|
or self.config['TEMPLATES_AUTO_RELOAD']
|
||||||
rv = Environment(self, **options)
|
rv = Environment(self, **options)
|
||||||
rv.globals.update(
|
rv.globals.update(
|
||||||
url_for=url_for,
|
url_for=url_for,
|
||||||
|
|
@ -1070,6 +1077,11 @@ class Flask(_PackageBoundObject):
|
||||||
The first `None` refers to the active blueprint. If the error
|
The first `None` refers to the active blueprint. If the error
|
||||||
handler should be application wide `None` shall be used.
|
handler should be application wide `None` shall be used.
|
||||||
|
|
||||||
|
.. versionadded:: 0.7
|
||||||
|
Use :meth:`register_error_handler` instead of modifying
|
||||||
|
:attr:`error_handler_spec` directly, for application wide error
|
||||||
|
handlers.
|
||||||
|
|
||||||
.. versionadded:: 0.7
|
.. versionadded:: 0.7
|
||||||
One can now additionally also register custom exception types
|
One can now additionally also register custom exception types
|
||||||
that do not necessarily have to be a subclass of the
|
that do not necessarily have to be a subclass of the
|
||||||
|
|
|
||||||
|
|
@ -399,3 +399,14 @@ class Blueprint(_PackageBoundObject):
|
||||||
self.name, code_or_exception, f))
|
self.name, code_or_exception, f))
|
||||||
return f
|
return f
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
def register_error_handler(self, code_or_exception, f):
|
||||||
|
"""Non-decorator version of the :meth:`errorhandler` error attach
|
||||||
|
function, akin to the :meth:`~flask.Flask.register_error_handler`
|
||||||
|
application-wide function of the :class:`~flask.Flask` object but
|
||||||
|
for error handlers limited to this blueprint.
|
||||||
|
|
||||||
|
.. versionadded:: 0.11
|
||||||
|
"""
|
||||||
|
self.record_once(lambda s: s.app._register_error_handler(
|
||||||
|
self.name, code_or_exception, f))
|
||||||
|
|
|
||||||
|
|
@ -199,16 +199,16 @@ def url_for(endpoint, **values):
|
||||||
For more information, head over to the :ref:`Quickstart <url-building>`.
|
For more information, head over to the :ref:`Quickstart <url-building>`.
|
||||||
|
|
||||||
To integrate applications, :class:`Flask` has a hook to intercept URL build
|
To integrate applications, :class:`Flask` has a hook to intercept URL build
|
||||||
errors through :attr:`Flask.build_error_handler`. The `url_for` function
|
errors through :attr:`Flask.url_build_error_handlers`. The `url_for`
|
||||||
results in a :exc:`~werkzeug.routing.BuildError` when the current app does
|
function results in a :exc:`~werkzeug.routing.BuildError` when the current
|
||||||
not have a URL for the given endpoint and values. When it does, the
|
app does not have a URL for the given endpoint and values. When it does, the
|
||||||
:data:`~flask.current_app` calls its :attr:`~Flask.build_error_handler` if
|
:data:`~flask.current_app` calls its :attr:`~Flask.url_build_error_handlers` if
|
||||||
it is not `None`, which can return a string to use as the result of
|
it is not `None`, which can return a string to use as the result of
|
||||||
`url_for` (instead of `url_for`'s default to raise the
|
`url_for` (instead of `url_for`'s default to raise the
|
||||||
:exc:`~werkzeug.routing.BuildError` exception) or re-raise the exception.
|
:exc:`~werkzeug.routing.BuildError` exception) or re-raise the exception.
|
||||||
An example::
|
An example::
|
||||||
|
|
||||||
def external_url_handler(error, endpoint, **values):
|
def external_url_handler(error, endpoint, values):
|
||||||
"Looks up an external URL when `url_for` cannot build a URL."
|
"Looks up an external URL when `url_for` cannot build a URL."
|
||||||
# This is an example of hooking the build_error_handler.
|
# This is an example of hooking the build_error_handler.
|
||||||
# Here, lookup_url is some utility function you've built
|
# Here, lookup_url is some utility function you've built
|
||||||
|
|
@ -225,10 +225,10 @@ def url_for(endpoint, **values):
|
||||||
# url_for will use this result, instead of raising BuildError.
|
# url_for will use this result, instead of raising BuildError.
|
||||||
return url
|
return url
|
||||||
|
|
||||||
app.build_error_handler = external_url_handler
|
app.url_build_error_handlers.append(external_url_handler)
|
||||||
|
|
||||||
Here, `error` is the instance of :exc:`~werkzeug.routing.BuildError`, and
|
Here, `error` is the instance of :exc:`~werkzeug.routing.BuildError`, and
|
||||||
`endpoint` and `**values` are the arguments passed into `url_for`. Note
|
`endpoint` and `values` are the arguments passed into `url_for`. Note
|
||||||
that this is for building URLs outside the current application, and not for
|
that this is for building URLs outside the current application, and not for
|
||||||
handling 404 NotFound errors.
|
handling 404 NotFound errors.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ except ImportError:
|
||||||
from itsdangerous import json as _json
|
from itsdangerous import json as _json
|
||||||
|
|
||||||
|
|
||||||
# figure out if simplejson escapes slashes. This behavior was changed
|
# Figure out if simplejson escapes slashes. This behavior was changed
|
||||||
# from one version to another without reason.
|
# from one version to another without reason.
|
||||||
_slash_escape = '\\/' not in _json.dumps('/')
|
_slash_escape = '\\/' not in _json.dumps('/')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -223,7 +223,7 @@ class SessionInterface(object):
|
||||||
|
|
||||||
def get_cookie_path(self, app):
|
def get_cookie_path(self, app):
|
||||||
"""Returns the path for which the cookie should be valid. The
|
"""Returns the path for which the cookie should be valid. The
|
||||||
default implementation uses the value from the SESSION_COOKIE_PATH``
|
default implementation uses the value from the ``SESSION_COOKIE_PATH``
|
||||||
config var if it's set, and falls back to ``APPLICATION_ROOT`` or
|
config var if it's set, and falls back to ``APPLICATION_ROOT`` or
|
||||||
uses ``/`` if it's `None`.
|
uses ``/`` if it's `None`.
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -37,12 +37,12 @@ except ImportError:
|
||||||
temporarily_connected_to = connected_to = _fail
|
temporarily_connected_to = connected_to = _fail
|
||||||
del _fail
|
del _fail
|
||||||
|
|
||||||
# the namespace for code signals. If you are not flask code, do
|
# The namespace for code signals. If you are not flask code, do
|
||||||
# not put signals in here. Create your own namespace instead.
|
# not put signals in here. Create your own namespace instead.
|
||||||
_signals = Namespace()
|
_signals = Namespace()
|
||||||
|
|
||||||
|
|
||||||
# core signals. For usage examples grep the sourcecode or consult
|
# Core signals. For usage examples grep the sourcecode or consult
|
||||||
# the API documentation in docs/api.rst as well as docs/signals.rst
|
# the API documentation in docs/api.rst as well as docs/signals.rst
|
||||||
template_rendered = _signals.signal('template-rendered')
|
template_rendered = _signals.signal('template-rendered')
|
||||||
request_started = _signals.signal('request-started')
|
request_started = _signals.signal('request-started')
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,39 @@ class BlueprintTestCase(FlaskTestCase):
|
||||||
self.assert_equal(c.get('/backend-no').data, b'backend says no')
|
self.assert_equal(c.get('/backend-no').data, b'backend says no')
|
||||||
self.assert_equal(c.get('/what-is-a-sideend').data, b'application itself says no')
|
self.assert_equal(c.get('/what-is-a-sideend').data, b'application itself says no')
|
||||||
|
|
||||||
|
def test_blueprint_specific_user_error_handling(self):
|
||||||
|
class MyDecoratorException(Exception):
|
||||||
|
pass
|
||||||
|
class MyFunctionException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
blue = flask.Blueprint('blue', __name__)
|
||||||
|
|
||||||
|
@blue.errorhandler(MyDecoratorException)
|
||||||
|
def my_decorator_exception_handler(e):
|
||||||
|
self.assert_true(isinstance(e, MyDecoratorException))
|
||||||
|
return 'boom'
|
||||||
|
|
||||||
|
def my_function_exception_handler(e):
|
||||||
|
self.assert_true(isinstance(e, MyFunctionException))
|
||||||
|
return 'bam'
|
||||||
|
blue.register_error_handler(MyFunctionException, my_function_exception_handler)
|
||||||
|
|
||||||
|
@blue.route('/decorator')
|
||||||
|
def blue_deco_test():
|
||||||
|
raise MyDecoratorException()
|
||||||
|
@blue.route('/function')
|
||||||
|
def blue_func_test():
|
||||||
|
raise MyFunctionException()
|
||||||
|
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
app.register_blueprint(blue)
|
||||||
|
|
||||||
|
c = app.test_client()
|
||||||
|
|
||||||
|
self.assert_equal(c.get('/decorator').data, b'boom')
|
||||||
|
self.assert_equal(c.get('/function').data, b'bam')
|
||||||
|
|
||||||
def test_blueprint_url_definitions(self):
|
def test_blueprint_url_definitions(self):
|
||||||
bp = flask.Blueprint('test', __name__)
|
bp = flask.Blueprint('test', __name__)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,9 @@ class ExtImportHookTestCase(FlaskTestCase):
|
||||||
next = tb.tb_next.tb_next
|
next = tb.tb_next.tb_next
|
||||||
if not PY2:
|
if not PY2:
|
||||||
next = next.tb_next
|
next = next.tb_next
|
||||||
self.assert_in('flask_broken/__init__.py', next.tb_frame.f_code.co_filename)
|
|
||||||
|
import os.path
|
||||||
|
self.assert_in(os.path.join('flask_broken', '__init__.py'), next.tb_frame.f_code.co_filename)
|
||||||
|
|
||||||
|
|
||||||
def suite():
|
def suite():
|
||||||
|
|
|
||||||
|
|
@ -269,7 +269,7 @@ class SendfileTestCase(FlaskTestCase):
|
||||||
app = flask.Flask(__name__)
|
app = flask.Flask(__name__)
|
||||||
with catch_warnings() as captured:
|
with catch_warnings() as captured:
|
||||||
with app.test_request_context():
|
with app.test_request_context():
|
||||||
f = open(os.path.join(app.root_path, 'static/index.html'))
|
f = open(os.path.join(app.root_path, 'static/index.html'), mode='rb')
|
||||||
rv = flask.send_file(f)
|
rv = flask.send_file(f)
|
||||||
rv.direct_passthrough = False
|
rv.direct_passthrough = False
|
||||||
with app.open_resource('static/index.html') as f:
|
with app.open_resource('static/index.html') as f:
|
||||||
|
|
|
||||||
|
|
@ -295,6 +295,14 @@ class TemplatingTestCase(FlaskTestCase):
|
||||||
rv = app.test_client().get('/')
|
rv = app.test_client().get('/')
|
||||||
self.assert_equal(rv.data, b'<h1>Jameson</h1>')
|
self.assert_equal(rv.data, b'<h1>Jameson</h1>')
|
||||||
|
|
||||||
|
def test_templates_auto_reload(self):
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
self.assert_true(app.config['TEMPLATES_AUTO_RELOAD'])
|
||||||
|
self.assert_true(app.jinja_env.auto_reload)
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
app.config['TEMPLATES_AUTO_RELOAD'] = False
|
||||||
|
self.assert_false(app.jinja_env.auto_reload)
|
||||||
|
|
||||||
|
|
||||||
def suite():
|
def suite():
|
||||||
suite = unittest.TestSuite()
|
suite = unittest.TestSuite()
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ class View(object):
|
||||||
#: view function is created the result is automatically decorated.
|
#: view function is created the result is automatically decorated.
|
||||||
#:
|
#:
|
||||||
#: .. versionadded:: 0.8
|
#: .. versionadded:: 0.8
|
||||||
decorators = []
|
decorators = ()
|
||||||
|
|
||||||
def dispatch_request(self):
|
def dispatch_request(self):
|
||||||
"""Subclasses have to override this method to implement the
|
"""Subclasses have to override this method to implement the
|
||||||
|
|
@ -89,7 +89,7 @@ class View(object):
|
||||||
for decorator in cls.decorators:
|
for decorator in cls.decorators:
|
||||||
view = decorator(view)
|
view = decorator(view)
|
||||||
|
|
||||||
# we attach the view class to the view function for two reasons:
|
# We attach the view class to the view function for two reasons:
|
||||||
# first of all it allows us to easily figure out what class-based
|
# first of all it allows us to easily figure out what class-based
|
||||||
# view this thing came from, secondly it's also used for instantiating
|
# view this thing came from, secondly it's also used for instantiating
|
||||||
# the view class so you can actually replace it with something else
|
# the view class so you can actually replace it with something else
|
||||||
|
|
@ -111,7 +111,7 @@ class MethodViewType(type):
|
||||||
for key in d:
|
for key in d:
|
||||||
if key in http_method_funcs:
|
if key in http_method_funcs:
|
||||||
methods.add(key.upper())
|
methods.add(key.upper())
|
||||||
# if we have no method at all in there we don't want to
|
# If we have no method at all in there we don't want to
|
||||||
# add a method list. (This is for instance the case for
|
# add a method list. (This is for instance the case for
|
||||||
# the baseclass or another subclass of a base method view
|
# the baseclass or another subclass of a base method view
|
||||||
# that does not introduce new methods).
|
# that does not introduce new methods).
|
||||||
|
|
@ -141,8 +141,8 @@ class MethodView(with_metaclass(MethodViewType, View)):
|
||||||
"""
|
"""
|
||||||
def dispatch_request(self, *args, **kwargs):
|
def dispatch_request(self, *args, **kwargs):
|
||||||
meth = getattr(self, request.method.lower(), None)
|
meth = getattr(self, request.method.lower(), None)
|
||||||
# if the request method is HEAD and we don't have a handler for it
|
# If the request method is HEAD and we don't have a handler for it
|
||||||
# retry with GET
|
# retry with GET.
|
||||||
if meth is None and request.method == 'HEAD':
|
if meth is None and request.method == 'HEAD':
|
||||||
meth = getattr(self, 'get', None)
|
meth = getattr(self, 'get', None)
|
||||||
assert meth is not None, 'Unimplemented method %r' % request.method
|
assert meth is not None, 'Unimplemented method %r' % request.method
|
||||||
|
|
|
||||||
|
|
@ -40,25 +40,25 @@ class Request(RequestBase):
|
||||||
specific ones.
|
specific ones.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#: the internal URL rule that matched the request. This can be
|
#: The internal URL rule that matched the request. This can be
|
||||||
#: useful to inspect which methods are allowed for the URL from
|
#: useful to inspect which methods are allowed for the URL from
|
||||||
#: a before/after handler (``request.url_rule.methods``) etc.
|
#: a before/after handler (``request.url_rule.methods``) etc.
|
||||||
#:
|
#:
|
||||||
#: .. versionadded:: 0.6
|
#: .. versionadded:: 0.6
|
||||||
url_rule = None
|
url_rule = None
|
||||||
|
|
||||||
#: a dict of view arguments that matched the request. If an exception
|
#: A dict of view arguments that matched the request. If an exception
|
||||||
#: happened when matching, this will be `None`.
|
#: happened when matching, this will be `None`.
|
||||||
view_args = None
|
view_args = None
|
||||||
|
|
||||||
#: if matching the URL failed, this is the exception that will be
|
#: If matching the URL failed, this is the exception that will be
|
||||||
#: raised / was raised as part of the request handling. This is
|
#: raised / was raised as part of the request handling. This is
|
||||||
#: usually a :exc:`~werkzeug.exceptions.NotFound` exception or
|
#: usually a :exc:`~werkzeug.exceptions.NotFound` exception or
|
||||||
#: something similar.
|
#: something similar.
|
||||||
routing_exception = None
|
routing_exception = None
|
||||||
|
|
||||||
# switched by the request context until 1.0 to opt in deprecated
|
# Switched by the request context until 1.0 to opt in deprecated
|
||||||
# module functionality
|
# module functionality.
|
||||||
_is_old_module = False
|
_is_old_module = False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
@ -179,7 +179,7 @@ class Request(RequestBase):
|
||||||
def _load_form_data(self):
|
def _load_form_data(self):
|
||||||
RequestBase._load_form_data(self)
|
RequestBase._load_form_data(self)
|
||||||
|
|
||||||
# in debug mode we're replacing the files multidict with an ad-hoc
|
# In debug mode we're replacing the files multidict with an ad-hoc
|
||||||
# subclass that raises a different error for key errors.
|
# subclass that raises a different error for key errors.
|
||||||
ctx = _request_ctx_stack.top
|
ctx = _request_ctx_stack.top
|
||||||
if ctx is not None and ctx.app.debug and \
|
if ctx is not None and ctx.app.debug and \
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ def parse_changelog():
|
||||||
match = re.search('^Version\s+(.*)', line.strip())
|
match = re.search('^Version\s+(.*)', line.strip())
|
||||||
if match is None:
|
if match is None:
|
||||||
continue
|
continue
|
||||||
length = len(match.group(1))
|
|
||||||
version = match.group(1).strip()
|
version = match.group(1).strip()
|
||||||
if lineiter.next().count('-') != len(match.group(0)):
|
if lineiter.next().count('-') != len(match.group(0)):
|
||||||
continue
|
continue
|
||||||
|
|
@ -60,6 +59,7 @@ def parse_date(string):
|
||||||
|
|
||||||
def set_filename_version(filename, version_number, pattern):
|
def set_filename_version(filename, version_number, pattern):
|
||||||
changed = []
|
changed = []
|
||||||
|
|
||||||
def inject_version(match):
|
def inject_version(match):
|
||||||
before, old, after = match.groups()
|
before, old, after = match.groups()
|
||||||
changed.append(True)
|
changed.append(True)
|
||||||
|
|
@ -133,7 +133,8 @@ def main():
|
||||||
if version in tags:
|
if version in tags:
|
||||||
fail('Version "%s" is already tagged', version)
|
fail('Version "%s" is already tagged', version)
|
||||||
if release_date.date() != date.today():
|
if release_date.date() != date.today():
|
||||||
fail('Release date is not today (%s != %s)')
|
fail('Release date is not today (%s != %s)',
|
||||||
|
release_date.date(), date.today())
|
||||||
|
|
||||||
if not git_is_clean():
|
if not git_is_clean():
|
||||||
fail('You have uncommitted changes in git')
|
fail('You have uncommitted changes in git')
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue