diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..8383fff9
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+CHANGES merge=union
diff --git a/.github/ISSUE_TEMPLATE.rst b/.github/ISSUE_TEMPLATE.rst
new file mode 100644
index 00000000..8854961a
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.rst
@@ -0,0 +1,2 @@
+The issue tracker is a tool to address bugs.
+Please use the #pocoo IRC channel on freenode or Stack Overflow for questions.
diff --git a/.gitignore b/.gitignore
index 9bf4f063..fb9baf35 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,9 @@ _mailinglist
.tox
.cache/
.idea/
+
+# Coverage reports
+htmlcov
+.coverage
+.coverage.*
+*,cover
diff --git a/.travis.yml b/.travis.yml
index 8d2d3c60..32247c58 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,22 +8,35 @@ python:
- "3.3"
- "3.4"
- "3.5"
+ - "3.6"
env:
- REQUIREMENTS=lowest
+ - REQUIREMENTS=lowest-simplejson
- REQUIREMENTS=release
+ - REQUIREMENTS=release-simplejson
- REQUIREMENTS=devel
+ - REQUIREMENTS=devel-simplejson
matrix:
exclude:
# Python 3 support currently does not work with lowest requirements
- python: "3.3"
env: REQUIREMENTS=lowest
+ - python: "3.3"
+ env: REQUIREMENTS=lowest-simplejson
- python: "3.4"
env: REQUIREMENTS=lowest
+ - python: "3.4"
+ env: REQUIREMENTS=lowest-simplejson
- python: "3.5"
env: REQUIREMENTS=lowest
-
+ - python: "3.5"
+ env: REQUIREMENTS=lowest-simplejson
+ - python: "3.6"
+ env: REQUIREMENTS=lowest
+ - python: "3.6"
+ env: REQUIREMENTS=lowest-simplejson
install:
- pip install tox
diff --git a/AUTHORS b/AUTHORS
index b0a4b6f3..33210243 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -15,9 +15,13 @@ Patches and Suggestions
- Chris Grindstaff
- Christopher Grebs
- Daniel Neuhäuser
+- Dan Sully
+- David Lord @davidism
- Edmond Burnett
- Florent Xicluna
- Georg Brandl
+- Jeff Widman @jeffwidman
+- Joshua Bronson @jab
- Justin Quick
- Kenneth Reitz
- Keyan Pishdadian
@@ -32,4 +36,3 @@ Patches and Suggestions
- Stephane Wirtel
- Thomas Schranz
- Zhao Xiaohong
-- David Lord @davidism
diff --git a/CHANGES b/CHANGES
index e3d9b0eb..11ac6430 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,11 +3,103 @@ Flask Changelog
Here you can see the full list of changes between each Flask release.
-Version 1.0
------------
+Version 0.13
+------------
+
+Major release, unreleased
+
+- Make `app.run()` into a noop if a Flask application is run from the
+ development server on the command line. This avoids some behavior that
+ was confusing to debug for newcomers.
+- Change default configuration `JSONIFY_PRETTYPRINT_REGULAR=False`. jsonify()
+ method returns compressed response by default, and pretty response in
+ debug mode.
+- Change Flask.__init__ to accept two new keyword arguments, ``host_matching``
+ and ``static_host``. This enables ``host_matching`` to be set properly by the
+ time the constructor adds the static route, and enables the static route to
+ be properly associated with the required host. (``#1559``)
+- ``send_file`` supports Unicode in ``attachment_filename``. (`#2223`_)
+- Pass ``_scheme`` argument from ``url_for`` to ``handle_build_error``.
+ (`#2017`_)
+- Add support for ``provide_automatic_options`` in ``add_url_rule`` to disable
+ adding OPTIONS method when the ``view_func`` argument is not a class.
+ (`#1489`_).
+- ``MethodView`` can inherit method handlers from base classes. (`#1936`_)
+- Errors caused while opening the session at the beginning of the request are
+ handled by the app's error handlers. (`#2254`_)
+- Blueprints gained ``json_encoder`` and ``json_decoder`` attributes to
+ override the app's encoder and decoder. (`#1898`_)
+- ``Flask.make_response`` raises ``TypeError`` instead of ``ValueError`` for
+ bad response types. The error messages have been improved to describe why the
+ type is invalid. (`#2256`_)
+
+.. _#1489: https://github.com/pallets/flask/pull/1489
+.. _#1898: https://github.com/pallets/flask/pull/1898
+.. _#1936: https://github.com/pallets/flask/pull/1936
+.. _#2017: https://github.com/pallets/flask/pull/2017
+.. _#2223: https://github.com/pallets/flask/pull/2223
+.. _#2254: https://github.com/pallets/flask/pull/2254
+.. _#2256: https://github.com/pallets/flask/pull/2256
+
+Version 0.12.1
+--------------
+
+Bugfix release, released on March 31st 2017
+
+- Prevent `flask run` from showing a NoAppException when an ImportError occurs
+ within the imported application module.
+- Fix encoding behavior of ``app.config.from_pyfile`` for Python 3. Fix
+ ``#2118``.
+- Use the ``SERVER_NAME`` config if it is present as default values for
+ ``app.run``. ``#2109``, ``#2152``
+- Call `ctx.auto_pop` with the exception object instead of `None`, in the
+ event that a `BaseException` such as `KeyboardInterrupt` is raised in a
+ request handler.
+
+Version 0.12
+------------
+
+Released on December 21st 2016, codename Punsch.
+
+- the cli command now responds to `--version`.
+- Mimetype guessing and ETag generation for file-like objects in ``send_file``
+ has been removed, as per issue ``#104``. See pull request ``#1849``.
+- Mimetype guessing in ``send_file`` now fails loudly and doesn't fall back to
+ ``application/octet-stream``. See pull request ``#1988``.
+- Make ``flask.safe_join`` able to join multiple paths like ``os.path.join``
+ (pull request ``#1730``).
+- Revert a behavior change that made the dev server crash instead of returning
+ a Internal Server Error (pull request ``#2006``).
+- Correctly invoke response handlers for both regular request dispatching as
+ well as error handlers.
+- Disable logger propagation by default for the app logger.
+- Add support for range requests in ``send_file``.
+- ``app.test_client`` includes preset default environment, which can now be
+ directly set, instead of per ``client.get``.
+
+Version 0.11.2
+--------------
+
+Bugfix release, unreleased
+
+- Fix crash when running under PyPy3, see pull request ``#1814``.
+
+Version 0.11.1
+--------------
+
+Bugfix release, released on June 7th 2016.
+
+- Fixed a bug that prevented ``FLASK_APP=foobar/__init__.py`` from working. See
+ pull request ``#1872``.
+
+Version 0.11
+------------
-(release date to be announced, codename to be selected)
+Released on May 29th 2016, codename Absinthe.
+- Added support to serializing top-level arrays to :func:`flask.jsonify`. This
+ introduces a security risk in ancient browsers. See
+ :ref:`json-security` for details.
- Added before_render_template signal.
- Added `**kwargs` to :meth:`flask.Test.test_client` to support passing
additional keyword arguments to the constructor of
@@ -23,7 +115,7 @@ Version 1.0
from a view function.
- Added :meth:`flask.Config.from_json`.
- Added :attr:`flask.Flask.config_class`.
-- Added :meth:`flask.config.Config.get_namespace`.
+- Added :meth:`flask.Config.get_namespace`.
- Templates are no longer automatically reloaded outside of debug mode. This
can be configured with the new ``TEMPLATES_AUTO_RELOAD`` config key.
- Added a workaround for a limitation in Python 3.3's namespace loader.
@@ -57,7 +149,7 @@ Version 1.0
- JSON responses are now terminated with a newline character, because it is a
convention that UNIX text files end with a newline and some clients don't
deal well when this newline is missing. See
- https://github.com/mitsuhiko/flask/pull/1262 -- this came up originally as a
+ https://github.com/pallets/flask/pull/1262 -- this came up originally as a
part of https://github.com/kennethreitz/httpbin/issues/168
- The automatically provided ``OPTIONS`` method is now correctly disabled if
the user registered an overriding rule with the lowercase-version
@@ -70,6 +162,12 @@ Version 1.0
- ``flask.g`` now has ``pop()`` and ``setdefault`` methods.
- Turn on autoescape for ``flask.templating.render_template_string`` by default
(pull request ``#1515``).
+- ``flask.ext`` is now deprecated (pull request ``#1484``).
+- ``send_from_directory`` now raises BadRequest if the filename is invalid on
+ the server OS (pull request ``#1763``).
+- Added the ``JSONIFY_MIMETYPE`` configuration variable (pull request ``#1728``).
+- Exceptions during teardown handling will no longer leave bad application
+ contexts lingering around.
Version 0.10.2
--------------
@@ -292,7 +390,7 @@ Released on September 29th 2011, codename Rakija
- Applications now not only have a root path where the resources and modules
are located but also an instance 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
+ conceptually only instance depending and outside version control so it's
the perfect place to put configuration files etc. For more information
see :ref:`instance-folders`.
- Added the ``APPLICATION_ROOT`` configuration variable.
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 12083f52..66766512 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -10,7 +10,7 @@ Support questions
Please, don't use the issue tracker for this. Check whether the ``#pocoo`` IRC
channel on Freenode can help with your issue. If your problem is not strictly
Werkzeug or Flask specific, ``#python`` is generally more active.
-`StackOverflow `_ is also worth considering.
+`Stack Overflow `_ is also worth considering.
Reporting issues
================
@@ -28,7 +28,7 @@ Submitting patches
clearly under which circumstances the bug happens. Make sure the test fails
without your patch.
-- Try to follow `PEP8 `_, but you
+- Try to follow `PEP8 `_, but you
may ignore the line-length-limit if following it would make the code uglier.
@@ -36,16 +36,16 @@ Running the testsuite
---------------------
You probably want to set up a `virtualenv
-`_.
+`_.
-The minimal requirement for running the testsuite is ``py.test``. You can
+The minimal requirement for running the testsuite is ``pytest``. You can
install it with::
pip install pytest
Clone this repository::
- git clone https://github.com/mitsuhiko/flask.git
+ git clone https://github.com/pallets/flask.git
Install Flask as an editable package using the current source::
@@ -54,19 +54,61 @@ Install Flask as an editable package using the current source::
Then you can run the testsuite with::
- py.test
+ pytest
-With only py.test installed, a large part of the testsuite will get skipped
+With only pytest installed, a large part of the testsuite will get skipped
though. Whether this is relevant depends on which part of Flask you're working
on. Travis is set up to run the full testsuite when you submit your pull
request anyways.
If you really want to test everything, you will have to install ``tox`` instead
-of ``pytest``. Currently we're depending on a development version of Tox
-because the released version is missing features we absolutely need. You can
-install it with::
+of ``pytest``. You can install it with::
- pip install hg+https://bitbucket.org/hpk42/tox
+ pip install tox
The ``tox`` command will then run all tests against multiple combinations
Python versions and dependency versions.
+
+Running test coverage
+---------------------
+Generating a report of lines that do not have unit test coverage can indicate where
+to start contributing. ``pytest`` integrates with ``coverage.py``, using the ``pytest-cov``
+plugin. This assumes you have already run the testsuite (see previous section)::
+
+ pip install pytest-cov
+
+After this has been installed, you can output a report to the command line using this command::
+
+ pytest --cov=flask tests/
+
+Generate a HTML report can be done using this command::
+
+ pytest --cov-report html --cov=flask tests/
+
+Full docs on ``coverage.py`` are here: https://coverage.readthedocs.io
+
+Caution
+=======
+pushing
+-------
+This repository contains several zero-padded file modes that may cause issues when pushing this repository to git hosts other than github. Fixing this is destructive to the commit history, so we suggest ignoring these warnings. If it fails to push and you're using a self-hosted git service like Gitlab, you can turn off repository checks in the admin panel.
+
+
+cloning
+-------
+The zero-padded file modes files above can cause issues while cloning, too. If you have
+
+::
+
+ [fetch]
+ fsckobjects = true
+
+or
+
+::
+
+ [receive]
+ fsckObjects = true
+
+
+set in your git configuration file, cloning this repository will fail. The only solution is to set both of the above settings to false while cloning, and then setting them back to true after the cloning is finished.
diff --git a/MANIFEST.in b/MANIFEST.in
index ce115864..f8d9c2ae 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,13 +1,11 @@
include Makefile CHANGES LICENSE AUTHORS
-recursive-include artwork *
-recursive-include tests *
-recursive-include examples *
-recursive-include docs *
-recursive-exclude docs *.pyc
-recursive-exclude docs *.pyo
-recursive-exclude tests *.pyc
-recursive-exclude tests *.pyo
-recursive-exclude examples *.pyc
-recursive-exclude examples *.pyo
+
+graft artwork
+graft tests
+graft examples
+graft docs
+
+global-exclude *.py[co]
+
prune docs/_build
prune docs/_themes
diff --git a/Makefile b/Makefile
index 1268a1b4..f76c2099 100644
--- a/Makefile
+++ b/Makefile
@@ -3,10 +3,8 @@
all: clean-pyc test
test:
- py.test tests examples
-
-tox-test:
- tox
+ pip install -r test-requirements.txt
+ tox -e py-release
audit:
python setup.py audit
diff --git a/README b/README
index d0e3c521..75c5e7b1 100644
--- a/README
+++ b/README
@@ -33,9 +33,11 @@
Good that you're asking. The tests are in the
tests/ folder. To run the tests use the
- `py.test` testing tool:
+ `pytest` testing tool:
- $ py.test
+ $ pytest
+
+ Details on contributing can be found in CONTRIBUTING.rst
~ Where can I get help?
diff --git a/docs/_templates/sidebarintro.html b/docs/_templates/sidebarintro.html
index 25245591..71fcd73b 100644
--- a/docs/_templates/sidebarintro.html
+++ b/docs/_templates/sidebarintro.html
@@ -16,7 +16,7 @@
diff --git a/docs/advanced_foreword.rst b/docs/advanced_foreword.rst
index 22e333f8..82b3dc58 100644
--- a/docs/advanced_foreword.rst
+++ b/docs/advanced_foreword.rst
@@ -46,24 +46,10 @@ spam, links to malicious software, and the like.
Flask is no different from any other framework in that you the developer must
build with caution, watching for exploits when building to your requirements.
-The Status of Python 3
-----------------------
-
-Currently the Python community is in the process of improving libraries to
-support the new iteration of the Python programming language. While the
-situation is greatly improving there are still some issues that make it
-hard for users to switch over to Python 3 just now. These problems are
-partially caused by changes in the language that went unreviewed for too
-long, partially also because we have not quite worked out how the lower-
-level API should change to account for the Unicode differences in Python 3.
-
-We strongly recommend using Python 2.7 with activated Python 3
-warnings during development. If you plan on upgrading to Python 3 in the
-near future we strongly recommend that you read `How to write forwards
-compatible Python code
-`_.
+Python 3 Support in Flask
+-------------------------
-If you do want to dive into Python 3 already have a look at the
-:ref:`python3-support` page.
+Flask, its dependencies, and most Flask extensions all support Python 3.
+If you want to use Flask with Python 3 have a look at the :ref:`python3-support` page.
Continue to :ref:`installation` or the :ref:`quickstart`.
diff --git a/docs/api.rst b/docs/api.rst
index 3da975e9..b5009907 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -30,61 +30,12 @@ Incoming Request Data
.. autoclass:: Request
:members:
-
- .. attribute:: form
-
- A :class:`~werkzeug.datastructures.MultiDict` with the parsed form data from ``POST``
- or ``PUT`` requests. Please keep in mind that file uploads will not
- end up here, but instead in the :attr:`files` attribute.
-
- .. attribute:: args
-
- A :class:`~werkzeug.datastructures.MultiDict` with the parsed contents of the query
- string. (The part in the URL after the question mark).
-
- .. attribute:: values
-
- A :class:`~werkzeug.datastructures.CombinedMultiDict` with the contents of both
- :attr:`form` and :attr:`args`.
-
- .. attribute:: cookies
-
- A :class:`dict` with the contents of all cookies transmitted with
- the request.
-
- .. attribute:: stream
-
- If the incoming form data was not encoded with a known mimetype
- the data is stored unmodified in this stream for consumption. Most
- of the time it is a better idea to use :attr:`data` which will give
- you that data as a string. The stream only returns the data once.
-
- .. attribute:: headers
-
- The incoming request headers as a dictionary like object.
-
- .. attribute:: data
-
- Contains the incoming request data as string in case it came with
- a mimetype Flask does not handle.
-
- .. attribute:: files
-
- A :class:`~werkzeug.datastructures.MultiDict` with files uploaded as part of a
- ``POST`` or ``PUT`` request. Each file is stored as
- :class:`~werkzeug.datastructures.FileStorage` object. It basically behaves like a
- standard file object you know from Python, with the difference that
- it also has a :meth:`~werkzeug.datastructures.FileStorage.save` function that can
- store the file on the filesystem.
+ :inherited-members:
.. attribute:: environ
The underlying WSGI environment.
- .. attribute:: method
-
- The current request method (``POST``, ``GET`` etc.)
-
.. attribute:: path
.. attribute:: full_path
.. attribute:: script_root
@@ -114,15 +65,8 @@ Incoming Request Data
`url_root` ``u'http://www.example.com/myapplication/'``
============= ======================================================
- .. attribute:: is_xhr
-
- ``True`` if the request was triggered via a JavaScript
- `XMLHttpRequest`. This only works with libraries that support the
- ``X-Requested-With`` header and set it to `XMLHttpRequest`.
- Libraries that do that are prototype, jQuery and Mochikit and
- probably some more.
-.. class:: request
+.. attribute:: request
To access incoming request data, you can use the global `request`
object. Flask parses incoming request data for you and gives you
@@ -289,7 +233,7 @@ thing, like it does for :class:`request` and :class:`session`.
It's now also possible to use the ``in`` operator on it to see if an
attribute is defined and it yields all keys on iteration.
- As of 1.0 you can use :meth:`pop` and :meth:`setdefault` in the same
+ As of 0.11 you can use :meth:`pop` and :meth:`setdefault` in the same
way you would use them on a dictionary.
This is a proxy. See :ref:`notes-on-proxies` for more information.
@@ -316,13 +260,7 @@ Useful Functions and Classes
.. autofunction:: url_for
-.. function:: abort(code)
-
- Raises an :exc:`~werkzeug.exceptions.HTTPException` for the given
- status code. For example to abort request handling with a page not
- found exception, you would call ``abort(404)``.
-
- :param code: the HTTP error code.
+.. autofunction:: abort
.. autofunction:: redirect
@@ -751,6 +689,8 @@ The following converters are available:
`int` accepts integers
`float` like `int` but for floating point values
`path` like the default but also accepts slashes
+`any` matches one of the items provided
+`uuid` accepts UUID strings
=========== ===============================================
Custom converters can be defined using :attr:`flask.Flask.url_map`.
@@ -890,13 +830,6 @@ Command Line Interface
Marks a function so that an instance of :class:`ScriptInfo` is passed
as first argument to the click callback.
-.. autofunction:: script_info_option
-
- A special decorator that informs a click callback to be passed the
- script info object as first argument. This is normally not useful
- unless you implement very special commands like the run command which
- does not want the application to be loaded yet.
-
.. autodata:: run_command
.. autodata:: shell_command
diff --git a/docs/appcontext.rst b/docs/appcontext.rst
index 07e44f94..166c5aa3 100644
--- a/docs/appcontext.rst
+++ b/docs/appcontext.rst
@@ -26,8 +26,8 @@ In contrast, during request handling, a couple of other rules exist:
There is a third state which is sitting in between a little bit.
Sometimes you are dealing with an application in a way that is similar to
-how you interact with applications during request handling just that there
-is no request active. Consider for instance that you're sitting in an
+how you interact with applications during request handling; just that there
+is no request active. Consider, for instance, that you're sitting in an
interactive Python shell and interacting with the application, or a
command line application.
@@ -74,6 +74,11 @@ The application context is also used by the :func:`~flask.url_for`
function in case a ``SERVER_NAME`` was configured. This allows you to
generate URLs even in the absence of a request.
+If no request context has been pushed and an application context has
+not been explicitly set, a ``RuntimeError`` will be raised. ::
+
+ RuntimeError: Working outside of application context.
+
Locality of the Context
-----------------------
diff --git a/docs/becomingbig.rst b/docs/becomingbig.rst
index 8b0a2743..0facbfee 100644
--- a/docs/becomingbig.rst
+++ b/docs/becomingbig.rst
@@ -12,7 +12,7 @@ Flask started in part to demonstrate how to build your own framework on top of
existing well-used tools Werkzeug (WSGI) and Jinja (templating), and as it
developed, it became useful to a wide audience. As you grow your codebase,
don't just use Flask -- understand it. Read the source. Flask's code is
-written to be read; it's documentation is published so you can use its internal
+written to be read; its documentation is published so you can use its internal
APIs. Flask sticks to documented APIs in upstream libraries, and documents its
internal utilities so that you can find the hook points needed for your
project.
@@ -35,7 +35,7 @@ Subclass.
The :class:`~flask.Flask` class has many methods designed for subclassing. You
can quickly add or customize behavior by subclassing :class:`~flask.Flask` (see
the linked method docs) and using that subclass wherever you instantiate an
-application class. This works well with :ref:`app-factories`.
+application class. This works well with :ref:`app-factories`. See :doc:`/patterns/subclassing` for an example.
Wrap with middleware.
---------------------
diff --git a/docs/blueprints.rst b/docs/blueprints.rst
index d22220b2..89d3701e 100644
--- a/docs/blueprints.rst
+++ b/docs/blueprints.rst
@@ -176,16 +176,25 @@ the `template_folder` parameter to the :class:`Blueprint` constructor::
admin = Blueprint('admin', __name__, template_folder='templates')
-As for static files, the path can be absolute or relative to the blueprint
-resource folder. The template folder is added to the searchpath of
-templates but with a lower priority than the actual application's template
-folder. That way you can easily override templates that a blueprint
-provides in the actual application.
+For static files, the path can be absolute or relative to the blueprint
+resource folder.
+
+The template folder is added to the search path of templates but with a lower
+priority than the actual application's template folder. That way you can
+easily override templates that a blueprint provides in the actual application.
+This also means that if you don't want a blueprint template to be accidentally
+overridden, make sure that no other blueprint or actual application template
+has the same relative path. When multiple blueprints provide the same relative
+template path the first blueprint registered takes precedence over the others.
+
So if you have a blueprint in the folder ``yourapplication/admin`` and you
want to render the template ``'admin/index.html'`` and you have provided
``templates`` as a `template_folder` you will have to create a file like
-this: :file:`yourapplication/admin/templates/admin/index.html`.
+this: :file:`yourapplication/admin/templates/admin/index.html`. The reason
+for the extra ``admin`` folder is to avoid getting our template overridden
+by a template named ``index.html`` in the actual application template
+folder.
To further reiterate this: if you have a blueprint named ``admin`` and you
want to render a template called :file:`index.html` which is specific to this
diff --git a/docs/cli.rst b/docs/cli.rst
index 141176ce..d0b033f6 100644
--- a/docs/cli.rst
+++ b/docs/cli.rst
@@ -3,11 +3,11 @@
Command Line Interface
======================
-.. versionadded:: 1.0
+.. versionadded:: 0.11
.. currentmodule:: flask
-One of the nice new features in Flask 1.0 is the built-in integration of
+One of the nice new features in Flask 0.11 is the built-in integration of
the `click `_ command line interface. This
enables a wide range of new features for the Flask ecosystem and your own
applications.
@@ -15,41 +15,38 @@ applications.
Basic Usage
-----------
-After installation of Flask you will now find a :command:`flask` script installed
-into your virtualenv. If you don't want to install Flask or you have a
-special use-case you can also use ``python -m flask`` to accomplish exactly
-the same.
+After installation of Flask you will now find a :command:`flask` script
+installed into your virtualenv. If you don't want to install Flask or you
+have a special use-case you can also use ``python -m flask`` to accomplish
+exactly the same.
The way this script works is by providing access to all the commands on
your Flask application's :attr:`Flask.cli` instance as well as some
built-in commands that are always there. Flask extensions can also
register more commands there if they desire so.
-For the :command:`flask` script to work, an application needs to be discovered.
-The two most common ways are either an environment variable
-(``FLASK_APP``) or the :option:`--app` / :option:`-a` parameter. It should be the
-import path for your application or the path to a Python file. In the
-latter case Flask will attempt to setup the Python path for you
-automatically and discover the module name but that might not always work.
+For the :command:`flask` script to work, an application needs to be
+discovered. This is achieved by exporting the ``FLASK_APP`` environment
+variable. It can be either set to an import path or to a filename of a
+Python module that contains a Flask application.
In that imported file the name of the app needs to be called ``app`` or
-optionally be specified after a colon.
+optionally be specified after a colon. For instance
+``mymodule:application`` would tell it to use the `application` object in
+the :file:`mymodule.py` file.
-Given a :file:`hello.py` file with the application in it named ``app`` this is
-how it can be run.
+Given a :file:`hello.py` file with the application in it named ``app``
+this is how it can be run.
Environment variables (On Windows use ``set`` instead of ``export``)::
export FLASK_APP=hello
flask run
-Parameters::
+Or with a filename::
- flask --app=hello run
-
-File names::
-
- flask --app=hello.py run
+ export FLASK_APP=/path/to/hello.py
+ flask run
Virtualenv Integration
----------------------
@@ -59,19 +56,33 @@ If you are constantly working with a virtualenv you can also put the
bottom of the file. That way every time you activate your virtualenv you
automatically also activate the correct application name.
+Edit the activate script for the shell you use. For example:
+
+Unix Bash: ``venv/bin/activate``::
+
+ FLASK_APP=hello
+ export FLASK_APP
+
+Windows CMD.exe: ``venv\Scripts\activate.bat``::
+
+ set "FLASK_APP=hello"
+ :END
+
Debug Flag
----------
-The :command:`flask` script can be run with :option:`--debug` or :option:`--no-debug` to
-automatically flip the debug flag of the application. This can also be
-configured by setting ``FLASK_DEBUG`` to ``1`` or ``0``.
+The :command:`flask` script can also be instructed to enable the debug
+mode of the application automatically by exporting ``FLASK_DEBUG``. If
+set to ``1`` debug is enabled or ``0`` disables it::
+
+ export FLASK_DEBUG=1
Running a Shell
---------------
To run an interactive Python shell you can use the ``shell`` command::
- flask --app=hello shell
+ flask shell
This will start up an interactive Python shell, setup the correct
application context and setup the local variables in the shell. This is
@@ -86,6 +97,7 @@ easily. Flask uses `click`_ for the command interface which makes
creating custom commands very easy. For instance if you want a shell
command to initialize the database you can do this::
+ import click
from flask import Flask
app = Flask(__name__)
@@ -93,11 +105,11 @@ command to initialize the database you can do this::
@app.cli.command()
def initdb():
"""Initialize the database."""
- print 'Init the db'
+ click.echo('Init the db')
The command will then show up on the command line::
- $ flask -a hello.py initdb
+ $ flask initdb
Init the db
Application Context
@@ -122,12 +134,12 @@ Factory Functions
-----------------
In case you are using factory functions to create your application (see
-:ref:`app-factories`) you will discover that the :command:`flask` command cannot
-work with them directly. Flask won't be able to figure out how to
+:ref:`app-factories`) you will discover that the :command:`flask` command
+cannot work with them directly. Flask won't be able to figure out how to
instantiate your application properly by itself. Because of this reason
the recommendation is to create a separate file that instantiates
-applications. This is by far not the only way to make this work. Another
-is the :ref:`custom-scripts` support.
+applications. This is not the only way to make this work. Another is the
+:ref:`custom-scripts` support.
For instance if you have a factory function that creates an application
from a filename you could make a separate file that creates such an
@@ -139,8 +151,8 @@ This could be a file named :file:`autoapp.py` with these contents::
from yourapplication import create_app
app = create_app(os.environ['YOURAPPLICATION_CONFIG'])
-Once this has happened you can make the flask command automatically pick
-it up::
+Once this has happened you can make the :command:`flask` command automatically
+pick it up::
export YOURAPPLICATION_CONFIG=/path/to/config.cfg
export FLASK_APP=/path/to/autoapp.py
@@ -152,9 +164,9 @@ From this point onwards :command:`flask` will find your application.
Custom Scripts
--------------
-While the most common way is to use the :command:`flask` command, you can also
-make your own "driver scripts". Since Flask uses click for the scripts
-there is no reason you cannot hook these scripts into any click
+While the most common way is to use the :command:`flask` command, you can
+also make your own "driver scripts". Since Flask uses click for the
+scripts there is no reason you cannot hook these scripts into any click
application. There is one big caveat and that is, that commands
registered to :attr:`Flask.cli` will expect to be (indirectly at least)
launched from a :class:`flask.cli.FlaskGroup` click group. This is
@@ -162,38 +174,32 @@ necessary so that the commands know which Flask application they have to
work with.
To understand why you might want custom scripts you need to understand how
-click finds and executes the Flask application. If you use the :command:`flask`
-script you specify the application to work with on the command line or
-environment variable as an import name. This is simple but it has some
-limitations. Primarily it does not work with application factory
-functions (see :ref:`app-factories`).
+click finds and executes the Flask application. If you use the
+:command:`flask` script you specify the application to work with on the
+command line or environment variable as an import name. This is simple
+but it has some limitations. Primarily it does not work with application
+factory functions (see :ref:`app-factories`).
With a custom script you don't have this problem as you can fully
customize how the application will be created. This is very useful if you
write reusable applications that you want to ship to users and they should
be presented with a custom management script.
-If you are used to writing click applications this will look familiar but
-at the same time, slightly different because of how commands are loaded.
-We won't go into detail now about the differences but if you are curious
-you can have a look at the :ref:`script-info-object` section to learn all
-about it.
-
To explain all of this, here is an example :file:`manage.py` script that
manages a hypothetical wiki application. We will go through the details
afterwards::
+ import os
import click
- from flask.cli import FlaskGroup, script_info_option
+ from flask.cli import FlaskGroup
def create_wiki_app(info):
from yourwiki import create_app
- config = info.data.get('config') or 'wikiconfig.py'
- return create_app(config=config)
+ return create_app(
+ config=os.environ.get('WIKI_CONFIG', 'wikiconfig.py'))
@click.group(cls=FlaskGroup, create_app=create_wiki_app)
- @script_info_option('--config', script_info_key='config')
- def cli(**params):
+ def cli():
"""This is a management script for the wiki application."""
if __name__ == '__main__':
@@ -204,56 +210,51 @@ step.
1. First we import the ``click`` library as well as the click extensions
from the ``flask.cli`` package. Primarily we are here interested
- in the :class:`~flask.cli.FlaskGroup` click group and the
- :func:`~flask.cli.script_info_option` decorator.
+ in the :class:`~flask.cli.FlaskGroup` click group.
2. The next thing we do is defining a function that is invoked with the
- script info object (:ref:`script-info-object`) from Flask and its
+ script info object (:class:`~flask.cli.ScriptInfo`) from Flask and its
purpose is to fully import and create the application. This can
either directly import an application object or create it (see
- :ref:`app-factories`).
-
- What is ``info.data``? It's a dictionary of arbitrary data on the
- script info that can be filled by options or through other means. We
- will come back to this later.
+ :ref:`app-factories`). In this case we load the config from an
+ environment variable.
3. Next step is to create a :class:`FlaskGroup`. In this case we just
make an empty function with a help doc string that just does nothing
and then pass the ``create_wiki_app`` function as a factory function.
Whenever click now needs to operate on a Flask application it will
call that function with the script info and ask for it to be created.
-4. In step 2 you could see that the config is passed to the actual
- creation function. This config comes from the :func:`script_info_option`
- decorator for the main script. It accepts a :option:`--config` option and
- then stores it in the script info so we can use it to create the
- application.
-5. All is rounded up by invoking the script.
+4. All is rounded up by invoking the script.
+
+CLI Plugins
+-----------
-.. _script-info-object:
+Flask extensions can always patch the :attr:`Flask.cli` instance with more
+commands if they want. However there is a second way to add CLI plugins
+to Flask which is through ``setuptools``. If you make a Python package that
+should export a Flask command line plugin you can ship a :file:`setup.py` file
+that declares an entrypoint that points to a click command:
-The Script Info
----------------
+Example :file:`setup.py`::
+
+ from setuptools import setup
+
+ setup(
+ name='flask-my-extension',
+ ...
+ entry_points='''
+ [flask.commands]
+ my-command=mypackage.commands:cli
+ ''',
+ )
+
+Inside :file:`mypackage/commands.py` you can then export a Click object::
+
+ import click
+
+ @click.command()
+ def cli():
+ """This is an example command."""
-The Flask script integration might be confusing at first, but there is a reason
-why it's done this way. The reason for this is that Flask wants to
-both provide custom commands to click as well as not loading your
-application unless it has to. The reason for this is added flexibility.
-
-This way an application can provide custom commands, but even in the
-absence of an application the :command:`flask` script is still operational on a
-basic level. In addition to that it means that the individual commands
-have the option to avoid creating an instance of the Flask application
-unless required. This is very useful as it allows the server commands for
-instance to load the application on a first request instead of
-immediately, therefore giving a better debug experience.
-
-All of this is provided through the :class:`flask.cli.ScriptInfo` object
-and some helper utilities around. The basic way it operates is that when
-the :class:`flask.cli.FlaskGroup` executes as a script it creates a script
-info and keeps it around. From that point onwards modifications on the
-script info can be done through click options. To simplify this pattern
-the :func:`flask.cli.script_info_option` decorator was added.
-
-Once Flask actually needs the individual Flask application it will invoke
-the :meth:`flask.cli.ScriptInfo.load_app` method. This happens when the
-server starts, when the shell is launched or when the script looks for an
-application-provided click command.
+Once that package is installed in the same virtualenv as Flask itself you
+can run ``flask my-command`` to invoke your command. This is useful to
+provide extra functionality that Flask itself cannot ship.
diff --git a/docs/conf.py b/docs/conf.py
index 285c8981..f53d72fa 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -10,14 +10,20 @@
#
# All configuration values have a default; values that are commented out
# serve to show the default.
+from __future__ import print_function
+import os
+import sys
+import pkg_resources
+import time
+import datetime
-import sys, os
+BUILD_DATE = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
-sys.path.append(os.path.abspath('_themes'))
-sys.path.append(os.path.abspath('.'))
+sys.path.append(os.path.join(os.path.dirname(__file__), '_themes'))
+sys.path.append(os.path.dirname(__file__))
# -- General configuration -----------------------------------------------------
@@ -26,8 +32,11 @@ sys.path.append(os.path.abspath('.'))
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx',
- 'flaskdocext']
+extensions = [
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.intersphinx',
+ 'flaskdocext'
+]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -43,24 +52,21 @@ master_doc = 'index'
# General information about the project.
project = u'Flask'
-copyright = u'2015, Armin Ronacher'
+copyright = u'2010 - {0}, Armin Ronacher'.format(BUILD_DATE.year)
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
-import pkg_resources
try:
release = pkg_resources.get_distribution('Flask').version
except pkg_resources.DistributionNotFound:
- print 'To build the documentation, The distribution information of Flask'
- print 'Has to be available. Either install the package into your'
- print 'development environment or run "setup.py develop" to setup the'
- print 'metadata. A virtualenv is recommended!'
+ print('Flask must be installed to build the documentation.')
+ print('Install from source using `pip install -e .` in a virtualenv.')
sys.exit(1)
-del pkg_resources
if 'dev' in release:
- release = release.split('dev')[0] + 'dev'
+ release = ''.join(release.partition('dev')[:2])
+
version = '.'.join(release.split('.')[:2])
# The language for content autogenerated by Sphinx. Refer to documentation
@@ -99,14 +105,12 @@ exclude_patterns = ['_build']
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
-html_theme = 'flask'
+# html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
-html_theme_options = {
- 'touch_icon': 'touch-icon.png'
-}
+# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = ['_themes']
@@ -125,7 +129,7 @@ html_theme_path = ['_themes']
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
-html_favicon = "flask-favicon.ico"
+html_favicon = '_static/flask-favicon.ico'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
@@ -142,9 +146,18 @@ html_static_path = ['_static']
# Custom sidebar templates, maps document names to template names.
html_sidebars = {
- 'index': ['sidebarintro.html', 'sourcelink.html', 'searchbox.html'],
- '**': ['sidebarlogo.html', 'localtoc.html', 'relations.html',
- 'sourcelink.html', 'searchbox.html']
+ 'index': [
+ 'sidebarintro.html',
+ 'sourcelink.html',
+ 'searchbox.html'
+ ],
+ '**': [
+ 'sidebarlogo.html',
+ 'localtoc.html',
+ 'relations.html',
+ 'sourcelink.html',
+ 'searchbox.html'
+ ]
}
# Additional templates that should be rendered to pages, maps page names to
@@ -186,8 +199,7 @@ htmlhelp_basename = 'Flaskdoc'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
- ('latexindex', 'Flask.tex', u'Flask Documentation',
- u'Armin Ronacher', 'manual'),
+ ('latexindex', 'Flask.tex', u'Flask Documentation', u'Armin Ronacher', 'manual'),
]
# Documents to append as an appendix to all manuals.
@@ -197,10 +209,10 @@ latex_documents = [
latex_use_modindex = False
latex_elements = {
- 'fontpkg': r'\usepackage{mathpazo}',
- 'papersize': 'a4paper',
- 'pointsize': '12pt',
- 'preamble': r'\usepackage{flaskstyle}'
+ 'fontpkg': r'\usepackage{mathpazo}',
+ 'papersize': 'a4paper',
+ 'pointsize': '12pt',
+ 'preamble': r'\usepackage{flaskstyle}'
}
latex_use_parts = True
@@ -222,7 +234,7 @@ latex_additional_files = ['flaskstyle.sty', 'logo.pdf']
# The scheme of the identifier. Typical schemes are ISBN or URL.
#epub_scheme = ''
-# The unique identifier of the text. This can be a ISBN number
+# The unique identifier of the text. This can be an ISBN number
# or the project homepage.
#epub_identifier = ''
@@ -244,31 +256,29 @@ latex_additional_files = ['flaskstyle.sty', 'logo.pdf']
#epub_tocdepth = 3
intersphinx_mapping = {
- 'https://docs.python.org/dev': None,
- 'http://werkzeug.pocoo.org/docs/': None,
- 'http://click.pocoo.org/': None,
- 'http://jinja.pocoo.org/docs/': None,
- 'http://www.sqlalchemy.org/docs/': None,
- 'https://wtforms.readthedocs.org/en/latest/': None,
- 'https://pythonhosted.org/blinker/': None
+ 'python': ('https://docs.python.org/3/', None),
+ 'werkzeug': ('http://werkzeug.pocoo.org/docs/', None),
+ 'click': ('http://click.pocoo.org/', None),
+ 'jinja': ('http://jinja.pocoo.org/docs/', None),
+ 'sqlalchemy': ('https://docs.sqlalchemy.org/en/latest/', None),
+ 'wtforms': ('https://wtforms.readthedocs.io/en/latest/', None),
+ 'blinker': ('https://pythonhosted.org/blinker/', None)
}
-pygments_style = 'flask_theme_support.FlaskyStyle'
-
-# fall back if theme is not there
try:
__import__('flask_theme_support')
-except ImportError, e:
- print '-' * 74
- print 'Warning: Flask themes unavailable. Building with default theme'
- print 'If you want the Flask themes, run this command and build again:'
- print
- print ' git submodule update --init'
- print '-' * 74
-
- pygments_style = 'tango'
- html_theme = 'default'
- html_theme_options = {}
+ pygments_style = 'flask_theme_support.FlaskyStyle'
+ html_theme = 'flask'
+ html_theme_options = {
+ 'touch_icon': 'touch-icon.png'
+ }
+except ImportError:
+ print('-' * 74)
+ print('Warning: Flask themes unavailable. Building with default theme')
+ print('If you want the Flask themes, run this command and build again:')
+ print()
+ print(' git submodule update --init')
+ print('-' * 74)
# unwrap decorators
diff --git a/docs/config.rst b/docs/config.rst
index 245d3bab..75ce239a 100644
--- a/docs/config.rst
+++ b/docs/config.rst
@@ -44,6 +44,21 @@ method::
SECRET_KEY='...'
)
+.. admonition:: Debug Mode with the ``flask`` Script
+
+ If you use the :command:`flask` script to start a local development
+ server, to enable the debug mode, you need to export the ``FLASK_DEBUG``
+ environment variable before running the server::
+
+ $ export FLASK_DEBUG=1
+ $ flask run
+
+ (On Windows you need to use ``set`` instead of ``export``).
+
+ ``app.debug`` and ``app.config['DEBUG']`` are not compatible with
+ the :command:`flask` script. They only worked when using ``Flask.run()``
+ method.
+
Builtin Configuration Values
----------------------------
@@ -52,7 +67,8 @@ The following configuration values are used internally by Flask:
.. tabularcolumns:: |p{6.5cm}|p{8.5cm}|
================================= =========================================
-``DEBUG`` enable/disable debug mode
+``DEBUG`` enable/disable debug mode when using
+ ``Flask.run()`` method to start server
``TESTING`` enable/disable testing mode
``PROPAGATE_EXCEPTIONS`` explicitly enable or disable the
propagation of exceptions. If not set or
@@ -177,12 +193,11 @@ The following configuration values are used internally by Flask:
behavior by changing this variable.
This is not recommended but might give
you a performance improvement on the
- cost of cachability.
-``JSONIFY_PRETTYPRINT_REGULAR`` If this is set to ``True`` (the default)
- jsonify responses will be pretty printed
- if they are not requested by an
- XMLHttpRequest object (controlled by
- the ``X-Requested-With`` header)
+ cost of cacheability.
+``JSONIFY_PRETTYPRINT_REGULAR`` If this is set to ``True`` or the Flask app
+ is running in debug mode, jsonify responses
+ will be pretty printed.
+``JSONIFY_MIMETYPE`` MIME type used for jsonify responses.
``TEMPLATES_AUTO_RELOAD`` Whether to check for modifications of
the template source and reload it
automatically. By default the value is
@@ -240,7 +255,7 @@ The following configuration values are used internally by Flask:
.. versionadded:: 0.10
``JSON_AS_ASCII``, ``JSON_SORT_KEYS``, ``JSONIFY_PRETTYPRINT_REGULAR``
-.. versionadded:: 1.0
+.. versionadded:: 0.11
``SESSION_REFRESH_EACH_REQUEST``, ``TEMPLATES_AUTO_RELOAD``,
``LOGGER_HANDLER_POLICY``, ``EXPLAIN_TEMPLATE_LOADING``
@@ -261,7 +276,7 @@ So a common pattern is this::
This first loads the configuration from the
`yourapplication.default_settings` module and then overrides the values
-with the contents of the file the :envvar:``YOURAPPLICATION_SETTINGS``
+with the contents of the file the :envvar:`YOURAPPLICATION_SETTINGS`
environment variable points to. This environment variable can be set on
Linux or OS X with the export command in the shell before starting the
server::
@@ -309,6 +324,7 @@ that experience:
limit yourself to request-only accesses to the configuration you can
reconfigure the object later on as needed.
+.. _config-dev-prod:
Development / Production
------------------------
@@ -330,7 +346,7 @@ there are alternative ways as well. For example you could use imports or
subclassing.
What is very popular in the Django world is to make the import explicit in
-the config file by adding an ``from yourapplication.default_settings
+the config file by adding ``from yourapplication.default_settings
import *`` to the top of the file and then overriding the changes by hand.
You could also inspect an environment variable like
``YOURAPPLICATION_MODE`` and set that to `production`, `development` etc
diff --git a/docs/deploying/fastcgi.rst b/docs/deploying/fastcgi.rst
index c0beae0c..5ca2a084 100644
--- a/docs/deploying/fastcgi.rst
+++ b/docs/deploying/fastcgi.rst
@@ -144,7 +144,7 @@ A basic FastCGI configuration for lighttpd looks like that::
)
alias.url = (
- "/static/" => "/path/to/your/static"
+ "/static/" => "/path/to/your/static/"
)
url.rewrite-once = (
@@ -159,7 +159,7 @@ work in the URL root you have to work around a lighttpd bug with the
Make sure to apply it only if you are mounting the application the URL
root. Also, see the Lighty docs for more information on `FastCGI and Python
-`_ (note that
+`_ (note that
explicitly passing a socket to run() is no longer necessary).
Configuring nginx
@@ -234,7 +234,7 @@ python path. Common problems are:
web server.
- Different python interpreters being used.
-.. _nginx: http://nginx.org/
-.. _lighttpd: http://www.lighttpd.net/
+.. _nginx: https://nginx.org/
+.. _lighttpd: https://www.lighttpd.net/
.. _cherokee: http://cherokee-project.com/
.. _flup: https://pypi.python.org/pypi/flup
diff --git a/docs/deploying/index.rst b/docs/deploying/index.rst
index ba506d6f..6950e47a 100644
--- a/docs/deploying/index.rst
+++ b/docs/deploying/index.rst
@@ -19,12 +19,12 @@ Hosted options
- `Deploying Flask on Heroku `_
- `Deploying Flask on OpenShift `_
-- `Deploying WSGI on dotCloud `_
- with `Flask-specific notes `_
- `Deploying Flask on Webfaction `_
- `Deploying Flask on Google App Engine `_
+- `Deploying Flask on AWS Elastic Beanstalk `_
- `Sharing your Localhost Server with Localtunnel `_
- `Deploying on Azure (IIS) `_
+- `Deploying on PythonAnywhere `_
Self-hosted options
-------------------
diff --git a/docs/deploying/mod_wsgi.rst b/docs/deploying/mod_wsgi.rst
index 9145b4f9..ca694b7d 100644
--- a/docs/deploying/mod_wsgi.rst
+++ b/docs/deploying/mod_wsgi.rst
@@ -13,7 +13,7 @@ If you are using the `Apache`_ webserver, consider using `mod_wsgi`_.
not called because this will always start a local WSGI server which
we do not want if we deploy that application to mod_wsgi.
-.. _Apache: http://httpd.apache.org/
+.. _Apache: https://httpd.apache.org/
Installing `mod_wsgi`
---------------------
@@ -114,7 +114,7 @@ refuse to run with the above configuration. On a Windows system, eliminate those
Note: There have been some changes in access control configuration for `Apache 2.4`_.
-.. _Apache 2.4: http://httpd.apache.org/docs/trunk/upgrading.html
+.. _Apache 2.4: https://httpd.apache.org/docs/trunk/upgrading.html
Most notably, the syntax for directory permissions has changed from httpd 2.2
@@ -130,12 +130,12 @@ to httpd 2.4 syntax
Require all granted
-For more information consult the `mod_wsgi wiki`_.
+For more information consult the `mod_wsgi documentation`_.
-.. _mod_wsgi: http://code.google.com/p/modwsgi/
-.. _installation instructions: http://code.google.com/p/modwsgi/wiki/QuickInstallationGuide
+.. _mod_wsgi: https://github.com/GrahamDumpleton/mod_wsgi
+.. _installation instructions: https://modwsgi.readthedocs.io/en/develop/installation.html
.. _virtual python: https://pypi.python.org/pypi/virtualenv
-.. _mod_wsgi wiki: http://code.google.com/p/modwsgi/w/list
+.. _mod_wsgi documentation: https://modwsgi.readthedocs.io/en/develop/index.html
Troubleshooting
---------------
@@ -143,7 +143,7 @@ Troubleshooting
If your application does not run, follow this guide to troubleshoot:
**Problem:** application does not run, errorlog shows SystemExit ignored
- You have a ``app.run()`` call in your application file that is not
+ You have an ``app.run()`` call in your application file that is not
guarded by an ``if __name__ == '__main__':`` condition. Either
remove that :meth:`~flask.Flask.run` call from the file and move it
into a separate :file:`run.py` file or put it into such an if block.
diff --git a/docs/deploying/uwsgi.rst b/docs/deploying/uwsgi.rst
index 2d15440f..50c85fb2 100644
--- a/docs/deploying/uwsgi.rst
+++ b/docs/deploying/uwsgi.rst
@@ -29,20 +29,16 @@ Given a flask application in myapp.py, use the following command:
.. sourcecode:: text
- $ uwsgi -s /tmp/uwsgi.sock --manage-script-name --mount /yourapplication=myapp:app
+ $ uwsgi -s /tmp/yourapplication.sock --manage-script-name --mount /yourapplication=myapp:app
-Or, if you prefer:
-
-.. sourcecode:: text
-
- $ uwsgi -s /tmp/uwsgi.sock --manage-script-name --mount /yourapplication=myapp:app
-
-The ``--manage-script-name`` will move the handling of ``SCRIPT_NAME`` to
-uwsgi, since its smarter about that. It is used together with the ``--mount``
-directive which will make requests to ``/yourapplication`` be directed to
-``myapp:app``, where ``myapp`` refers to the name of the file of your flask
-application (without extension). ``app`` is the callable inside of your
-application (usually the line reads ``app = Flask(__name__)``.
+The ``--manage-script-name`` will move the handling of ``SCRIPT_NAME`` to uwsgi,
+since its smarter about that. It is used together with the ``--mount`` directive
+which will make requests to ``/yourapplication`` be directed to ``myapp:app``.
+If your application is accessible at root level, you can use a single ``/``
+instead of ``/yourapplication``. ``myapp`` refers to the name of the file of
+your flask application (without extension) or the module which provides ``app``.
+``app`` is the callable inside of your application (usually the line reads
+``app = Flask(__name__)``.
If you want to deploy your flask application inside of a virtual environment,
you need to also add ``--virtualenv /path/to/virtual/environment``. You might
@@ -70,7 +66,7 @@ to have it in the URL root its a bit simpler::
uwsgi_pass unix:/tmp/yourapplication.sock;
}
-.. _nginx: http://nginx.org/
-.. _lighttpd: http://www.lighttpd.net/
+.. _nginx: https://nginx.org/
+.. _lighttpd: https://www.lighttpd.net/
.. _cherokee: http://cherokee-project.com/
.. _uwsgi: http://projects.unbit.it/uwsgi/
diff --git a/docs/deploying/wsgi-standalone.rst b/docs/deploying/wsgi-standalone.rst
index bd7b1006..ad43c144 100644
--- a/docs/deploying/wsgi-standalone.rst
+++ b/docs/deploying/wsgi-standalone.rst
@@ -25,7 +25,7 @@ For example, to run a Flask application with 4 worker processes (``-w
.. _Gunicorn: http://gunicorn.org/
.. _eventlet: http://eventlet.net/
-.. _greenlet: http://greenlet.readthedocs.org/en/latest/
+.. _greenlet: https://greenlet.readthedocs.io/en/latest/
Gevent
-------
@@ -41,7 +41,7 @@ event loop::
http_server.serve_forever()
.. _Gevent: http://www.gevent.org/
-.. _greenlet: http://greenlet.readthedocs.org/en/latest/
+.. _greenlet: https://greenlet.readthedocs.io/en/latest/
.. _libev: http://software.schmorp.de/pkg/libev.html
Twisted Web
@@ -97,9 +97,10 @@ localhost at port 8000, setting appropriate headers:
proxy_pass http://127.0.0.1:8000/;
proxy_redirect off;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
}
}
diff --git a/docs/errorhandling.rst b/docs/errorhandling.rst
index f51d7460..2791fec3 100644
--- a/docs/errorhandling.rst
+++ b/docs/errorhandling.rst
@@ -28,6 +28,46 @@ exception to the :attr:`~flask.Flask.logger`.
But there is more you can do, and we will cover some better setups to deal
with errors.
+Error Logging Tools
+-------------------
+
+Sending error mails, even if just for critical ones, can become
+overwhelming if enough users are hitting the error and log files are
+typically never looked at. This is why we recommend using `Sentry
+`_ for dealing with application errors. It's
+available as an Open Source project `on GitHub
+`__ and is also available as a `hosted version
+`_ which you can try for free. Sentry
+aggregates duplicate errors, captures the full stack trace and local
+variables for debugging, and sends you mails based on new errors or
+frequency thresholds.
+
+To use Sentry you need to install the `raven` client::
+
+ $ pip install raven
+
+And then add this to your Flask app::
+
+ from raven.contrib.flask import Sentry
+ sentry = Sentry(app, dsn='YOUR_DSN_HERE')
+
+Or if you are using factories you can also init it later::
+
+ from raven.contrib.flask import Sentry
+ sentry = Sentry(dsn='YOUR_DSN_HERE')
+
+ def create_app():
+ app = Flask(__name__)
+ sentry.init_app(app)
+ ...
+ return app
+
+The `YOUR_DSN_HERE` value needs to be replaced with the DSN value you get
+from your Sentry installation.
+
+Afterwards failures are automatically reported to Sentry and from there
+you can receive error notifications.
+
.. _error-handlers:
Error handlers
@@ -37,7 +77,7 @@ You might want to show custom error pages to the user when an error occurs.
This can be done by registering error handlers.
Error handlers are normal :ref:`views` but instead of being registered for
-routes they are registered for exceptions that are rised while trying to
+routes, they are registered for exceptions that are raised while trying to
do something else.
Registering
@@ -49,23 +89,24 @@ Register error handlers using :meth:`~flask.Flask.errorhandler` or
@app.errorhandler(werkzeug.exceptions.BadRequest)
def handle_bad_request(e):
return 'bad request!'
-
+
app.register_error_handler(400, lambda e: 'bad request!')
Those two ways are equivalent, but the first one is more clear and leaves
you with a function to call on your whim (and in tests). Note that
:exc:`werkzeug.exceptions.HTTPException` subclasses like
:exc:`~werkzeug.exceptions.BadRequest` from the example and their HTTP codes
-are interchangable when handed to the registration methods or decorator
+are interchangeable when handed to the registration methods or decorator
(``BadRequest.code == 400``).
-You are however not limited to a :exc:`~werkzeug.exceptions.HTTPException`
-or its code but can register a handler for every exception class you like.
+You are however not limited to :exc:`~werkzeug.exceptions.HTTPException`
+or HTTP status codes but can register a handler for every exception class you
+like.
-.. versionchanged:: 1.0
+.. versionchanged:: 0.11
- Errorhandlers are now prioritized by specifity instead of the order they're
- registered in.
+ Errorhandlers are now prioritized by specificity of the exception classes
+ they are registered for instead of the order they are registered in.
Handling
````````
@@ -74,7 +115,7 @@ Once an exception instance is raised, its class hierarchy is traversed,
and searched for in the exception classes for which handlers are registered.
The most specific handler is selected.
-E.g. if a instance of :exc:`ConnectionRefusedError` is raised, and a handler
+E.g. if an instance of :exc:`ConnectionRefusedError` is raised, and a handler
is registered for :exc:`ConnectionError` and :exc:`ConnectionRefusedError`,
the more specific :exc:`ConnectionRefusedError` handler is called on the
exception instance, and its response is shown to the user.
@@ -130,7 +171,7 @@ Logging to a File
Even if you get mails, you probably also want to log warnings. It's a
good idea to keep as much information around that might be required to
-debug a problem. By default as of Flask 1.0, errors are logged to your
+debug a problem. By default as of Flask 0.11, errors are logged to your
webserver's log automatically. Warnings however are not. Please note
that Flask itself will not issue any warnings in the core system, so it's
your responsibility to warn in the code if something seems odd.
@@ -175,7 +216,7 @@ A formatter can be instantiated with a format string. Note that
tracebacks are appended to the log entry automatically. You don't have to
do that in the log formatter format string.
-Here some example setups:
+Here are some example setups:
Email
`````
@@ -235,8 +276,9 @@ that this list is not complete, consult the official documentation of the
| ``%(lineno)d`` | Source line number where the logging call was |
| | issued (if available). |
+------------------+----------------------------------------------------+
-| ``%(asctime)s`` | Human-readable time when the LogRecord` was |
-| | created. By default this is of the form |
+| ``%(asctime)s`` | Human-readable time when the |
+| | :class:`~logging.LogRecord` was created. |
+| | By default this is of the form |
| | ``"2003-07-08 16:49:45,896"`` (the numbers after |
| | the comma are millisecond portion of the time). |
| | This can be changed by subclassing the formatter |
diff --git a/docs/extensiondev.rst b/docs/extensiondev.rst
index 918187fe..9ae6e6f1 100644
--- a/docs/extensiondev.rst
+++ b/docs/extensiondev.rst
@@ -29,13 +29,7 @@ be something like "Flask-SimpleXML". Make sure to include the name
This is how users can then register dependencies to your extension in
their :file:`setup.py` files.
-Flask sets up a redirect package called :data:`flask.ext` where users
-should import the extensions from. If you for instance have a package
-called ``flask_something`` users would import it as
-``flask.ext.something``. This is done to transition from the old
-namespace packages. See :ref:`ext-import-transition` for more details.
-
-But how do extensions look like themselves? An extension has to ensure
+But what do extensions look like themselves? An extension has to ensure
that it works with multiple Flask application instances at once. This is
a requirement because many people will use patterns like the
:ref:`app-factories` pattern to create their application as needed to aid
@@ -360,8 +354,7 @@ extension to be approved you have to follow these guidelines:
find a new maintainer including full source hosting transition and PyPI
access. If no maintainer is available, give access to the Flask core team.
1. An approved Flask extension must provide exactly one package or module
- named ``flask_extensionname``. They might also reside inside a
- ``flaskext`` namespace packages though this is discouraged now.
+ named ``flask_extensionname``.
2. It must ship a testing suite that can either be invoked with ``make test``
or ``python setup.py test``. For test suites invoked with ``make
test`` the extension has to ensure that all dependencies for the test
@@ -394,27 +387,24 @@ extension to be approved you have to follow these guidelines:
Python 2.7
-.. _ext-import-transition:
-
Extension Import Transition
---------------------------
-For a while we recommended using namespace packages for Flask extensions.
-This turned out to be problematic in practice because many different
-competing namespace package systems exist and pip would automatically
-switch between different systems and this caused a lot of problems for
-users.
+In early versions of Flask we recommended using namespace packages for Flask
+extensions, of the form ``flaskext.foo``. This turned out to be problematic in
+practice because it meant that multiple ``flaskext`` packages coexist.
+Consequently we have recommended to name extensions ``flask_foo`` over
+``flaskext.foo`` for a long time.
-Instead we now recommend naming packages ``flask_foo`` instead of the now
-deprecated ``flaskext.foo``. Flask 0.8 introduces a redirect import
-system that lets uses import from ``flask.ext.foo`` and it will try
-``flask_foo`` first and if that fails ``flaskext.foo``.
+Flask 0.8 introduced a redirect import system as a compatibility aid for app
+developers: Importing ``flask.ext.foo`` would try ``flask_foo`` and
+``flaskext.foo`` in that order.
-Flask extensions should urge users to import from ``flask.ext.foo``
-instead of ``flask_foo`` or ``flaskext_foo`` so that extensions can
-transition to the new package name without affecting users.
+As of Flask 0.11, most Flask extensions have transitioned to the new naming
+schema. The ``flask.ext.foo`` compatibility alias is still in Flask 0.11 but is
+now deprecated -- you should use ``flask_foo``.
-.. _OAuth extension: http://pythonhosted.org/Flask-OAuth/
+.. _OAuth extension: https://pythonhosted.org/Flask-OAuth/
.. _mailinglist: http://flask.pocoo.org/mailinglist/
.. _IRC channel: http://flask.pocoo.org/community/irc/
diff --git a/docs/extensions.rst b/docs/extensions.rst
index 748b11b3..6deb9652 100644
--- a/docs/extensions.rst
+++ b/docs/extensions.rst
@@ -1,3 +1,5 @@
+.. _extensions:
+
Flask Extensions
================
@@ -18,10 +20,17 @@ Using Extensions
Extensions typically have documentation that goes along that shows how to
use it. There are no general rules in how extensions are supposed to
behave but they are imported from common locations. If you have an
-extension called ``Flask-Foo`` or ``Foo-Flask`` it will be always
-importable from ``flask.ext.foo``::
+extension called ``Flask-Foo`` or ``Foo-Flask`` it should be always
+importable from ``flask_foo``::
- from flask.ext import foo
+ import flask_foo
+
+Building Extensions
+-------------------
+
+While `Flask Extension Registry`_ contains many Flask extensions, you may not find
+an extension that fits your need. If this is the case, you can always create your own.
+Consider reading :ref:`extension-dev` to develop your own Flask extension.
Flask Before 0.8
----------------
@@ -44,5 +53,6 @@ And here is how you can use it::
Once the ``flaskext_compat`` module is activated the :data:`flask.ext` will
exist and you can start importing from there.
+
.. _Flask Extension Registry: http://flask.pocoo.org/extensions/
-.. _flaskext_compat.py: https://raw.githubusercontent.com/mitsuhiko/flask/master/scripts/flaskext_compat.py
+.. _flaskext_compat.py: https://raw.githubusercontent.com/pallets/flask/master/scripts/flaskext_compat.py
diff --git a/docs/htmlfaq.rst b/docs/htmlfaq.rst
index cba99fa1..0b6ff504 100644
--- a/docs/htmlfaq.rst
+++ b/docs/htmlfaq.rst
@@ -30,7 +30,7 @@ the (X)HTML generation on the web is based on non-XML template engines
(such as Jinja, the one used in Flask) which do not protect you from
accidentally creating invalid XHTML. There are XML based template engines,
such as Kid and the popular Genshi, but they often come with a larger
-runtime overhead and, are not as straightforward to use because they have
+runtime overhead and are not as straightforward to use because they have
to obey XML rules.
The majority of users, however, assumed they were properly using XHTML.
diff --git a/docs/installation.rst b/docs/installation.rst
index 4f1ceaaf..96c363f5 100644
--- a/docs/installation.rst
+++ b/docs/installation.rst
@@ -40,24 +40,20 @@ installations of Python, one for each project. It doesn't actually install
separate copies of Python, but it does provide a clever way to keep different
project environments isolated. Let's see how virtualenv works.
-If you are on Mac OS X or Linux, chances are that one of the following two
-commands will work for you::
-
- $ sudo easy_install virtualenv
-
-or even better::
+If you are on Mac OS X or Linux, chances are that the following
+command will work for you::
$ sudo pip install virtualenv
-One of these will probably install virtualenv on your system. Maybe it's even
+It will probably install virtualenv on your system. Maybe it's even
in your package manager. If you use Ubuntu, try::
$ sudo apt-get install python-virtualenv
-If you are on Windows and don't have the :command:`easy_install` command, you must
+If you are on Windows and don't have the ``easy_install`` command, you must
install it first. Check the :ref:`windows-easy-install` section for more
information about how to do that. Once you have it installed, run the same
-commands as above, but without the :command:`sudo` prefix.
+commands as above, but without the ``sudo`` prefix.
Once you have virtualenv installed, just fire up a shell and create
your own environment. I usually create a project folder and a :file:`venv`
@@ -76,7 +72,7 @@ corresponding environment. On OS X and Linux, do the following::
If you are a Windows user, the following command is for you::
- $ venv\scripts\activate
+ $ venv\Scripts\activate
Either way, you should now be using your virtualenv (notice how the prompt of
your shell has changed to show the active environment).
@@ -99,24 +95,24 @@ System-Wide Installation
------------------------
This is possible as well, though I do not recommend it. Just run
-:command:`pip` with root privileges::
+``pip`` with root privileges::
$ sudo pip install Flask
(On Windows systems, run it in a command-prompt window with administrator
-privileges, and leave out :command:`sudo`.)
+privileges, and leave out ``sudo``.)
Living on the Edge
------------------
If you want to work with the latest version of Flask, there are two ways: you
-can either let :command:`pip` pull in the development version, or you can tell
+can either let ``pip`` pull in the development version, or you can tell
it to operate on a git checkout. Either way, virtualenv is recommended.
Get the git checkout in a new virtualenv and run in development mode::
- $ git clone http://github.com/mitsuhiko/flask.git
+ $ git clone https://github.com/pallets/flask.git
Initialized empty Git repository in ~/dev/flask/.git/
$ cd flask
$ virtualenv venv
@@ -131,40 +127,34 @@ This will pull in the dependencies and activate the git head as the current
version inside the virtualenv. Then all you have to do is run ``git pull
origin`` to update to the latest version.
-
.. _windows-easy-install:
`pip` and `setuptools` on Windows
---------------------------------
-Sometimes getting the standard "Python packaging tools" like *pip*, *setuptools*
-and *virtualenv* can be a little trickier, but nothing very hard. The two crucial
-packages you will need are setuptools and pip - these will let you install
-anything else (like virtualenv). Fortunately there are two "bootstrap scripts"
-you can run to install either.
+Sometimes getting the standard "Python packaging tools" like ``pip``, ``setuptools``
+and ``virtualenv`` can be a little trickier, but nothing very hard. The crucial
+package you will need is pip - this will let you install
+anything else (like virtualenv). Fortunately there is a "bootstrap script"
+you can run to install.
-If you don't currently have either, then `get-pip.py` will install both for you
-(you won't need to run ez_setup.py).
+If you don't currently have ``pip``, then `get-pip.py` will install it for you.
`get-pip.py`_
-To install the latest setuptools, you can use its bootstrap file:
-
-`ez_setup.py`_
-
-Either should be double-clickable once you download them. If you already have pip,
+It should be double-clickable once you download it. If you already have ``pip``,
you can upgrade them by running::
> pip install --upgrade pip setuptools
-Most often, once you pull up a command prompt you want to be able to type :command:`pip`
-and :command:`python` which will run those things, but this might not automatically happen
+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!).
To fix this, you should be able to navigate to your Python install directory
-(e.g :file:`C:\Python27`), then go to :file:`Tools`, then :file:`Scripts`; then find the
+(e.g :file:`C:\Python27`), then go to :file:`Tools`, then :file:`Scripts`, then find the
:file:`win_add2path.py` file and run that. Open a **new** Command Prompt and
-check that you can now just type :command:`python` to bring up the interpreter.
+check that you can now just type ``python`` to bring up the interpreter.
Finally, to install `virtualenv`_, you can simply run::
@@ -172,5 +162,4 @@ Finally, to install `virtualenv`_, you can simply run::
Then you can be off on your way following the installation instructions above.
-.. _get-pip.py: https://raw.githubusercontent.com/pypa/pip/master/contrib/get-pip.py
-.. _ez_setup.py: https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
+.. _get-pip.py: https://bootstrap.pypa.io/get-pip.py
diff --git a/docs/patterns/apierrors.rst b/docs/patterns/apierrors.rst
index ce5c8446..90e8c13d 100644
--- a/docs/patterns/apierrors.rst
+++ b/docs/patterns/apierrors.rst
@@ -2,7 +2,7 @@ Implementing API Exceptions
===========================
It's very common to implement RESTful APIs on top of Flask. One of the
-first thing that developers run into is the realization that the builtin
+first things that developers run into is the realization that the builtin
exceptions are not expressive enough for APIs and that the content type of
:mimetype:`text/html` they are emitting is not very useful for API consumers.
diff --git a/docs/patterns/appdispatch.rst b/docs/patterns/appdispatch.rst
index 3ff99e09..726850e2 100644
--- a/docs/patterns/appdispatch.rst
+++ b/docs/patterns/appdispatch.rst
@@ -4,11 +4,11 @@ Application Dispatching
=======================
Application dispatching is the process of combining multiple Flask
-applications on the WSGI level. You can not only combine Flask
-applications into something larger but any WSGI application. This would
-even allow you to run a Django and a Flask application in the same
-interpreter side by side if you want. The usefulness of this depends on
-how the applications work internally.
+applications on the WSGI level. You can combine not only Flask
+applications but any WSGI application. This would allow you to run a
+Django and a Flask application in the same interpreter side by side if
+you want. The usefulness of this depends on how the applications work
+internally.
The fundamental difference from the :ref:`module approach
` is that in this case you are running the same or
@@ -31,7 +31,7 @@ Note that :func:`run_simple ` is not intended for
use in production. Use a :ref:`full-blown WSGI server `.
In order to use the interactive debugger, debugging must be enabled both on
-the application and the simple server, here is the "hello world" example with
+the application and the simple server. Here is the "hello world" example with
debugging and :func:`run_simple `::
from flask import Flask
@@ -56,7 +56,7 @@ If you have entirely separated applications and you want them to work next
to each other in the same Python interpreter process you can take
advantage of the :class:`werkzeug.wsgi.DispatcherMiddleware`. The idea
here is that each Flask application is a valid WSGI application and they
-are combined by the dispatcher middleware into a larger one that
+are combined by the dispatcher middleware into a larger one that is
dispatched based on prefix.
For example you could have your main application run on ``/`` and your
diff --git a/docs/patterns/appfactories.rst b/docs/patterns/appfactories.rst
index bcac210c..fdbde504 100644
--- a/docs/patterns/appfactories.rst
+++ b/docs/patterns/appfactories.rst
@@ -6,7 +6,7 @@ Application Factories
If you are already using packages and blueprints for your application
(:ref:`blueprints`) there are a couple of really nice ways to further improve
the experience. A common pattern is creating the application object when
-the blueprint is imported. But if you move the creation of this object,
+the blueprint is imported. But if you move the creation of this object
into a function, you can then create multiple instances of this app later.
So why would you want to do this?
@@ -60,7 +60,7 @@ Factories & Extensions
It's preferable to create your extensions and app factories so that the
extension object does not initially get bound to the application.
-Using `Flask-SQLAlchemy `_,
+Using `Flask-SQLAlchemy `_,
as an example, you should not do something along those lines::
def create_app(config_filename):
@@ -99,7 +99,8 @@ an application::
It can then be used with the :command:`flask` command::
- flask --app=exampleapp run
+ export FLASK_APP=exampleapp
+ flask run
Factory Improvements
--------------------
diff --git a/docs/patterns/celery.rst b/docs/patterns/celery.rst
index 52155f62..673d953b 100644
--- a/docs/patterns/celery.rst
+++ b/docs/patterns/celery.rst
@@ -36,7 +36,7 @@ This is all that is necessary to properly integrate Celery with Flask::
from celery import Celery
def make_celery(app):
- celery = Celery(app.import_name, backend=app.config['CELERY_BACKEND'],
+ celery = Celery(app.import_name, backend=app.config['CELERY_RESULT_BACKEND'],
broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
TaskBase = celery.Task
diff --git a/docs/patterns/deferredcallbacks.rst b/docs/patterns/deferredcallbacks.rst
index 83d4fb49..886ae40a 100644
--- a/docs/patterns/deferredcallbacks.rst
+++ b/docs/patterns/deferredcallbacks.rst
@@ -56,9 +56,9 @@ this the following function needs to be registered as
A Practical Example
-------------------
-Now we can easily at any point in time register a function to be called at
-the end of this particular request. For example you can remember the
-current language of the user in a cookie in the before-request function::
+At any time during a request, we can register a function to be called at the
+end of the request. For example you can remember the current language of the
+user in a cookie in the before-request function::
from flask import request
diff --git a/docs/patterns/distribute.rst b/docs/patterns/distribute.rst
index 997ca89b..f4a07579 100644
--- a/docs/patterns/distribute.rst
+++ b/docs/patterns/distribute.rst
@@ -1,13 +1,12 @@
.. _distribute-deployment:
-Deploying with Distribute
+Deploying with Setuptools
=========================
-`distribute`_, formerly setuptools, is an extension library that is
-commonly used to (like the name says) distribute Python libraries and
-extensions. It extends distutils, a basic module installation system
-shipped with Python to also support various more complex constructs that
-make larger applications easier to distribute:
+`Setuptools`_, is an extension library that is commonly used to
+distribute Python libraries and extensions. It extends distutils, a basic
+module installation system shipped with Python to also support various more
+complex constructs that make larger applications easier to distribute:
- **support for dependencies**: a library or application can declare a
list of other libraries it depends on which will be installed
@@ -16,34 +15,32 @@ make larger applications easier to distribute:
Python installation. This makes it possible to query information
provided by one package from another package. The best known feature of
this system is the entry point support which allows one package to
- declare an "entry point" another package can hook into to extend the
+ declare an "entry point" that another package can hook into to extend the
other package.
-- **installation manager**: :command:`easy_install`, which comes with distribute
- can install other libraries for you. You can also use `pip`_ which
- sooner or later will replace :command:`easy_install` which does more than just
- installing packages for you.
+- **installation manager**: :command:`pip` can install other libraries for you.
-Flask itself, and all the libraries you can find on the cheeseshop
-are distributed with either distribute, the older setuptools or distutils.
+If you have Python 2 (>=2.7.9) or Python 3 (>=3.4) installed from python.org,
+you will already have pip and setuptools on your system. Otherwise, you
+will need to install them yourself.
+
+Flask itself, and all the libraries you can find on PyPI are distributed with
+either setuptools or distutils.
In this case we assume your application is called
:file:`yourapplication.py` and you are not using a module, but a :ref:`package
-`. Distributing resources with standard modules is
-not supported by `distribute`_ so we will not bother with it. If you have
-not yet converted your application into a package, head over to the
-:ref:`larger-applications` pattern to see how this can be done.
+`. If you have not yet converted your application into
+a package, head over to the :ref:`larger-applications` pattern to see
+how this can be done.
-A working deployment with distribute is the first step into more complex
+A working deployment with setuptools is the first step into more complex
and more automated deployment scenarios. If you want to fully automate
the process, also read the :ref:`fabric-deployment` chapter.
Basic Setup Script
------------------
-Because you have Flask running, you either have setuptools or distribute
-available on your system anyways. If you do not, fear not, there is a
-script to install it for you: `distribute_setup.py`_. Just download and
-run with your Python interpreter.
+Because you have Flask installed, you have setuptools available on your system.
+Flask already depends upon setuptools.
Standard disclaimer applies: :ref:`you better use a virtualenv
`.
@@ -52,10 +49,6 @@ Your setup code always goes into a file named :file:`setup.py` next to your
application. The name of the file is only convention, but because
everybody will look for a file with that name, you better not change it.
-Yes, even if you are using `distribute`, you are importing from a package
-called `setuptools`. `distribute` is fully backwards compatible with
-`setuptools`, so it also uses the same import name.
-
A basic :file:`setup.py` file for a Flask application looks like this::
from setuptools import setup
@@ -71,8 +64,8 @@ A basic :file:`setup.py` file for a Flask application looks like this::
)
Please keep in mind that you have to list subpackages explicitly. If you
-want distribute to lookup the packages for you automatically, you can use
-the `find_packages` function::
+want setuptools to lookup the packages for you automatically, you can use
+the ``find_packages`` function::
from setuptools import setup, find_packages
@@ -81,17 +74,36 @@ the `find_packages` function::
packages=find_packages()
)
-Most parameters to the `setup` function should be self explanatory,
-`include_package_data` and `zip_safe` might not be.
-`include_package_data` tells distribute to look for a :file:`MANIFEST.in` file
+Most parameters to the ``setup`` function should be self explanatory,
+``include_package_data`` and ``zip_safe`` might not be.
+``include_package_data`` tells setuptools to look for a :file:`MANIFEST.in` file
and install all the entries that match as package data. We will use this
to distribute the static files and templates along with the Python module
-(see :ref:`distributing-resources`). The `zip_safe` flag can be used to
+(see :ref:`distributing-resources`). The ``zip_safe`` flag can be used to
force or prevent zip Archive creation. In general you probably don't want
your packages to be installed as zip files because some tools do not
support them and they make debugging a lot harder.
+Tagging Builds
+--------------
+
+It is useful to distinguish between release and development builds. Add a
+:file:`setup.cfg` file to configure these options.
+
+ [egg_info]
+ tag_build = .dev
+ tag_date = 1
+
+ [aliases]
+ release = egg_info -RDb ''
+
+Running ``python setup.py sdist`` will create a development package
+with ".dev" and the current date appended: ``flaskr-1.0.dev20160314.tar.gz``.
+Running ``python setup.py release sdist`` will create a release package
+with only the version: ``flaskr-1.0.tar.gz``.
+
+
.. _distributing-resources:
Distributing Resources
@@ -99,7 +111,7 @@ Distributing Resources
If you try to install the package you just created, you will notice that
folders like :file:`static` or :file:`templates` are not installed for you. The
-reason for this is that distribute does not know which files to add for
+reason for this is that setuptools does not know which files to add for
you. What you should do, is to create a :file:`MANIFEST.in` file next to your
:file:`setup.py` file. This file lists all the files that should be added to
your tarball::
@@ -109,13 +121,13 @@ your tarball::
Don't forget that even if you enlist them in your :file:`MANIFEST.in` file, they
won't be installed for you unless you set the `include_package_data`
-parameter of the `setup` function to ``True``!
+parameter of the ``setup`` function to ``True``!
Declaring Dependencies
----------------------
-Dependencies are declared in the `install_requires` parameter as list.
+Dependencies are declared in the ``install_requires`` parameter as a list.
Each item in that list is the name of a package that should be pulled from
PyPI on installation. By default it will always use the most recent
version, but you can also provide minimum and maximum version
@@ -127,40 +139,39 @@ requirements. Here some examples::
'BrokenPackage>=0.7,<=1.0'
]
-I mentioned earlier that dependencies are pulled from PyPI. What if you
+As mentioned earlier, dependencies are pulled from PyPI. What if you
want to depend on a package that cannot be found on PyPI and won't be
because it is an internal package you don't want to share with anyone?
-Just still do as if there was a PyPI entry for it and provide a list of
-alternative locations where distribute should look for tarballs::
+Just do it as if there was a PyPI entry and provide a list of
+alternative locations where setuptools should look for tarballs::
dependency_links=['http://example.com/yourfiles']
Make sure that page has a directory listing and the links on the page are
pointing to the actual tarballs with their correct filenames as this is
-how distribute will find the files. If you have an internal company
-server that contains the packages, provide the URL to that server there.
+how setuptools will find the files. If you have an internal company
+server that contains the packages, provide the URL to that server.
Installing / Developing
-----------------------
To install your application (ideally into a virtualenv) just run the
-:file:`setup.py` script with the `install` parameter. It will install your
+:file:`setup.py` script with the ``install`` parameter. It will install your
application into the virtualenv's site-packages folder and also download
and install all dependencies::
$ python setup.py install
If you are developing on the package and also want the requirements to be
-installed, you can use the `develop` command instead::
+installed, you can use the ``develop`` command instead::
$ python setup.py develop
This has the advantage of just installing a link to the site-packages
folder instead of copying the data over. You can then continue to work on
-the code without having to run `install` again after each change.
+the code without having to run ``install`` again after each change.
-.. _distribute: https://pypi.python.org/pypi/distribute
.. _pip: https://pypi.python.org/pypi/pip
-.. _distribute_setup.py: http://python-distribute.org/distribute_setup.py
+.. _Setuptools: https://pypi.python.org/pypi/setuptools
diff --git a/docs/patterns/fabric.rst b/docs/patterns/fabric.rst
index 7270a569..3dbf2146 100644
--- a/docs/patterns/fabric.rst
+++ b/docs/patterns/fabric.rst
@@ -43,36 +43,25 @@ virtual environment::
env.hosts = ['server1.example.com', 'server2.example.com']
def pack():
- # create a new source distribution as tarball
+ # build the package
local('python setup.py sdist --formats=gztar', capture=False)
def deploy():
- # figure out the release name and version
+ # figure out the package name and version
dist = local('python setup.py --fullname', capture=True).strip()
- # upload the source tarball to the temporary folder on the server
- put('dist/%s.tar.gz' % dist, '/tmp/yourapplication.tar.gz')
- # create a place where we can unzip the tarball, then enter
- # that directory and unzip it
- run('mkdir /tmp/yourapplication')
- with cd('/tmp/yourapplication'):
- run('tar xzf /tmp/yourapplication.tar.gz')
- # now setup the package with our virtual environment's
- # python interpreter
- run('/var/www/yourapplication/env/bin/python setup.py install')
- # now that all is set up, delete the folder again
- run('rm -rf /tmp/yourapplication /tmp/yourapplication.tar.gz')
- # and finally touch the .wsgi file so that mod_wsgi triggers
- # a reload of the application
- run('touch /var/www/yourapplication.wsgi')
+ filename = '%s.tar.gz' % dist
+
+ # upload the package to the temporary folder on the server
+ put('dist/%s' % filename, '/tmp/%s' % filename)
-The example above is well documented and should be straightforward. Here
-a recap of the most common commands fabric provides:
+ # install the package in the application's virtualenv with pip
+ run('/var/www/yourapplication/env/bin/pip install /tmp/%s' % filename)
-- `run` - executes a command on a remote server
-- `local` - executes a command on the local machine
-- `put` - uploads a file to the remote server
-- `cd` - changes the directory on the serverside. This has to be used
- in combination with the ``with`` statement.
+ # remove the uploaded package
+ run('rm -r /tmp/%s' % filename)
+
+ # touch the .wsgi file to trigger a reload in mod_wsgi
+ run('touch /var/www/yourapplication.wsgi')
Running Fabfiles
----------------
@@ -156,6 +145,7 @@ location where it's expected (eg: :file:`/var/www/yourapplication`).
Either way, in our case here we only expect one or two servers and we can
upload them ahead of time by hand.
+
First Deployment
----------------
diff --git a/docs/patterns/favicon.rst b/docs/patterns/favicon.rst
index acdee24b..21ea767f 100644
--- a/docs/patterns/favicon.rst
+++ b/docs/patterns/favicon.rst
@@ -49,5 +49,5 @@ web server's documentation.
See also
--------
-* The `Favicon `_ article on
+* The `Favicon `_ article on
Wikipedia
diff --git a/docs/patterns/fileuploads.rst b/docs/patterns/fileuploads.rst
index 10aa15f2..1c4b0d36 100644
--- a/docs/patterns/fileuploads.rst
+++ b/docs/patterns/fileuploads.rst
@@ -21,7 +21,7 @@ specific upload folder and displays a file to the user. Let's look at the
bootstrapping code for our application::
import os
- from flask import Flask, request, redirect, url_for
+ from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = '/path/to/the/uploads'
@@ -40,14 +40,14 @@ your users to be able to upload everything there if the server is directly
sending out the data to the client. That way you can make sure that users
are not able to upload HTML files that would cause XSS problems (see
:ref:`xss`). Also make sure to disallow ``.php`` files if the server
-executes them, but who has PHP installed on his server, right? :)
+executes them, but who has PHP installed on their server, right? :)
Next the functions that check if an extension is valid and that uploads
the file and redirects the user to the URL for the uploaded file::
def allowed_file(filename):
return '.' in filename and \
- filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
+ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/', methods=['GET', 'POST'])
def upload_file():
@@ -58,7 +58,7 @@ the file and redirects the user to the URL for the uploaded file::
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
- # submit a empty part without filename
+ # submit an empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
@@ -71,9 +71,9 @@ the file and redirects the user to the URL for the uploaded file::
Upload new File
Upload new File
-
'''
@@ -104,9 +104,9 @@ before storing it directly on the filesystem.
>>> secure_filename('../../../../home/username/.bashrc')
'home_username_.bashrc'
-Now one last thing is missing: the serving of the uploaded files. In the
-:func:`upload_file()` we redirect the user to
-``url_for('uploaded_file', filename=filename)``, that is, ``/uploads/filename``.
+Now one last thing is missing: the serving of the uploaded files. In the
+:func:`upload_file()` we redirect the user to
+``url_for('uploaded_file', filename=filename)``, that is, ``/uploads/filename``.
So we write the :func:`uploaded_file` function to return the file of that name. As
of Flask 0.5 we can use a function that does that for us::
@@ -181,4 +181,4 @@ applications dealing with uploads, there is also a Flask extension called
blacklisting of extensions and more.
.. _jQuery: https://jquery.com/
-.. _Flask-Uploads: http://pythonhosted.org/Flask-Uploads/
+.. _Flask-Uploads: https://pythonhosted.org/Flask-Uploads/
diff --git a/docs/patterns/flashing.rst b/docs/patterns/flashing.rst
index b2de07ce..7efd1446 100644
--- a/docs/patterns/flashing.rst
+++ b/docs/patterns/flashing.rst
@@ -9,7 +9,9 @@ application. Flask provides a really simple way to give feedback to a
user with the flashing system. The flashing system basically makes it
possible to record a message at the end of a request and access it next
request and only next request. This is usually combined with a layout
-template that does this.
+template that does this. Note that browsers and sometimes web servers enforce
+a limit on cookie sizes. This means that flashing messages that are too
+large for session cookies causes message flashing to fail silently.
Simple Flashing
---------------
@@ -76,7 +78,7 @@ And here is the :file:`login.html` template which also inherits from
{% if error %}