diff --git a/.gitattributes b/.gitattributes index 8383fff9..6f9ff673 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -CHANGES merge=union +CHANGES.rst merge=union diff --git a/.travis.yml b/.travis.yml index e156d1b3..e487c353 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,9 @@ language: python matrix: include: - python: 3.6 - env: TOXENV=py,simplejson,devel,lowest,codecov,docs-html + env: TOXENV=py,simplejson,devel,lowest,codecov + - python: 3.6 + env: TOXENV=docs-html - python: 3.5 env: TOXENV=py,codecov - python: 3.4 @@ -15,9 +17,16 @@ matrix: env: TOXENV=py,codecov - python: nightly env: TOXENV=py + - os: osx + language: generic + env: TOXENV=py allow_failures: - python: nightly env: TOXENV=py + - os: osx + language: generic + env: TOXENV=py + fast_finish: true install: - pip install tox diff --git a/AUTHORS b/AUTHORS index 3237ea65..220046ed 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,40 +1,12 @@ -Flask is written and maintained by Armin Ronacher and -various contributors: +Flask is developed and maintained by the Pallets team and community +contributors. It was created by Armin Ronacher. The core maintainers +are: -Development Lead -```````````````` +- David Lord (davidism) +- Adrian Mönnich (ThiefMaster) +- Armin Ronacher (mitsuhiko) +- Marcus Unterwaditzer (untitaker) -- Armin Ronacher +A full list of contributors is available from git with:: -Patches and Suggestions -``````````````````````` - -- Adam Byrtek -- Adam Zapletal -- Ali Afshar -- Chris Edgemon -- Chris Grindstaff -- Christopher Grebs -- Daniel Neuhäuser -- Dan Sully -- David Lord @davidism -- Edmond Burnett -- Florent Xicluna -- Georg Brandl -- Hsiaoming Yang @lepture -- Jeff Widman @jeffwidman -- Joshua Bronson @jab -- Justin Quick -- Kenneth Reitz -- Keyan Pishdadian -- Marian Sigler -- Martijn Pieters -- Matt Campell -- Matthew Frazier -- Michael van Tellingen -- Ron DuPlain -- Sebastien Estienne -- Simon Sapin -- Stephane Wirtel -- Thomas Schranz -- Zhao Xiaohong + git shortlog -sne diff --git a/CHANGES.rst b/CHANGES.rst index b1b65a45..58ea4b16 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,5 @@ +.. currentmodule:: flask + Flask Changelog =============== @@ -11,114 +13,126 @@ unreleased - Bump minimum dependency versions to the latest stable versions: Werkzeug >= 0.14, Jinja >= 2.10, itsdangerous >= 0.24, Click >= 5.1. (`#2586`_) -- 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. (`#2193`_) -- 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`_) -- Add ``routes`` CLI command to output routes registered on the application. - (`#2259`_) +- Skip :meth:`app.run ` when a Flask application is run from + the command line. This avoids some behavior that was confusing to + debug. +- Change the default for :data:`JSONIFY_PRETTYPRINT_REGULAR` to + ``False``. :func:`~json.jsonify` returns a compact format by default, + and an indented format in debug mode. (`#2193`_) +- :meth:`Flask.__init__ ` accepts the ``host_matching`` argument + and sets it on :attr:`~Flask.url_map`. (`#1559`_) +- :meth:`Flask.__init__ ` accepts the ``static_host`` argument + and passes it as the ``host`` argument when defining the static route. + (`#1559`_) +- :func:`send_file` supports Unicode in ``attachment_filename``. + (`#2223`_) +- Pass ``_scheme`` argument from :func:`url_for` to + :meth:`~Flask.handle_url_build_error`. (`#2017`_) +- :meth:`~Flask.add_url_rule` accepts the ``provide_automatic_options`` + argument to disable adding the ``OPTIONS`` method. (`#1489`_) +- :class:`~views.MethodView` subclasses 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 :attr:`~Blueprint.json_encoder` and + :attr:`~Blueprint.json_decoder` attributes to override the app's + encoder and decoder. (`#1898`_) +- :meth:`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`_) +- Add ``routes`` CLI command to output routes registered on the + application. (`#2259`_) - Show warning when session cookie domain is a bare hostname or an IP - address, as these may not behave properly in some browsers, such as Chrome. - (`#2282`_) + address, as these may not behave properly in some browsers, such as + Chrome. (`#2282`_) - Allow IP address as exact session cookie domain. (`#2282`_) -- ``SESSION_COOKIE_DOMAIN`` is set if it is detected through ``SERVER_NAME``. - (`#2282`_) -- Auto-detect zero-argument app factory called ``create_app`` or ``make_app`` - from ``FLASK_APP``. (`#2297`_) -- Factory functions are not required to take a ``script_info`` parameter to - work with the ``flask`` command. If they take a single parameter or a - parameter named ``script_info``, the ``ScriptInfo`` object will be passed. - (`#2319`_) -- FLASK_APP=myproject.app:create_app('dev') support. -- ``FLASK_APP`` can be set to an app factory, with arguments if needed, for - example ``FLASK_APP=myproject.app:create_app('dev')``. (`#2326`_) -- ``FLASK_APP`` can point to local packages that are not installed in dev mode, - although `pip install -e` should still be preferred. (`#2414`_) -- ``View.provide_automatic_options = True`` is set on the view function from - ``View.as_view``, to be detected in ``app.add_url_rule``. (`#2316`_) +- ``SESSION_COOKIE_DOMAIN`` is set if it is detected through + ``SERVER_NAME``. (`#2282`_) +- Auto-detect zero-argument app factory called ``create_app`` or + ``make_app`` from ``FLASK_APP``. (`#2297`_) +- Factory functions are not required to take a ``script_info`` parameter + to work with the ``flask`` command. If they take a single parameter or + a parameter named ``script_info``, the :class:`~cli.ScriptInfo` object + will be passed. (`#2319`_) +- ``FLASK_APP`` can be set to an app factory, with arguments if needed, + for example ``FLASK_APP=myproject.app:create_app('dev')``. (`#2326`_) +- ``FLASK_APP`` can point to local packages that are not installed in + editable mode, although ``pip install -e`` is still preferred. + (`#2414`_) +- The :class:`~views.View` class attribute + :attr:`~views.View.provide_automatic_options` is set in + :meth:`~views.View.as_view`, to be detected by + :meth:`~Flask.add_url_rule`. (`#2316`_) - Error handling will try handlers registered for ``blueprint, code``, - ``app, code``, ``blueprint, exception``, ``app, exception``. (`#2314`_) -- ``Cookie`` is added to the response's ``Vary`` header if the session is - accessed at all during the request (and it wasn't deleted). (`#2288`_) -- ``app.test_request_context()`` take ``subdomain`` and ``url_scheme`` - parameters for use when building base URL. (`#1621`_) -- Set ``APPLICATION_ROOT = '/'`` by default. This was already the implicit - default when it was set to ``None``. -- ``TRAP_BAD_REQUEST_ERRORS`` is enabled by default in debug mode. - ``BadRequestKeyError`` has a message with the bad key in debug mode instead - of the generic bad request message. (`#2348`_) -- Allow registering new tags with ``TaggedJSONSerializer`` to support - storing other types in the session cookie. (`#2352`_) -- Only open the session if the request has not been pushed onto the context - stack yet. This allows ``stream_with_context`` generators to access the same - session that the containing view uses. (`#2354`_) -- Add ``json`` keyword argument for the test client request methods. This will - dump the given object as JSON and set the appropriate content type. - (`#2358`_) -- Extract JSON handling to a mixin applied to both the request and response - classes used by Flask. This adds the ``is_json`` and ``get_json`` methods to - the response to make testing JSON response much easier. (`#2358`_) -- Removed error handler caching because it caused unexpected results for some - exception inheritance hierarchies. Register handlers explicitly for each - exception if you don't want to traverse the MRO. (`#2362`_) + ``app, code``, ``blueprint, exception``, ``app, exception``. + (`#2314`_) +- ``Cookie`` is added to the response's ``Vary`` header if the session + is accessed at all during the request (and not deleted). (`#2288`_) +- :meth:`~Flask.test_request_context` accepts ``subdomain`` and + ``url_scheme`` arguments for use when building the base URL. + (`#1621`_) +- Set :data:`APPLICATION_ROOT` to ``'/'`` by default. This was already + the implicit default when it was set to ``None``. +- :data:`TRAP_BAD_REQUEST_ERRORS` is enabled by default in debug mode. + ``BadRequestKeyError`` has a message with the bad key in debug mode + instead of the generic bad request message. (`#2348`_) +- Allow registering new tags with + :class:`~json.tag.TaggedJSONSerializer` to support storing other types + in the session cookie. (`#2352`_) +- Only open the session if the request has not been pushed onto the + context stack yet. This allows :func:`~stream_with_context` + generators to access the same session that the containing view uses. + (`#2354`_) +- Add ``json`` keyword argument for the test client request methods. + This will dump the given object as JSON and set the appropriate + content type. (`#2358`_) +- Extract JSON handling to a mixin applied to both the :class:`Request` + and :class:`Response` classes. This adds the :meth:`~Response.is_json` + and :meth:`~Response.get_json` methods to the response to make testing + JSON response much easier. (`#2358`_) +- Removed error handler caching because it caused unexpected results for + some exception inheritance hierarchies. Register handlers explicitly + for each exception if you want to avoid traversing the MRO. (`#2362`_) - Fix incorrect JSON encoding of aware, non-UTC datetimes. (`#2374`_) -- Template auto reloading will honor the ``run`` command's ``debug`` flag even - if ``app.jinja_env`` was already accessed. (`#2373`_) +- Template auto reloading will honor debug mode even even if + :attr:`~Flask.jinja_env` was already accessed. (`#2373`_) - The following old deprecated code was removed. (`#2385`_) - ``flask.ext`` - import extensions directly by their name instead of through the ``flask.ext`` namespace. For example, ``import flask.ext.sqlalchemy`` becomes ``import flask_sqlalchemy``. - - ``Flask.init_jinja_globals`` - extend ``Flask.create_jinja_environment`` - instead. - - ``Flask.error_handlers`` - tracked by ``Flask.error_handler_spec``, - use ``@app.errorhandler`` to register handlers. - - ``Flask.request_globals_class`` - use ``Flask.app_ctx_globals_class`` - instead. - - ``Flask.static_path`` - use ``Flask.static_url_path`` instead. - - ``Request.module`` - use ``Request.blueprint`` instead. - -- The ``request.json`` property is no longer deprecated. (`#1421`_) -- Support passing an existing ``EnvironBuilder`` or ``dict`` to - ``test_client.open``. (`#2412`_) -- The ``flask`` command and ``app.run`` will load environment variables using - from ``.env`` and ``.flaskenv`` files if python-dotenv is installed. - (`#2416`_) -- When passing a full URL to the test client, use the scheme in the URL instead - of the ``PREFERRED_URL_SCHEME``. (`#2430`_) -- ``app.logger`` has been simplified. ``LOGGER_NAME`` and - ``LOGGER_HANDLER_POLICY`` config was removed. The logger is always named - ``flask.app``. The level is only set on first access, it doesn't check - ``app.debug`` each time. Only one format is used, not different ones - depending on ``app.debug``. No handlers are removed, and a handler is only - added if no handlers are already configured. (`#2436`_) -- Blueprint view function name may not contain dots. (`#2450`_) -- Fix a ``ValueError`` caused by invalid Range requests in some cases. - (`#2526`_) -- The dev server now uses threads by default. (`#2529`_) -- Loading config files with ``silent=True`` will ignore ``ENOTDIR`` - errors. (`#2581`_) + - ``Flask.init_jinja_globals`` - extend + :meth:`Flask.create_jinja_environment` instead. + - ``Flask.error_handlers`` - tracked by + :attr:`Flask.error_handler_spec`, use :meth:`Flask.errorhandler` to + register handlers. + - ``Flask.request_globals_class`` - use + :attr:`Flask.app_ctx_globals_class` instead. + - ``Flask.static_path`` - use :attr:`Flask.static_url_path` instead. + - ``Request.module`` - use :attr:`Request.blueprint` instead. + +- The :attr:`Request.json` property is no longer deprecated. (`#1421`_) +- Support passing a :class:`~werkzeug.test.EnvironBuilder` or + ``dict`` to :meth:`test_client.open `. + (`#2412`_) +- The ``flask`` command and :meth:`Flask.run` will load environment + variables from ``.env`` and ``.flaskenv`` files if python-dotenv is + installed. (`#2416`_) +- When passing a full URL to the test client, the scheme in the URL is + used instead of :data:`PREFERRED_URL_SCHEME`. (`#2430`_) +- :attr:`Flask.logger` has been simplified. ``LOGGER_NAME`` and + ``LOGGER_HANDLER_POLICY`` config was removed. The logger is always + named ``flask.app``. The level is only set on first access, it doesn't + check :attr:`Flask.debug` each time. Only one format is used, not + different ones depending on :attr:`Flask.debug`. No handlers are + removed, and a handler is only added if no handlers are already + configured. (`#2436`_) +- Blueprint view function names may not contain dots. (`#2450`_) +- Fix a ``ValueError`` caused by invalid ``Range`` requests in some + cases. (`#2526`_) +- The development server uses threads by default. (`#2529`_) +- Loading config files with ``silent=True`` will ignore + :data:`~errno.ENOTDIR` errors. (`#2581`_) - Pass ``--cert`` and ``--key`` options to ``flask run`` to run the development server over HTTPS. (`#2606`_) - Added :data:`SESSION_COOKIE_SAMESITE` to control the ``SameSite`` @@ -127,6 +141,7 @@ unreleased .. _pallets/meta#24: https://github.com/pallets/meta/issues/24 .. _#1421: https://github.com/pallets/flask/issues/1421 .. _#1489: https://github.com/pallets/flask/pull/1489 +.. _#1559: https://github.com/pallets/flask/issues/1559 .. _#1621: https://github.com/pallets/flask/pull/1621 .. _#1898: https://github.com/pallets/flask/pull/1898 .. _#1936: https://github.com/pallets/flask/pull/1936 diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index ef02b732..a9bcace6 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -131,8 +131,22 @@ Read more about `coverage `_. Running the full test suite with ``tox`` will combine the coverage reports from all runs. -``make`` targets -~~~~~~~~~~~~~~~~ + +Building the docs +~~~~~~~~~~~~~~~~~ + +Build the docs in the ``docs`` directory using Sphinx:: + + cd docs + make html + +Open ``_build/html/index.html`` in your browser to view the docs. + +Read more about `Sphinx `_. + + +make targets +~~~~~~~~~~~~ Flask provides a ``Makefile`` with various shortcuts. They will ensure that all dependencies are installed. diff --git a/LICENSE b/LICENSE index a7da10e1..8f9252f4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,33 +1,31 @@ -Copyright (c) 2015 by Armin Ronacher and contributors. See AUTHORS -for more details. +Copyright © 2010 by the Pallets team. Some rights reserved. -Redistribution and use in source and binary forms of the software as well -as documentation, with or without modification, are permitted provided -that the following conditions are met: +Redistribution and use in source and binary forms of the software as +well as documentation, with or without modification, are permitted +provided that the following conditions are met: -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. -* The names of the contributors may not be used to endorse or - promote products derived from this software without specific - prior written permission. +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT -NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/MANIFEST.in b/MANIFEST.in index 3616212e..d8a725b5 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ -include Makefile CHANGES LICENSE AUTHORS tox.ini +include Makefile CHANGES.rst LICENSE AUTHORS tox.ini graft artwork graft tests diff --git a/Makefile b/Makefile index aef8a782..7df5fd00 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,6 @@ test: clean-pyc install-dev pytest coverage: clean-pyc install-dev - pip install -q -e .[test] coverage run -m pytest coverage report coverage html @@ -34,20 +33,3 @@ clean-pyc: find . -name '*.pyc' -exec rm -f {} + find . -name '*.pyo' -exec rm -f {} + find . -name '*~' -exec rm -f {} + - -upload-docs: - $(MAKE) -C docs html dirhtml latex epub - $(MAKE) -C docs/_build/latex all-pdf - cd docs/_build/; mv html flask-docs; zip -r flask-docs.zip flask-docs; mv flask-docs html - rsync -a docs/_build/dirhtml/ flow.srv.pocoo.org:/srv/websites/flask.pocoo.org/docs/ - rsync -a docs/_build/latex/Flask.pdf flow.srv.pocoo.org:/srv/websites/flask.pocoo.org/docs/flask-docs.pdf - rsync -a docs/_build/flask-docs.zip flow.srv.pocoo.org:/srv/websites/flask.pocoo.org/docs/flask-docs.zip - rsync -a docs/_build/epub/Flask.epub flow.srv.pocoo.org:/srv/websites/flask.pocoo.org/docs/flask-docs.epub - -# ebook-convert docs: http://manual.calibre-ebook.com/cli/ebook-convert.html -ebook: - @echo 'Using .epub from `make upload-docs` to create .mobi.' - @echo 'Command `ebook-covert` is provided by calibre package.' - @echo 'Requires X-forwarding for Qt features used in conversion (ssh -X).' - @echo 'Do not mind "Invalid value for ..." CSS errors if .mobi renders.' - ssh -X pocoo.org ebook-convert /var/www/flask.pocoo.org/docs/flask-docs.epub /var/www/flask.pocoo.org/docs/flask-docs.mobi --cover http://flask.pocoo.org/docs/_images/logo-full.png --authors 'Armin Ronacher' diff --git a/README b/README deleted file mode 100644 index 75c5e7b1..00000000 --- a/README +++ /dev/null @@ -1,49 +0,0 @@ - - - // Flask // - - web development, one drop at a time - - - ~ What is Flask? - - Flask is a microframework for Python based on Werkzeug - and Jinja2. It's intended for getting started very quickly - and was developed with best intentions in mind. - - ~ Is it ready? - - It's still not 1.0 but it's shaping up nicely and is - already widely used. Consider the API to slightly - improve over time but we don't plan on breaking it. - - ~ What do I need? - - All dependencies are installed by using `pip install Flask`. - We encourage you to use a virtualenv. Check the docs for - complete installation and usage instructions. - - ~ Where are the docs? - - Go to http://flask.pocoo.org/docs/ for a prebuilt version - of the current documentation. Otherwise build them yourself - from the sphinx sources in the docs folder. - - ~ Where are the tests? - - Good that you're asking. The tests are in the - tests/ folder. To run the tests use the - `pytest` testing tool: - - $ pytest - - Details on contributing can be found in CONTRIBUTING.rst - - ~ Where can I get help? - - Either use the #pocoo IRC channel on irc.freenode.net or - ask on the mailinglist: http://flask.pocoo.org/mailinglist/ - - See http://flask.pocoo.org/community/ for more resources. - - diff --git a/README.rst b/README.rst new file mode 100644 index 00000000..ef01ca5b --- /dev/null +++ b/README.rst @@ -0,0 +1,62 @@ +Flask +===== + +Flask is a lightweight `WSGI`_ web application framework. It is designed +to make getting started quick and easy, with the ability to scale up to +complex applications. It began as a simple wrapper around `Werkzeug`_ +and `Jinja`_ and has become one of the most popular Python web +application frameworks. + +Flask offers suggestions, but doesn't enforce any dependencies or +project layout. It is up to the developer to choose the tools and +libraries they want to use. There are many extensions provided by the +community that make adding new functionality easy. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + pip install -U Flask + + +A Simple Example +---------------- + +.. code-block:: python + + from flask import Flask + + app = Flask(__name__) + + @app.route('/') + def hello(): + return 'Hello, World!' + +.. code-block:: none + + $ FLASK_APP=hello.py flask run + * Running on http://localhost:5000/ + + +Links +----- + +* Website: https://www.palletsprojects.com/p/flask/ +* Releases: https://pypi.org/project/Flask/ +* Code: https://github.com/pallets/flask +* Issue tracker: https://github.com/pallets/flask/issues +* Test status: + + * Linux, Mac: https://travis-ci.org/pallets/flask + * Windows: https://ci.appveyor.com/project/pallets/flask + +* Test coverage: https://codecov.io/gh/pallets/flask + +.. _WSGI: https://wsgi.readthedocs.io +.. _Werkzeug: https://www.palletsprojects.com/p/werkzeug/ +.. _Jinja: https://www.palletsprojects.com/p/jinja/ +.. _pip: https://pip.pypa.io/en/stable/quickstart/ diff --git a/docs/index.rst b/docs/index.rst index 617104ee..5e9f8426 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -4,28 +4,23 @@ Welcome to Flask ================ .. image:: _static/logo-full.png - :alt: Flask: web development, one drop at a time - :class: floatingflask + :alt: Flask: web development, one drop at a time + :class: floatingflask -Welcome to Flask's documentation. This documentation is divided into -different parts. I recommend that you get started with -:ref:`installation` and then head over to the :ref:`quickstart`. -Besides the quickstart, there is also a more detailed :ref:`tutorial` that -shows how to create a complete (albeit small) application with Flask. If -you'd rather dive into the internals of Flask, check out -the :ref:`api` documentation. Common patterns are described in the -:ref:`patterns` section. +Welcome to Flask's documentation. Get started with :ref:`installation` +and then get an overview with the :ref:`quickstart`. There is also a +more detailed :ref:`tutorial` that shows how to create a small but +complete application with Flask. Common patterns are described in the +:ref:`patterns` section. The rest of the docs desribe each component of +Flask in detail, with a full reference in the :ref:`api` section. -Flask depends on two external libraries: the `Jinja2`_ template -engine and the `Werkzeug`_ WSGI toolkit. These libraries are not documented -here. If you want to dive into their documentation, check out the -following links: +Flask depends on the `Jinja`_ template engine and the `Werkzeug`_ WSGI +toolkit. The documentation for these libraries can be found at: -- `Jinja2 Documentation `_ -- `Werkzeug Documentation `_ +- `Jinja documentation `_ +- `Werkzeug documentation `_ - -.. _Jinja2: http://jinja.pocoo.org/ -.. _Werkzeug: http://werkzeug.pocoo.org/ +.. _Jinja: https://www.palletsprojects.com/p/jinja/ +.. _Werkzeug: https://www.palletsprojects.com/p/werkzeug/ .. include:: contents.rst.inc diff --git a/scripts/flaskext_tester.py b/scripts/flaskext_tester.py deleted file mode 100644 index 93ab0ad7..00000000 --- a/scripts/flaskext_tester.py +++ /dev/null @@ -1,309 +0,0 @@ -# -*- coding: utf-8 -*- -""" - Flask Extension Tests - ~~~~~~~~~~~~~~~~~~~~~ - - Tests the Flask extensions. - - :copyright: (c) 2015 by Ali Afshar. - :license: BSD, see LICENSE for more details. -""" - -import os -import sys -import shutil -import urllib2 -import tempfile -import subprocess -import argparse - -from flask import json - -from setuptools.package_index import PackageIndex -from setuptools.archive_util import unpack_archive - -flask_svc_url = 'http://flask.pocoo.org/extensions/' - - -# OS X has awful paths when using mkstemp or gettempdir(). I don't -# care about security or clashes here, so pick something that is -# actually memorable. -if sys.platform == 'darwin': - _tempdir = '/private/tmp' -else: - _tempdir = tempfile.gettempdir() -tdir = _tempdir + '/flaskext-test' -flaskdir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) - - -# virtualenv hack *cough* -os.environ['PYTHONDONTWRITEBYTECODE'] = '' - - -RESULT_TEMPATE = u'''\ - -Flask-Extension Test Results - -

Flask-Extension Test Results

-

- This page contains the detailed test results for the test run of - all {{ 'approved' if approved }} Flask extensions. -

Summary

- - - - - - - {%- for result in results %} - {% set outcome = 'success' if result.success else 'failed' %} - - - {%- endfor %} - -
Extension - Version - Author - License - Outcome - {%- for iptr, _ in results[0].logs|dictsort %} - {{ iptr }} - {%- endfor %} -
{{ result.name }} - {{ result.version }} - {{ result.author }} - {{ result.license }} - {{ outcome }} - {%- for iptr, _ in result.logs|dictsort %} - see log - {%- endfor %} -
-

Test Logs

-

Detailed test logs for all tests on all platforms: -{%- for result in results %} - {%- for iptr, log in result.logs|dictsort %} -

- {{ result.name }} - {{ result.version }} [{{ iptr }}]

-
{{ log }}
- {%- endfor %} -{%- endfor %} -''' - - -def log(msg, *args): - print('[EXTTEST] ' + (msg % args)) - - -class TestResult(object): - - def __init__(self, name, folder, statuscode, interpreters): - intrptr = os.path.join(folder, '.tox/%s/bin/python' - % interpreters[0]) - self.statuscode = statuscode - self.folder = folder - self.success = statuscode == 0 - - def fetch(field): - try: - c = subprocess.Popen([intrptr, 'setup.py', - '--' + field], cwd=folder, - stdout=subprocess.PIPE) - return c.communicate()[0].strip() - except OSError: - return '?' - self.name = name - self.license = fetch('license') - self.author = fetch('author') - self.version = fetch('version') - - self.logs = {} - for interpreter in interpreters: - logfile = os.path.join(folder, '.tox/%s/log/test.log' - % interpreter) - if os.path.isfile(logfile): - self.logs[interpreter] = open(logfile).read() - else: - self.logs[interpreter] = '' - - -def create_tdir(): - try: - shutil.rmtree(tdir) - except Exception: - pass - os.mkdir(tdir) - - -def package_flask(): - distfolder = tdir + '/.flask-dist' - c = subprocess.Popen(['python', 'setup.py', 'sdist', '--formats=gztar', - '--dist', distfolder], cwd=flaskdir) - c.wait() - return os.path.join(distfolder, os.listdir(distfolder)[0]) - - -def get_test_command(checkout_dir): - if os.path.isfile(checkout_dir + '/Makefile'): - return 'make test' - return 'python setup.py test' - - -def fetch_extensions_list(): - req = urllib2.Request(flask_svc_url, headers={'accept':'application/json'}) - d = urllib2.urlopen(req).read() - data = json.loads(d) - for ext in data['extensions']: - yield ext - - -def checkout_extension(name): - log('Downloading extension %s to temporary folder', name) - root = os.path.join(tdir, name) - os.mkdir(root) - checkout_path = PackageIndex().download(name, root) - - unpack_archive(checkout_path, root) - path = None - for fn in os.listdir(root): - path = os.path.join(root, fn) - if os.path.isdir(path): - break - log('Downloaded to %s', path) - return path - - -tox_template = """[tox] -envlist=%(env)s - -[testenv] -deps= - %(deps)s - distribute - py -commands=bash flaskext-runtest.sh {envlogdir}/test.log -downloadcache=%(cache)s -""" - - -def create_tox_ini(checkout_path, interpreters, flask_dep): - tox_path = os.path.join(checkout_path, 'tox-flask-test.ini') - if not os.path.exists(tox_path): - with open(tox_path, 'w') as f: - f.write(tox_template % { - 'env': ','.join(interpreters), - 'cache': tdir, - 'deps': flask_dep - }) - return tox_path - - -def iter_extensions(only_approved=True): - for ext in fetch_extensions_list(): - if ext['approved'] or not only_approved: - yield ext['name'] - - -def test_extension(name, interpreters, flask_dep): - checkout_path = checkout_extension(name) - log('Running tests with tox in %s', checkout_path) - - # figure out the test command and write a wrapper script. We - # can't write that directly into the tox ini because tox does - # not invoke the command from the shell so we have no chance - # to pipe the output into a logfile. The /dev/null hack is - # to trick py.test (if used) into not guessing widths from the - # invoking terminal. - test_command = get_test_command(checkout_path) - log('Test command: %s', test_command) - f = open(checkout_path + '/flaskext-runtest.sh', 'w') - f.write(test_command + ' &> "$1" < /dev/null\n') - f.close() - - # if there is a tox.ini, remove it, it will cause troubles - # for us. Remove it if present, we are running tox ourselves - # afterall. - - create_tox_ini(checkout_path, interpreters, flask_dep) - rv = subprocess.call(['tox', '-c', 'tox-flask-test.ini'], cwd=checkout_path) - return TestResult(name, checkout_path, rv, interpreters) - - -def run_tests(extensions, interpreters): - results = {} - create_tdir() - log('Packaging Flask') - flask_dep = package_flask() - log('Running extension tests') - log('Temporary Environment: %s', tdir) - for name in extensions: - log('Testing %s', name) - result = test_extension(name, interpreters, flask_dep) - if result.success: - log('Extension test succeeded') - else: - log('Extension test failed') - results[name] = result - return results - - -def render_results(results, approved): - from jinja2 import Template - items = results.values() - items.sort(key=lambda x: x.name.lower()) - rv = Template(RESULT_TEMPATE, autoescape=True).render(results=items, - approved=approved) - fd, filename = tempfile.mkstemp(suffix='.html') - os.fdopen(fd, 'w').write(rv.encode('utf-8') + '\n') - return filename - - -def main(): - parser = argparse.ArgumentParser(description='Runs Flask extension tests') - parser.add_argument('--all', dest='all', action='store_true', - help='run against all extensions, not just approved') - parser.add_argument('--browse', dest='browse', action='store_true', - help='show browser with the result summary') - parser.add_argument('--env', dest='env', default='py25,py26,py27', - help='the tox environments to run against') - parser.add_argument('--extension=', dest='extension', default=None, - help='tests a single extension') - args = parser.parse_args() - - if args.extension is not None: - only_approved = False - extensions = [args.extension] - else: - only_approved = not args.all - extensions = iter_extensions(only_approved) - - results = run_tests(extensions, [x.strip() for x in args.env.split(',')]) - filename = render_results(results, only_approved) - if args.browse: - import webbrowser - webbrowser.open('file:///' + filename.lstrip('/')) - print('Results written to {}'.format(filename)) - - -if __name__ == '__main__': - main() diff --git a/scripts/make-release.py b/scripts/make-release.py old mode 100644 new mode 100755 index 7fb42787..e1ca54f8 --- a/scripts/make-release.py +++ b/scripts/make-release.py @@ -1,23 +1,13 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- -""" - make-release - ~~~~~~~~~~~~ - - Helper script that performs a release. Does pretty much everything - automatically for us. - - :copyright: (c) 2015 by Armin Ronacher. - :license: BSD, see LICENSE for more details. -""" from __future__ import print_function -import sys + import os import re -from datetime import datetime, date -from subprocess import Popen, PIPE +import sys +from datetime import date, datetime +from subprocess import PIPE, Popen -_date_clean_re = re.compile(r'(\d+)(st|nd|rd|th)') +_date_strip_re = re.compile(r'(?<=\d)(st|nd|rd|th)') def parse_changelog(): @@ -25,18 +15,27 @@ def parse_changelog(): lineiter = iter(f) for line in lineiter: match = re.search('^Version\s+(.*)', line.strip()) + if match is None: continue + version = match.group(1).strip() - if lineiter.next().count('-') != len(match.group(0)): + + if next(lineiter).count('-') != len(match.group(0)): continue + while 1: - change_info = lineiter.next().strip() + change_info = next(lineiter).strip() + if change_info: break - match = re.search(r'released on (\w+\s+\d+\w+\s+\d+)' - r'(?:, codename (.*))?(?i)', change_info) + match = re.search( + r'released on (\w+\s+\d+\w+\s+\d+)(?:, codename (.*))?', + change_info, + flags=re.IGNORECASE + ) + if match is None: continue @@ -46,15 +45,16 @@ def parse_changelog(): def bump_version(version): try: - parts = map(int, version.split('.')) + parts = [int(i) for i in version.split('.')] except ValueError: fail('Current version is not numeric') + parts[-1] += 1 return '.'.join(map(str, parts)) def parse_date(string): - string = _date_clean_re.sub(r'\1', string) + string = _date_strip_re.sub('', string) return datetime.strptime(string, '%B %d %Y') @@ -65,9 +65,13 @@ def set_filename_version(filename, version_number, pattern): before, old, after = match.groups() changed.append(True) return before + version_number + after + with open(filename) as f: - contents = re.sub(r"^(\s*%s\s*=\s*')(.+?)(')(?sm)" % pattern, - inject_version, f.read()) + contents = re.sub( + r"^(\s*%s\s*=\s*')(.+?)(')" % pattern, + inject_version, f.read(), + flags=re.DOTALL | re.MULTILINE + ) if not changed: fail('Could not find %s in %s', pattern, filename) @@ -81,8 +85,9 @@ def set_init_version(version): set_filename_version('flask/__init__.py', version, '__version__') -def build_and_upload(): - Popen([sys.executable, 'setup.py', 'release', 'sdist', 'bdist_wheel', 'upload']).wait() +def build(): + cmd = [sys.executable, 'setup.py', 'sdist', 'bdist_wheel'] + Popen(cmd).wait() def fail(message, *args): @@ -95,7 +100,9 @@ def info(message, *args): def get_git_tags(): - return set(Popen(['git', 'tag'], stdout=PIPE).communicate()[0].splitlines()) + return set( + Popen(['git', 'tag'], stdout=PIPE).communicate()[0].splitlines() + ) def git_is_clean(): @@ -116,29 +123,40 @@ def main(): os.chdir(os.path.join(os.path.dirname(__file__), '..')) rv = parse_changelog() + if rv is None: fail('Could not parse changelog') version, release_date, codename = rv - dev_version = bump_version(version) + '-dev' + dev_version = bump_version(version) + '.dev' - info('Releasing %s (codename %s, release date %s)', - version, codename, release_date.strftime('%d/%m/%Y')) + info( + 'Releasing %s (codename %s, release date %s)', + version, codename, release_date.strftime('%d/%m/%Y') + ) tags = get_git_tags() if version in tags: fail('Version "%s" is already tagged', version) + if release_date.date() != date.today(): - fail('Release date is not today (%s != %s)', - release_date.date(), date.today()) + fail( + 'Release date is not today (%s != %s)', + release_date.date(), date.today() + ) if not git_is_clean(): fail('You have uncommitted changes in git') + try: + import wheel # noqa: F401 + except ImportError: + fail('You need to install the wheel package.') + set_init_version(version) make_git_commit('Bump version number to %s', version) make_git_tag(version) - build_and_upload() + build() set_init_version(dev_version) diff --git a/setup.cfg b/setup.cfg index 527dd3e6..c7641dfc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [aliases] -release = egg_info -RDb '' +release = egg_info -Db '' [bdist_wheel] universal = 1 diff --git a/setup.py b/setup.py old mode 100644 new mode 100755 index 2ece939a..22a39b64 --- a/setup.py +++ b/setup.py @@ -1,74 +1,27 @@ -""" -Flask ------ - -Flask is a microframework for Python based on Werkzeug, Jinja 2 and good -intentions. And before you ask: It's BSD licensed! - -Flask is Fun -```````````` - -Save in a hello.py: - -.. code:: python - - from flask import Flask - app = Flask(__name__) - - @app.route("/") - def hello(): - return "Hello World!" - - if __name__ == "__main__": - app.run() - -And Easy to Setup -````````````````` - -And run it: - -.. code:: bash - - $ pip install Flask - $ python hello.py - * Running on http://localhost:5000/ - -Ready for production? `Read this first `. - -Links -````` - -* `website `_ -* `documentation `_ -* `development version - `_ - -""" +#!/usr/bin/env python +import io import re -import ast from setuptools import setup -_version_re = re.compile(r'__version__\s+=\s+(.*)') +with io.open('README.rst', 'rt', encoding='utf8') as f: + readme = f.read() -with open('flask/__init__.py', 'rb') as f: - version = str(ast.literal_eval(_version_re.search( - f.read().decode('utf-8')).group(1))) +with io.open('flask/__init__.py', 'rt', encoding='utf8') as f: + version = re.search(r'__version__ = \'(.*?)\'', f.read()).group(1) setup( name='Flask', version=version, - url='https://github.com/pallets/flask/', + url='https://www.palletsprojects.com/p/flask/', license='BSD', author='Armin Ronacher', author_email='armin.ronacher@active-4.com', - description='A microframework based on Werkzeug, Jinja2 ' - 'and good intentions', - long_description=__doc__, + description='A simple framework for building complex web applications.', + long_description=readme, packages=['flask', 'flask.json'], include_package_data=True, zip_safe=False, platforms='any', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', install_requires=[ 'Werkzeug>=0.14', 'Jinja2>=2.10', diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index edf1abb9..00000000 --- a/test-requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -tox -pytest -pytest-cov \ No newline at end of file