diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index a5e46b04..bbed06fc 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -9,8 +9,9 @@ Support questions Please, don't use the issue tracker for this. Use one of the following resources for questions about your own code: -* The IRC channel ``#pocoo`` on FreeNode. -* The IRC channel ``#python`` on FreeNode for more general questions. +* The ``#get-help`` channel on our Discord chat: https://discord.gg/t6rrQZH + * The IRC channel ``#pocoo`` on FreeNode is linked to Discord, but + Discord is preferred. * The mailing list flask@python.org for long term discussion or larger issues. * Ask on `Stack Overflow`_. Search with Google first using: ``site:stackoverflow.com flask {search term, exception message, etc.}`` @@ -81,14 +82,26 @@ First time setup Start coding ~~~~~~~~~~~~ -- Create a branch to identify the issue you would like to work on (e.g. - ``2287-dry-test-suite``) +- Create a branch to identify the issue you would like to work on. If + you're submitting a bug or documentation fix, branch off of the + latest ".x" branch:: + + git checkout -b your-branch-name origin/1.0.x + + If you're submitting a feature addition or change, branch off of the + "master" branch:: + + git checkout -b your-branch-name origin/master + - Using your favorite editor, make your changes, `committing as you go`_. - Try to follow `PEP8`_, but you may ignore the line length limit if following it would make the code uglier. - Include tests that cover any code changes you make. Make sure the test fails without your patch. `Run the tests. `_. -- Push your commits to GitHub and `create a pull request`_. +- Push your commits to GitHub and `create a pull request`_ by using:: + + git push --set-upstream origin your-branch-name + - Celebrate 🎉 .. _committing as you go: https://dont-be-afraid-to-commit.readthedocs.io/en/latest/git/commandlinegit.html#commit-your-changes diff --git a/README.rst b/README.rst index 25af0d7e..2991a836 100644 --- a/README.rst +++ b/README.rst @@ -75,6 +75,7 @@ Links * Test status: https://dev.azure.com/pallets/pallets/_build?definitionId=2 * Test coverage: https://codecov.io/gh/pallets/flask +* Official chat: https://discord.gg/t6rrQZH .. _WSGI: https://wsgi.readthedocs.io .. _Werkzeug: https://www.palletsprojects.com/p/werkzeug/ diff --git a/docs/api.rst b/docs/api.rst index 11ee4d7b..f4a97845 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -726,7 +726,7 @@ requests, make sure the default route only handles ``GET``, as redirects can't preserve form data. :: @app.route('/region/', defaults={'id': 1}) - @app.route('/region/', methods=['GET', 'POST']) + @app.route('/region/', methods=['GET', 'POST']) def region(id): pass diff --git a/docs/appcontext.rst b/docs/appcontext.rst index cdc14d94..a0d3a2dd 100644 --- a/docs/appcontext.rst +++ b/docs/appcontext.rst @@ -49,7 +49,7 @@ Typically, an application context will have the same lifetime as a request. See :doc:`/reqcontext` for more information about how the contexts work -and the full lifecycle of a request. +and the full life cycle of a request. Manually Push a Context diff --git a/docs/becomingbig.rst b/docs/becomingbig.rst index 58e1778d..6b534d64 100644 --- a/docs/becomingbig.rst +++ b/docs/becomingbig.rst @@ -97,6 +97,6 @@ Discuss with the community. The Flask developers keep the framework accessible to users with codebases big and small. If you find an obstacle in your way, caused by Flask, don't hesitate -to contact the developers on the mailinglist or IRC channel. The best way for +to contact the developers on the mailing list or IRC channel. The best way for the Flask and Flask extension developers to improve the tools for larger applications is getting feedback from users. diff --git a/docs/blueprints.rst b/docs/blueprints.rst index fb639966..2e940be1 100644 --- a/docs/blueprints.rst +++ b/docs/blueprints.rst @@ -246,7 +246,7 @@ was dispatched to any other admin blueprint endpoint. Error Handlers -------------- -Blueprints support the errorhandler decorator just like the :class:`Flask` +Blueprints support the ``errorhandler`` decorator just like the :class:`Flask` application object, so it is easy to make Blueprint-specific custom error pages. @@ -258,14 +258,13 @@ Here is an example for a "404 Page Not Found" exception:: Most errorhandlers will simply work as expected; however, there is a caveat concerning handlers for 404 and 405 exceptions. These errorhandlers are only -invoked from an appropriate ``raise`` statement or a call to ``abort`` -in another of the blueprint's view functions; they are not invoked by, -e.g., an invalid URL access. This is because the blueprint does not -"own" a certain URL space, so the application instance has no way of -knowing which blueprint errorhandler it should run if given an invalid URL. -If you would like to execute different handling strategies for these errors -based on URL prefixes, they may be defined at the application level using -the ``request`` proxy object:: +invoked from an appropriate ``raise`` statement or a call to ``abort`` in another +of the blueprint's view functions; they are not invoked by, e.g., an invalid URL +access. This is because the blueprint does not "own" a certain URL space, so +the application instance has no way of knowing which blueprint error handler it +should run if given an invalid URL. If you would like to execute different +handling strategies for these errors based on URL prefixes, they may be defined +at the application level using the ``request`` proxy object:: @app.errorhandler(404) @app.errorhandler(405) diff --git a/docs/cli.rst b/docs/cli.rst index efe94e98..5835d74b 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -68,9 +68,9 @@ parts: The ``create_app`` factory in ``hello`` is called with the string ``'dev'`` as the argument. -If ``FLASK_APP`` is not set, the command will look for a file called -:file:`wsgi.py` or :file:`app.py` and try to detect an application instance or -factory. +If ``FLASK_APP`` is not set, the command will try to import "app" or +"wsgi" (as a ".py" file, or package) and try to detect an application +instance or factory. Within the given import, the command looks for an application instance named ``app`` or ``application``, then any application instance. If no instance is diff --git a/docs/config.rst b/docs/config.rst index b68f0d22..f0f67a67 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -9,7 +9,7 @@ toggling the debug mode, setting the secret key, and other such environment-specific things. The way Flask is designed usually requires the configuration to be -available when the application starts up. You can hardcode the +available when the application starts up. You can hard code the configuration in the code, which for many small applications is not actually that bad, but there are better ways. @@ -437,6 +437,7 @@ methods on the config object as well to load from individual files. For a complete reference, read the :class:`~flask.Config` object's documentation. + Configuring from Environment Variables -------------------------------------- @@ -448,15 +449,13 @@ Environment variables can be set on Linux or OS X with the export command in the shell before starting the server:: $ export SECRET_KEY='5f352379324c22463451387a0aec5d2f' - $ export DEBUG=False + $ export MAIL_ENABLED=false $ python run-app.py * Running on http://127.0.0.1:5000/ - * Restarting with reloader... -On Windows systems use the `set` builtin instead:: +On Windows systems use the ``set`` builtin instead:: > set SECRET_KEY='5f352379324c22463451387a0aec5d2f' - > set DEBUG=False While this approach is straightforward to use, it is important to remember that environment variables are strings -- they are not automatically deserialized @@ -464,17 +463,15 @@ into Python types. Here is an example of a configuration file that uses environment variables:: - # Example configuration import os - ENVIRONMENT_DEBUG = os.environ.get("DEBUG", default=False) - if ENVIRONMENT_DEBUG.lower() in ("f", "false"): - ENVIRONMENT_DEBUG = False + _mail_enabled = os.environ.get("MAIL_ENABLED", default="true") + MAIL_ENABLED = _mail_enabled.lower() in {"1", "t", "true"} + + SECRET_KEY = os.environ.get("SECRET_KEY") - DEBUG = ENVIRONMENT_DEBUG - SECRET_KEY = os.environ.get("SECRET_KEY", default=None) if not SECRET_KEY: - raise ValueError("No secret key set for Flask application") + raise ValueError("No SECRET_KEY set for Flask application") Notice that any value besides an empty string will be interpreted as a boolean @@ -486,6 +483,7 @@ ability to access the configuration when starting up. There are other methods on the config object as well to load from individual files. For a complete reference, read the :class:`~flask.Config` class documentation. + Configuration Best Practices ---------------------------- @@ -496,7 +494,7 @@ that experience: 1. Create your application in a function and register blueprints on it. That way you can create multiple instances of your application with - different configurations attached which makes unittesting a lot + different configurations attached which makes unit testing a lot easier. You can use this to pass in configuration as needed. 2. Do not write code that needs the configuration at import time. If you @@ -529,7 +527,7 @@ 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 -and import different hardcoded files based on that. +and import different hard-coded files based on that. An interesting pattern is also to use classes and inheritance for configuration:: diff --git a/docs/deploying/wsgi-standalone.rst b/docs/deploying/wsgi-standalone.rst index 1e4d9d31..3b2f9ed9 100644 --- a/docs/deploying/wsgi-standalone.rst +++ b/docs/deploying/wsgi-standalone.rst @@ -23,9 +23,15 @@ For example, to run a Flask application with 4 worker processes (``-w $ gunicorn -w 4 -b 127.0.0.1:4000 myproject:app +The ``gunicorn`` command expects the names of your application module or +package and the application instance within the module. If you use the +application factory pattern, you can pass a call to that:: + + $ gunicorn "myproject:create_app()" + .. _Gunicorn: https://gunicorn.org/ .. _eventlet: https://eventlet.net/ -.. _greenlet: https://greenlet.readthedocs.io/en/latest/ + uWSGI -------- @@ -123,8 +129,8 @@ If your httpd is not providing these headers, the most common setup invokes the host being set from ``X-Forwarded-Host`` and the remote address from ``X-Forwarded-For``:: - from werkzeug.contrib.fixers import ProxyFix - app.wsgi_app = ProxyFix(app.wsgi_app) + from werkzeug.middleware.proxy_fix import ProxyFix + app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1) .. admonition:: Trusting Headers diff --git a/docs/design.rst b/docs/design.rst index f0f7126d..3dd1a284 100644 --- a/docs/design.rst +++ b/docs/design.rst @@ -41,7 +41,7 @@ the time. There are ways to fake multiple applications with a single application object, like maintaining a stack of applications, but this causes some problems I won't outline here in detail. Now the question is: when does a microframework need more than one application at the same -time? A good example for this is unittesting. When you want to test +time? A good example for this is unit testing. When you want to test something it can be very helpful to create a minimal application to test specific behavior. When the application object is deleted everything it allocated will be freed again. @@ -76,7 +76,7 @@ there are better ways to do that so that you do not lose the reference to the application object :meth:`~flask.Flask.wsgi_app`). Furthermore this design makes it possible to use a factory function to -create the application which is very helpful for unittesting and similar +create the application which is very helpful for unit testing and similar things (:ref:`app-factories`). The Routing System diff --git a/docs/extensiondev.rst b/docs/extensiondev.rst index fc65a350..95a70ba2 100644 --- a/docs/extensiondev.rst +++ b/docs/extensiondev.rst @@ -287,7 +287,7 @@ also avoids having multiple developers working in isolation on pretty much the same problem. Remember: good API design is hard, so introduce your project on the -mailinglist, and let other developers give you a helping hand with +mailing list, and let other developers give you a helping hand with designing the API. The best Flask extensions are extensions that share common idioms for the diff --git a/docs/extensions.rst b/docs/extensions.rst index e91e9b6c..bd4565ec 100644 --- a/docs/extensions.rst +++ b/docs/extensions.rst @@ -6,7 +6,7 @@ Extensions Extensions are extra packages that add functionality to a Flask application. For example, an extension might add support for sending email or connecting to a database. Some extensions add entire new -frameworks to help build certain types of applications, like a ReST API. +frameworks to help build certain types of applications, like a REST API. Finding Extensions diff --git a/docs/patterns/methodoverrides.rst b/docs/patterns/methodoverrides.rst index d5c187b6..45dbb87e 100644 --- a/docs/patterns/methodoverrides.rst +++ b/docs/patterns/methodoverrides.rst @@ -2,14 +2,14 @@ Adding HTTP Method Overrides ============================ Some HTTP proxies do not support arbitrary HTTP methods or newer HTTP -methods (such as PATCH). In that case it's possible to “proxy” HTTP +methods (such as PATCH). In that case it's possible to "proxy" HTTP methods through another HTTP method in total violation of the protocol. The way this works is by letting the client do an HTTP POST request and -set the ``X-HTTP-Method-Override`` header and set the value to the -intended HTTP method (such as ``PATCH``). +set the ``X-HTTP-Method-Override`` header. Then the method is replaced +with the header value before being passed to Flask. -This can easily be accomplished with an HTTP middleware:: +This can be accomplished with an HTTP middleware:: class HTTPMethodOverrideMiddleware(object): allowed_methods = frozenset([ @@ -29,13 +29,12 @@ This can easily be accomplished with an HTTP middleware:: def __call__(self, environ, start_response): method = environ.get('HTTP_X_HTTP_METHOD_OVERRIDE', '').upper() if method in self.allowed_methods: - method = method.encode('ascii', 'replace') environ['REQUEST_METHOD'] = method if method in self.bodyless_methods: environ['CONTENT_LENGTH'] = '0' return self.app(environ, start_response) -To use this with Flask this is all that is necessary:: +To use this with Flask, wrap the app object with the middleware:: from flask import Flask diff --git a/docs/quickstart.rst b/docs/quickstart.rst index acf6dc15..47200a13 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -203,7 +203,7 @@ of the argument like ````. :: @app.route('/user/') def show_user_profile(username): # show the user profile for that user - return 'User %s' % username + return 'User %s' % escape(username) @app.route('/post/') def show_post(post_id): @@ -213,7 +213,7 @@ of the argument like ````. :: @app.route('/path/') def show_subpath(subpath): # show the subpath after /path/ - return 'Subpath %s' % subpath + return 'Subpath %s' % escape(subpath) Converter types: @@ -281,7 +281,7 @@ Python shell. See :ref:`context-locals`. .. code-block:: python - from flask import Flask, url_for + from flask import Flask, escape, url_for app = Flask(__name__) @@ -295,7 +295,7 @@ Python shell. See :ref:`context-locals`. @app.route('/user/') def profile(username): - return '{}\'s profile'.format(username) + return '{}\'s profile'.format(escape(username)) with app.test_request_context(): print(url_for('index')) @@ -690,10 +690,10 @@ response objects is as follows: returned from the view. 2. If it's a string, a response object is created with that data and the default parameters. -3. If a tuple is returned the items in the tuple can provide extra - information. Such tuples have to be in the form ``(response, status, - headers)`` or ``(response, headers)`` where at least one item has - to be in the tuple. The ``status`` value will override the status code +3. If a tuple is returned the items in the tuple can provide extra information. + Such tuples have to be in the form ``(response, status, headers)``, + ``(response, headers)`` or ``(response, status)`` where at least one item + has to be in the tuple. The ``status`` value will override the status code and ``headers`` can be a list or dictionary of additional header values. 4. If none of that works, Flask will assume the return value is a valid WSGI application and convert that into a response object. diff --git a/docs/shell.rst b/docs/shell.rst index 9d9bb5f9..c863a77d 100644 --- a/docs/shell.rst +++ b/docs/shell.rst @@ -20,7 +20,7 @@ can you do? This is where some helper functions come in handy. Keep in mind however that these functions are not only there for interactive shell usage, but -also for unittesting and other situations that require a faked request +also for unit testing and other situations that require a faked request context. Generally it's recommended that you read the :ref:`request-context` diff --git a/docs/unicode.rst b/docs/unicode.rst index d3cb683f..f8ab1558 100644 --- a/docs/unicode.rst +++ b/docs/unicode.rst @@ -43,8 +43,8 @@ The Golden Rule So the rule of thumb: if you are not dealing with binary data, work with Unicode. What does working with Unicode in Python 2.x mean? -- as long as you are using ASCII charpoints only (basically numbers, - some special characters of latin letters without umlauts or anything +- as long as you are using ASCII code points only (basically numbers, + some special characters of Latin letters without umlauts or anything fancy) you can use regular string literals (``'Hello World'``). - if you need anything else than ASCII in a string you have to mark this string as Unicode string by prefixing it with a lowercase `u`. diff --git a/flask/ctx.py b/flask/ctx.py index 817086d7..3d85e01b 100644 --- a/flask/ctx.py +++ b/flask/ctx.py @@ -175,7 +175,7 @@ def has_request_context(): self.remote_addr = remote_addr Alternatively you can also just test any of the context bound objects - (such as :class:`request` or :class:`g` for truthness):: + (such as :class:`request` or :class:`g`) for truthness:: class User(db.Model): diff --git a/flask/helpers.py b/flask/helpers.py index 389a86df..19cb4c99 100644 --- a/flask/helpers.py +++ b/flask/helpers.py @@ -278,7 +278,7 @@ def url_for(endpoint, **values): :param values: the variable arguments of the URL rule :param _external: if set to ``True``, an absolute URL is generated. Server address can be changed via ``SERVER_NAME`` configuration variable which - defaults to `localhost`. + falls back to the `Host` header, then to the IP and port of the request. :param _scheme: a string specifying the desired URL scheme. The `_external` parameter must be set to ``True`` or a :exc:`ValueError` is raised. The default behavior uses the same scheme as the current request, or