Merge pull request #4646 from pallets/cli-app-env
This commit is contained in:
commit
ae547270e9
18 changed files with 344 additions and 634 deletions
|
|
@ -27,6 +27,12 @@ Unreleased
|
||||||
instance on every request. :issue:`2520`.
|
instance on every request. :issue:`2520`.
|
||||||
- A ``flask.cli.FlaskGroup`` Click group can be nested as a
|
- A ``flask.cli.FlaskGroup`` Click group can be nested as a
|
||||||
sub-command in a custom CLI. :issue:`3263`
|
sub-command in a custom CLI. :issue:`3263`
|
||||||
|
- Add ``--app``, ``--env``, and ``--debug`` options to the ``flask``
|
||||||
|
CLI, instead of requiring that they are set through environment
|
||||||
|
variables. :issue:`2836`
|
||||||
|
- Add ``--env-file`` option to the ``flask`` CLI. This allows
|
||||||
|
specifying a dotenv file to load in addition to ``.env`` and
|
||||||
|
``.flaskenv``. :issue:`3108`
|
||||||
|
|
||||||
|
|
||||||
Version 2.1.3
|
Version 2.1.3
|
||||||
|
|
|
||||||
206
docs/cli.rst
206
docs/cli.rst
|
|
@ -15,40 +15,10 @@ Application Discovery
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
The ``flask`` command is installed by Flask, not your application; it must be
|
The ``flask`` command is installed by Flask, not your application; it must be
|
||||||
told where to find your application in order to use it. The ``FLASK_APP``
|
told where to find your application in order to use it. The ``--app``
|
||||||
environment variable is used to specify how to load the application.
|
option is used to specify how to load the application.
|
||||||
|
|
||||||
.. tabs::
|
While ``--app`` supports a variety of options for specifying your
|
||||||
|
|
||||||
.. group-tab:: Bash
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ export FLASK_APP=hello
|
|
||||||
$ flask run
|
|
||||||
|
|
||||||
.. group-tab:: Fish
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ set -x FLASK_APP hello
|
|
||||||
$ flask run
|
|
||||||
|
|
||||||
.. group-tab:: CMD
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> set FLASK_APP=hello
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
.. group-tab:: Powershell
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> $env:FLASK_APP = "hello"
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
While ``FLASK_APP`` supports a variety of options for specifying your
|
|
||||||
application, most use cases should be simple. Here are the typical values:
|
application, most use cases should be simple. Here are the typical values:
|
||||||
|
|
||||||
(nothing)
|
(nothing)
|
||||||
|
|
@ -56,32 +26,32 @@ application, most use cases should be simple. Here are the typical values:
|
||||||
automatically detecting an app (``app`` or ``application``) or
|
automatically detecting an app (``app`` or ``application``) or
|
||||||
factory (``create_app`` or ``make_app``).
|
factory (``create_app`` or ``make_app``).
|
||||||
|
|
||||||
``FLASK_APP=hello``
|
``--app hello``
|
||||||
The given name is imported, automatically detecting an app (``app``
|
The given name is imported, automatically detecting an app (``app``
|
||||||
or ``application``) or factory (``create_app`` or ``make_app``).
|
or ``application``) or factory (``create_app`` or ``make_app``).
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
``FLASK_APP`` has three parts: an optional path that sets the current working
|
``--app`` has three parts: an optional path that sets the current working
|
||||||
directory, a Python file or dotted import path, and an optional variable
|
directory, a Python file or dotted import path, and an optional variable
|
||||||
name of the instance or factory. If the name is a factory, it can optionally
|
name of the instance or factory. If the name is a factory, it can optionally
|
||||||
be followed by arguments in parentheses. The following values demonstrate these
|
be followed by arguments in parentheses. The following values demonstrate these
|
||||||
parts:
|
parts:
|
||||||
|
|
||||||
``FLASK_APP=src/hello``
|
``--app src/hello``
|
||||||
Sets the current working directory to ``src`` then imports ``hello``.
|
Sets the current working directory to ``src`` then imports ``hello``.
|
||||||
|
|
||||||
``FLASK_APP=hello.web``
|
``--app hello.web``
|
||||||
Imports the path ``hello.web``.
|
Imports the path ``hello.web``.
|
||||||
|
|
||||||
``FLASK_APP=hello:app2``
|
``--app hello:app2``
|
||||||
Uses the ``app2`` Flask instance in ``hello``.
|
Uses the ``app2`` Flask instance in ``hello``.
|
||||||
|
|
||||||
``FLASK_APP="hello:create_app('dev')"``
|
``--app 'hello:create_app("dev")'``
|
||||||
The ``create_app`` factory in ``hello`` is called with the string ``'dev'``
|
The ``create_app`` factory in ``hello`` is called with the string ``'dev'``
|
||||||
as the argument.
|
as the argument.
|
||||||
|
|
||||||
If ``FLASK_APP`` is not set, the command will try to import "app" or
|
If ``--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
|
"wsgi" (as a ".py" file, or package) and try to detect an application
|
||||||
instance or factory.
|
instance or factory.
|
||||||
|
|
||||||
|
|
@ -137,8 +107,9 @@ Environments
|
||||||
|
|
||||||
.. versionadded:: 1.0
|
.. versionadded:: 1.0
|
||||||
|
|
||||||
The environment in which the Flask app runs is set by the
|
The environment in which the Flask app executes is set by the
|
||||||
:envvar:`FLASK_ENV` environment variable. If not set it defaults to
|
``FLASK_ENV`` environment variable. When using the ``flask`` command, it
|
||||||
|
can also be set with the ``--env`` option. If not set it defaults to
|
||||||
``production``. The other recognized environment is ``development``.
|
``production``. The other recognized environment is ``development``.
|
||||||
Flask and extensions may choose to enable behaviors based on the
|
Flask and extensions may choose to enable behaviors based on the
|
||||||
environment.
|
environment.
|
||||||
|
|
@ -147,63 +118,16 @@ If the env is set to ``development``, the ``flask`` command will enable
|
||||||
debug mode and ``flask run`` will enable the interactive debugger and
|
debug mode and ``flask run`` will enable the interactive debugger and
|
||||||
reloader.
|
reloader.
|
||||||
|
|
||||||
.. tabs::
|
.. code-block:: text
|
||||||
|
|
||||||
.. group-tab:: Bash
|
$ flask --app hello --env development run
|
||||||
|
* Serving Flask app "hello"
|
||||||
.. code-block:: text
|
* Environment: development
|
||||||
|
* Debug mode: on
|
||||||
$ export FLASK_ENV=development
|
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
|
||||||
$ flask run
|
* Restarting with inotify reloader
|
||||||
* Serving Flask app "hello"
|
* Debugger is active!
|
||||||
* Environment: development
|
* Debugger PIN: 223-456-919
|
||||||
* Debug mode: on
|
|
||||||
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
|
|
||||||
* Restarting with inotify reloader
|
|
||||||
* Debugger is active!
|
|
||||||
* Debugger PIN: 223-456-919
|
|
||||||
|
|
||||||
.. group-tab:: Fish
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ set -x FLASK_ENV development
|
|
||||||
$ flask run
|
|
||||||
* Serving Flask app "hello"
|
|
||||||
* Environment: development
|
|
||||||
* Debug mode: on
|
|
||||||
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
|
|
||||||
* Restarting with inotify reloader
|
|
||||||
* Debugger is active!
|
|
||||||
* Debugger PIN: 223-456-919
|
|
||||||
|
|
||||||
.. group-tab:: CMD
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> set FLASK_ENV=development
|
|
||||||
> flask run
|
|
||||||
* Serving Flask app "hello"
|
|
||||||
* Environment: development
|
|
||||||
* Debug mode: on
|
|
||||||
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
|
|
||||||
* Restarting with inotify reloader
|
|
||||||
* Debugger is active!
|
|
||||||
* Debugger PIN: 223-456-919
|
|
||||||
|
|
||||||
.. group-tab:: Powershell
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> $env:FLASK_ENV = "development"
|
|
||||||
> flask run
|
|
||||||
* Serving Flask app "hello"
|
|
||||||
* Environment: development
|
|
||||||
* Debug mode: on
|
|
||||||
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
|
|
||||||
* Restarting with inotify reloader
|
|
||||||
* Debugger is active!
|
|
||||||
* Debugger PIN: 223-456-919
|
|
||||||
|
|
||||||
|
|
||||||
Watch Extra Files with the Reloader
|
Watch Extra Files with the Reloader
|
||||||
|
|
@ -211,72 +135,31 @@ Watch Extra Files with the Reloader
|
||||||
|
|
||||||
When using development mode, the reloader will trigger whenever your
|
When using development mode, the reloader will trigger whenever your
|
||||||
Python code or imported modules change. The reloader can watch
|
Python code or imported modules change. The reloader can watch
|
||||||
additional files with the ``--extra-files`` option, or the
|
additional files with the ``--extra-files`` option. Multiple paths are
|
||||||
``FLASK_RUN_EXTRA_FILES`` environment variable. Multiple paths are
|
|
||||||
separated with ``:``, or ``;`` on Windows.
|
separated with ``:``, or ``;`` on Windows.
|
||||||
|
|
||||||
.. tabs::
|
.. code-block:: text
|
||||||
|
|
||||||
.. group-tab:: Bash
|
$ flask run --extra-files file1:dirA/file2:dirB/
|
||||||
|
* Running on http://127.0.0.1:8000/
|
||||||
.. code-block:: text
|
* Detected change in '/path/to/file1', reloading
|
||||||
|
|
||||||
$ flask run --extra-files file1:dirA/file2:dirB/
|
|
||||||
# or
|
|
||||||
$ export FLASK_RUN_EXTRA_FILES=file1:dirA/file2:dirB/
|
|
||||||
$ flask run
|
|
||||||
* Running on http://127.0.0.1:8000/
|
|
||||||
* Detected change in '/path/to/file1', reloading
|
|
||||||
|
|
||||||
.. group-tab:: Fish
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ flask run --extra-files file1:dirA/file2:dirB/
|
|
||||||
# or
|
|
||||||
$ set -x FLASK_RUN_EXTRA_FILES file1 dirA/file2 dirB/
|
|
||||||
$ flask run
|
|
||||||
* Running on http://127.0.0.1:8000/
|
|
||||||
* Detected change in '/path/to/file1', reloading
|
|
||||||
|
|
||||||
.. group-tab:: CMD
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> flask run --extra-files file1:dirA/file2:dirB/
|
|
||||||
# or
|
|
||||||
> set FLASK_RUN_EXTRA_FILES=file1:dirA/file2:dirB/
|
|
||||||
> flask run
|
|
||||||
* Running on http://127.0.0.1:8000/
|
|
||||||
* Detected change in '/path/to/file1', reloading
|
|
||||||
|
|
||||||
.. group-tab:: Powershell
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> flask run --extra-files file1:dirA/file2:dirB/
|
|
||||||
# or
|
|
||||||
> $env:FLASK_RUN_EXTRA_FILES = "file1:dirA/file2:dirB/"
|
|
||||||
> flask run
|
|
||||||
* Running on http://127.0.0.1:8000/
|
|
||||||
* Detected change in '/path/to/file1', reloading
|
|
||||||
|
|
||||||
|
|
||||||
Ignore files with the Reloader
|
Ignore files with the Reloader
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The reloader can also ignore files using :mod:`fnmatch` patterns with
|
The reloader can also ignore files using :mod:`fnmatch` patterns with
|
||||||
the ``--exclude-patterns`` option, or the ``FLASK_RUN_EXCLUDE_PATTERNS``
|
the ``--exclude-patterns`` option. Multiple patterns are separated with
|
||||||
environment variable. Multiple patterns are separated with ``:``, or
|
``:``, or ``;`` on Windows.
|
||||||
``;`` on Windows.
|
|
||||||
|
|
||||||
|
|
||||||
Debug Mode
|
Debug Mode
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Debug mode will be enabled when :envvar:`FLASK_ENV` is ``development``,
|
Debug mode will be enabled when the execution environment is
|
||||||
as described above. If you want to control debug mode separately, use
|
``development``, as described above. If you want to control debug mode
|
||||||
:envvar:`FLASK_DEBUG`. The value ``1`` enables it, ``0`` disables it.
|
separately, use the ``--debug/--no-debug`` option or the ``FLASK_DEBUG``
|
||||||
|
environment variable.
|
||||||
|
|
||||||
|
|
||||||
.. _dotenv:
|
.. _dotenv:
|
||||||
|
|
@ -284,14 +167,21 @@ as described above. If you want to control debug mode separately, use
|
||||||
Environment Variables From dotenv
|
Environment Variables From dotenv
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
Rather than setting ``FLASK_APP`` each time you open a new terminal, you can
|
The ``flask`` command supports setting any option for any command with
|
||||||
use Flask's dotenv support to set environment variables automatically.
|
environment variables. The variables are named like ``FLASK_OPTION`` or
|
||||||
|
``FLASK_COMMAND_OPTION``, for example ``FLASK_APP`` or
|
||||||
|
``FLASK_RUN_PORT``.
|
||||||
|
|
||||||
|
Rather than passing options every time you run a command, or environment
|
||||||
|
variables every time you open a new terminal, you can use Flask's dotenv
|
||||||
|
support to set environment variables automatically.
|
||||||
|
|
||||||
If `python-dotenv`_ is installed, running the ``flask`` command will set
|
If `python-dotenv`_ is installed, running the ``flask`` command will set
|
||||||
environment variables defined in the files :file:`.env` and :file:`.flaskenv`.
|
environment variables defined in the files ``.env`` and ``.flaskenv``.
|
||||||
This can be used to avoid having to set ``FLASK_APP`` manually every time you
|
You can also specify an extra file to load with the ``--env-file``
|
||||||
open a new terminal, and to set configuration using environment variables
|
option. Dotenv files can be used to avoid having to set ``--app`` or
|
||||||
similar to how some deployment services work.
|
``FLASK_APP`` manually, and to set configuration using environment
|
||||||
|
variables similar to how some deployment services work.
|
||||||
|
|
||||||
Variables set on the command line are used over those set in :file:`.env`,
|
Variables set on the command line are used over those set in :file:`.env`,
|
||||||
which are used over those set in :file:`.flaskenv`. :file:`.flaskenv` should be
|
which are used over those set in :file:`.flaskenv`. :file:`.flaskenv` should be
|
||||||
|
|
@ -612,7 +502,7 @@ Custom Scripts
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
When you are using the app factory pattern, it may be more convenient to define
|
When you are using the app factory pattern, it may be more convenient to define
|
||||||
your own Click script. Instead of using ``FLASK_APP`` and letting Flask load
|
your own Click script. Instead of using ``--app`` and letting Flask load
|
||||||
your application, you can create your own Click object and export it as a
|
your application, you can create your own Click object and export it as a
|
||||||
`console script`_ entry point.
|
`console script`_ entry point.
|
||||||
|
|
||||||
|
|
@ -646,7 +536,7 @@ Define the entry point in :file:`setup.py`::
|
||||||
)
|
)
|
||||||
|
|
||||||
Install the application in the virtualenv in editable mode and the custom
|
Install the application in the virtualenv in editable mode and the custom
|
||||||
script is available. Note that you don't need to set ``FLASK_APP``. ::
|
script is available. Note that you don't need to set ``--app``. ::
|
||||||
|
|
||||||
$ pip install -e .
|
$ pip install -e .
|
||||||
$ wiki run
|
$ wiki run
|
||||||
|
|
|
||||||
|
|
@ -47,61 +47,33 @@ Environment and Debug Features
|
||||||
|
|
||||||
The :data:`ENV` and :data:`DEBUG` config values are special because they
|
The :data:`ENV` and :data:`DEBUG` config values are special because they
|
||||||
may behave inconsistently if changed after the app has begun setting up.
|
may behave inconsistently if changed after the app has begun setting up.
|
||||||
In order to set the environment and debug mode reliably, Flask uses
|
In order to set the environment and debug mode reliably, pass options to
|
||||||
environment variables.
|
the ``flask`` command or use environment variables.
|
||||||
|
|
||||||
The environment is used to indicate to Flask, extensions, and other
|
The execution environment is used to indicate to Flask, extensions, and
|
||||||
programs, like Sentry, what context Flask is running in. It is
|
other programs, like Sentry, what context Flask is running in. It is
|
||||||
controlled with the :envvar:`FLASK_ENV` environment variable and
|
controlled with the ``FLASK_ENV`` environment variable, or the
|
||||||
defaults to ``production``.
|
``--env`` option when using the ``flask`` command, and defaults to
|
||||||
|
``production``.
|
||||||
|
|
||||||
Setting :envvar:`FLASK_ENV` to ``development`` will enable debug mode.
|
Setting ``--env development`` will enable debug mode. ``flask run`` will
|
||||||
``flask run`` will use the interactive debugger and reloader by default
|
use the interactive debugger and reloader by default in debug mode. To
|
||||||
in debug mode. To control this separately from the environment, use the
|
control this separately from the environment, use the
|
||||||
:envvar:`FLASK_DEBUG` flag.
|
``--debug/--no-debug`` option or the ``FLASK_DEBUG`` environment
|
||||||
|
variable.
|
||||||
.. versionchanged:: 1.0
|
|
||||||
Added :envvar:`FLASK_ENV` to control the environment separately
|
|
||||||
from debug mode. The development environment enables debug mode.
|
|
||||||
|
|
||||||
To switch Flask to the development environment and enable debug mode,
|
To switch Flask to the development environment and enable debug mode,
|
||||||
set :envvar:`FLASK_ENV`:
|
set ``--env``:
|
||||||
|
|
||||||
.. tabs::
|
.. code-block:: text
|
||||||
|
|
||||||
.. group-tab:: Bash
|
$ flask --app hello --env development run
|
||||||
|
|
||||||
.. code-block:: text
|
Using the options or environment variables as described above is
|
||||||
|
recommended. While it is possible to set :data:`ENV` and :data:`DEBUG`
|
||||||
$ export FLASK_ENV=development
|
in your config or code, this is strongly discouraged. They can't be read
|
||||||
$ flask run
|
early by the ``flask`` command, and some systems or extensions may have
|
||||||
|
already configured themselves based on a previous value.
|
||||||
.. group-tab:: Fish
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ set -x FLASK_ENV development
|
|
||||||
$ flask run
|
|
||||||
|
|
||||||
.. group-tab:: CMD
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> set FLASK_ENV=development
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
.. group-tab:: Powershell
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> $env:FLASK_ENV = "development"
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
Using the environment variables as described above is recommended. While
|
|
||||||
it is possible to set :data:`ENV` and :data:`DEBUG` in your config or
|
|
||||||
code, this is strongly discouraged. They can't be read early by the
|
|
||||||
``flask`` command, and some systems or extensions may have already
|
|
||||||
configured themselves based on a previous value.
|
|
||||||
|
|
||||||
|
|
||||||
Builtin Configuration Values
|
Builtin Configuration Values
|
||||||
|
|
|
||||||
|
|
@ -39,45 +39,19 @@ during a request. This debugger should only be used during development.
|
||||||
security risk. Do not run the development server or debugger in a
|
security risk. Do not run the development server or debugger in a
|
||||||
production environment.
|
production environment.
|
||||||
|
|
||||||
To enable the debugger, run the development server with the
|
To enable the debugger, run the development server with the environment
|
||||||
``FLASK_ENV`` environment variable set to ``development``. This puts
|
set to ``development``. This puts Flask in debug mode, which changes how
|
||||||
Flask in debug mode, which changes how it handles some errors, and
|
it handles some errors, and enables the debugger and reloader.
|
||||||
enables the debugger and reloader.
|
|
||||||
|
|
||||||
.. tabs::
|
.. code-block:: text
|
||||||
|
|
||||||
.. group-tab:: Bash
|
$ flask --app hello --env development run
|
||||||
|
|
||||||
.. code-block:: text
|
``FLASK_ENV`` can also be set as an environment variable. When running
|
||||||
|
|
||||||
$ export FLASK_ENV=development
|
|
||||||
$ flask run
|
|
||||||
|
|
||||||
.. group-tab:: Fish
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ set -x FLASK_ENV development
|
|
||||||
$ flask run
|
|
||||||
|
|
||||||
.. group-tab:: CMD
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> set FLASK_ENV=development
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
.. group-tab:: Powershell
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> $env:FLASK_ENV = "development"
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
``FLASK_ENV`` can only be set as an environment variable. When running
|
|
||||||
from Python code, passing ``debug=True`` enables debug mode, which is
|
from Python code, passing ``debug=True`` enables debug mode, which is
|
||||||
mostly equivalent. Debug mode can be controlled separately from
|
mostly equivalent. Debug mode can be controlled separately from the
|
||||||
``FLASK_ENV`` with the ``FLASK_DEBUG`` environment variable as well.
|
environment with the ``--debug/--no-debug`` option or the
|
||||||
|
``FLASK_DEBUG`` environment variable.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
|
@ -102,37 +76,9 @@ When using an external debugger, the app should still be in debug mode,
|
||||||
but it can be useful to disable the built-in debugger and reloader,
|
but it can be useful to disable the built-in debugger and reloader,
|
||||||
which can interfere.
|
which can interfere.
|
||||||
|
|
||||||
When running from the command line:
|
.. code-block:: text
|
||||||
|
|
||||||
.. tabs::
|
$ flask --app hello --env development run --no-debugger --no-reload
|
||||||
|
|
||||||
.. group-tab:: Bash
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ export FLASK_ENV=development
|
|
||||||
$ flask run --no-debugger --no-reload
|
|
||||||
|
|
||||||
.. group-tab:: Fish
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ set -x FLASK_ENV development
|
|
||||||
$ flask run --no-debugger --no-reload
|
|
||||||
|
|
||||||
.. group-tab:: CMD
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> set FLASK_ENV=development
|
|
||||||
> flask run --no-debugger --no-reload
|
|
||||||
|
|
||||||
.. group-tab:: Powershell
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> $env:FLASK_ENV = "development"
|
|
||||||
> flask run --no-debugger --no-reload
|
|
||||||
|
|
||||||
When running from Python:
|
When running from Python:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,71 +89,20 @@ Using Applications
|
||||||
|
|
||||||
To run such an application, you can use the :command:`flask` command:
|
To run such an application, you can use the :command:`flask` command:
|
||||||
|
|
||||||
.. tabs::
|
.. code-block:: text
|
||||||
|
|
||||||
.. group-tab:: Bash
|
$ flask run --app hello run
|
||||||
|
|
||||||
.. code-block:: text
|
Flask will automatically detect the factory if it is named
|
||||||
|
``create_app`` or ``make_app`` in ``hello``. You can also pass arguments
|
||||||
|
to the factory like this:
|
||||||
|
|
||||||
$ export FLASK_APP=myapp
|
.. code-block:: text
|
||||||
$ flask run
|
|
||||||
|
|
||||||
.. group-tab:: Fish
|
$ flask run --app hello:create_app(local_auth=True)``
|
||||||
|
|
||||||
.. code-block:: text
|
Then the ``create_app`` factory in ``myapp`` is called with the keyword
|
||||||
|
argument ``local_auth=True``. See :doc:`/cli` for more detail.
|
||||||
$ set -x FLASK_APP myapp
|
|
||||||
$ flask run
|
|
||||||
|
|
||||||
.. group-tab:: CMD
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> set FLASK_APP=myapp
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
.. group-tab:: Powershell
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> $env:FLASK_APP = "myapp"
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
Flask will automatically detect the factory (``create_app`` or ``make_app``)
|
|
||||||
in ``myapp``. You can also pass arguments to the factory like this:
|
|
||||||
|
|
||||||
.. tabs::
|
|
||||||
|
|
||||||
.. group-tab:: Bash
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ export FLASK_APP="myapp:create_app('dev')"
|
|
||||||
$ flask run
|
|
||||||
|
|
||||||
.. group-tab:: Fish
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ set -x FLASK_APP "myapp:create_app('dev')"
|
|
||||||
$ flask run
|
|
||||||
|
|
||||||
.. group-tab:: CMD
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> set FLASK_APP="myapp:create_app('dev')"
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
.. group-tab:: Powershell
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> $env:FLASK_APP = "myapp:create_app('dev')"
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
Then the ``create_app`` factory in ``myapp`` is called with the string
|
|
||||||
``'dev'`` as the argument. See :doc:`/cli` for more detail.
|
|
||||||
|
|
||||||
Factory Improvements
|
Factory Improvements
|
||||||
--------------------
|
--------------------
|
||||||
|
|
|
||||||
|
|
@ -56,70 +56,17 @@ a big problem, just add a new file called :file:`setup.py` next to the inner
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
In order to run the application you need to export an environment variable
|
Install your application so it is importable:
|
||||||
that tells Flask where to find the application instance:
|
|
||||||
|
|
||||||
.. tabs::
|
.. code-block:: text
|
||||||
|
|
||||||
.. group-tab:: Bash
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ export FLASK_APP=yourapplication
|
|
||||||
|
|
||||||
.. group-tab:: Fish
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ set -x FLASK_APP yourapplication
|
|
||||||
|
|
||||||
.. group-tab:: CMD
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> set FLASK_APP=yourapplication
|
|
||||||
|
|
||||||
.. group-tab:: Powershell
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> $env:FLASK_APP = "yourapplication"
|
|
||||||
|
|
||||||
If you are outside of the project directory make sure to provide the exact
|
|
||||||
path to your application directory. Similarly you can turn on the
|
|
||||||
development features like this:
|
|
||||||
|
|
||||||
.. tabs::
|
|
||||||
|
|
||||||
.. group-tab:: Bash
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ export FLASK_ENV=development
|
|
||||||
|
|
||||||
.. group-tab:: Fish
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ set -x FLASK_ENV development
|
|
||||||
|
|
||||||
.. group-tab:: CMD
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> set FLASK_ENV=development
|
|
||||||
|
|
||||||
.. group-tab:: Powershell
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> $env:FLASK_ENV = "development"
|
|
||||||
|
|
||||||
In order to install and run the application you need to issue the following
|
|
||||||
commands::
|
|
||||||
|
|
||||||
$ pip install -e .
|
$ pip install -e .
|
||||||
$ flask run
|
|
||||||
|
To use the ``flask`` command and run your application you need to set
|
||||||
|
the ``--app`` option that tells Flask where to find the application
|
||||||
|
instance:
|
||||||
|
|
||||||
|
$ flask --app yourapplication run
|
||||||
|
|
||||||
What did we gain from this? Now we can restructure the application a bit
|
What did we gain from this? Now we can restructure the application a bit
|
||||||
into multiple modules. The only thing you have to remember is the
|
into multiple modules. The only thing you have to remember is the
|
||||||
|
|
|
||||||
|
|
@ -39,50 +39,20 @@ Save it as :file:`hello.py` or something similar. Make sure to not call
|
||||||
your application :file:`flask.py` because this would conflict with Flask
|
your application :file:`flask.py` because this would conflict with Flask
|
||||||
itself.
|
itself.
|
||||||
|
|
||||||
To run the application, use the :command:`flask` command or
|
To run the application, use the ``flask`` command or
|
||||||
:command:`python -m flask`. Before you can do that you need
|
``python -m flask``. You need to tell the Flask where your application
|
||||||
to tell your terminal the application to work with by exporting the
|
is with the ``-app`` option.
|
||||||
``FLASK_APP`` environment variable:
|
|
||||||
|
|
||||||
.. tabs::
|
.. code-block:: text
|
||||||
|
|
||||||
.. group-tab:: Bash
|
$ flask --app hello run
|
||||||
|
* Serving Flask app 'hello' (lazy loading)
|
||||||
.. code-block:: text
|
* Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
|
||||||
|
|
||||||
$ export FLASK_APP=hello
|
|
||||||
$ flask run
|
|
||||||
* Running on http://127.0.0.1:5000/
|
|
||||||
|
|
||||||
.. group-tab:: Fish
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ set -x FLASK_APP hello
|
|
||||||
$ flask run
|
|
||||||
* Running on http://127.0.0.1:5000/
|
|
||||||
|
|
||||||
.. group-tab:: CMD
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> set FLASK_APP=hello
|
|
||||||
> flask run
|
|
||||||
* Running on http://127.0.0.1:5000/
|
|
||||||
|
|
||||||
.. group-tab:: Powershell
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> $env:FLASK_APP = "hello"
|
|
||||||
> flask run
|
|
||||||
* Running on http://127.0.0.1:5000/
|
|
||||||
|
|
||||||
.. admonition:: Application Discovery Behavior
|
.. admonition:: Application Discovery Behavior
|
||||||
|
|
||||||
As a shortcut, if the file is named ``app.py`` or ``wsgi.py``, you
|
As a shortcut, if the file is named ``app.py`` or ``wsgi.py``, you
|
||||||
don't have to set the ``FLASK_APP`` environment variable. See
|
don't have to use ``--app``. See :doc:`/cli` for more details.
|
||||||
:doc:`/cli` for more details.
|
|
||||||
|
|
||||||
This launches a very simple builtin server, which is good enough for
|
This launches a very simple builtin server, which is good enough for
|
||||||
testing but probably not what you want to use in production. For
|
testing but probably not what you want to use in production. For
|
||||||
|
|
@ -114,34 +84,6 @@ handle that.
|
||||||
This tells your operating system to listen on all public IPs.
|
This tells your operating system to listen on all public IPs.
|
||||||
|
|
||||||
|
|
||||||
What to do if the Server does not Start
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
In case the :command:`python -m flask` fails or :command:`flask`
|
|
||||||
does not exist, there are multiple reasons this might be the case.
|
|
||||||
First of all you need to look at the error message.
|
|
||||||
|
|
||||||
Old Version of Flask
|
|
||||||
````````````````````
|
|
||||||
|
|
||||||
Versions of Flask older than 0.11 used to have different ways to start the
|
|
||||||
application. In short, the :command:`flask` command did not exist, and
|
|
||||||
neither did :command:`python -m flask`. In that case you have two options:
|
|
||||||
either upgrade to newer Flask versions or have a look at :doc:`/server`
|
|
||||||
to see the alternative method for running a server.
|
|
||||||
|
|
||||||
Invalid Import Name
|
|
||||||
```````````````````
|
|
||||||
|
|
||||||
The ``FLASK_APP`` environment variable is the name of the module to import at
|
|
||||||
:command:`flask run`. In case that module is incorrectly named you will get an
|
|
||||||
import error upon start (or if debug is enabled when you navigate to the
|
|
||||||
application). It will tell you what it tried to import and why it failed.
|
|
||||||
|
|
||||||
The most common reason is a typo or because you did not actually create an
|
|
||||||
``app`` object.
|
|
||||||
|
|
||||||
|
|
||||||
Debug Mode
|
Debug Mode
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|
@ -162,38 +104,19 @@ error occurs during a request.
|
||||||
security risk. Do not run the development server or debugger in a
|
security risk. Do not run the development server or debugger in a
|
||||||
production environment.
|
production environment.
|
||||||
|
|
||||||
To enable all development features, set the ``FLASK_ENV`` environment
|
To enable all development features, set the ``--env`` option to
|
||||||
variable to ``development`` before calling ``flask run``.
|
``development``.
|
||||||
|
|
||||||
.. tabs::
|
.. code-block:: text
|
||||||
|
|
||||||
.. group-tab:: Bash
|
$ flask --app hello --env development run
|
||||||
|
* Serving Flask app 'hello' (lazy loading)
|
||||||
.. code-block:: text
|
* Environment: development
|
||||||
|
* Debug mode: on
|
||||||
$ export FLASK_ENV=development
|
* Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
|
||||||
$ flask run
|
* Restarting with stat
|
||||||
|
* Debugger is active!
|
||||||
.. group-tab:: Fish
|
* Debugger PIN: nnn-nnn-nnn
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ set -x FLASK_ENV development
|
|
||||||
$ flask run
|
|
||||||
|
|
||||||
.. group-tab:: CMD
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> set FLASK_ENV=development
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
.. group-tab:: Powershell
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> $env:FLASK_ENV = "development"
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
See also:
|
See also:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -227,8 +227,8 @@ associated with it is destroyed. If an error occurs during development,
|
||||||
it is useful to delay destroying the data for debugging purposes.
|
it is useful to delay destroying the data for debugging purposes.
|
||||||
|
|
||||||
When the development server is running in development mode (the
|
When the development server is running in development mode (the
|
||||||
``FLASK_ENV`` environment variable is set to ``'development'``), the
|
``--env`` option is set to ``'development'``), the error and data will
|
||||||
error and data will be preserved and shown in the interactive debugger.
|
be preserved and shown in the interactive debugger.
|
||||||
|
|
||||||
This behavior can be controlled with the
|
This behavior can be controlled with the
|
||||||
:data:`PRESERVE_CONTEXT_ON_EXCEPTION` config. As described above, it
|
:data:`PRESERVE_CONTEXT_ON_EXCEPTION` config. As described above, it
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,16 @@ Command Line
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The ``flask run`` command line script is the recommended way to run the
|
The ``flask run`` command line script is the recommended way to run the
|
||||||
development server. It requires setting the ``FLASK_APP`` environment
|
development server. Use the ``--app`` option to point to your
|
||||||
variable to point to your application, and ``FLASK_ENV=development`` to
|
application, and the ``--env development`` option to fully enable
|
||||||
fully enable development mode.
|
development mode.
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
$ flask --app hello --env development run
|
||||||
|
|
||||||
|
These options (and any others) can also be set using environment
|
||||||
|
variables.
|
||||||
|
|
||||||
.. tabs::
|
.. tabs::
|
||||||
|
|
||||||
|
|
@ -65,11 +72,11 @@ and using the CLI.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Prior to Flask 1.0 the ``FLASK_ENV`` environment variable was not
|
Debug mode can be controlled separately from the development
|
||||||
supported and you needed to enable debug mode by exporting
|
environment with the ``--debug/--no-debug`` option or the
|
||||||
``FLASK_DEBUG=1``. This can still be used to control debug mode, but
|
``FLASK_DEBUG`` environment variable. This is how older versions of
|
||||||
you should prefer setting the development environment as shown
|
Flask worked. You should prefer setting the development environment
|
||||||
above.
|
as shown above.
|
||||||
|
|
||||||
|
|
||||||
.. _address-already-in-use:
|
.. _address-already-in-use:
|
||||||
|
|
|
||||||
|
|
@ -196,15 +196,13 @@ previous page.
|
||||||
If you're still running the server from the previous page, you can
|
If you're still running the server from the previous page, you can
|
||||||
either stop the server, or run this command in a new terminal. If
|
either stop the server, or run this command in a new terminal. If
|
||||||
you use a new terminal, remember to change to your project directory
|
you use a new terminal, remember to change to your project directory
|
||||||
and activate the env as described in :doc:`/installation`. You'll
|
and activate the env as described in :doc:`/installation`.
|
||||||
also need to set ``FLASK_APP`` and ``FLASK_ENV`` as shown on the
|
|
||||||
previous page.
|
|
||||||
|
|
||||||
Run the ``init-db`` command:
|
Run the ``init-db`` command:
|
||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
$ flask init-db
|
$ flask --app flaskr init-db
|
||||||
Initialized the database.
|
Initialized the database.
|
||||||
|
|
||||||
There will now be a ``flaskr.sqlite`` file in the ``instance`` folder in
|
There will now be a ``flaskr.sqlite`` file in the ``instance`` folder in
|
||||||
|
|
|
||||||
|
|
@ -48,35 +48,9 @@ Pip will install your project along with its dependencies.
|
||||||
Since this is a different machine, you need to run ``init-db`` again to
|
Since this is a different machine, you need to run ``init-db`` again to
|
||||||
create the database in the instance folder.
|
create the database in the instance folder.
|
||||||
|
|
||||||
.. tabs::
|
.. code-block:: text
|
||||||
|
|
||||||
.. group-tab:: Bash
|
$ flask --app flaskr init-db
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ export FLASK_APP=flaskr
|
|
||||||
$ flask init-db
|
|
||||||
|
|
||||||
.. group-tab:: Fish
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ set -x FLASK_APP flaskr
|
|
||||||
$ flask init-db
|
|
||||||
|
|
||||||
.. group-tab:: CMD
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> set FLASK_APP=flaskr
|
|
||||||
> flask init-db
|
|
||||||
|
|
||||||
.. group-tab:: Powershell
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> $env:FLASK_APP = "flaskr"
|
|
||||||
> flask init-db
|
|
||||||
|
|
||||||
When Flask detects that it's installed (not in editable mode), it uses
|
When Flask detects that it's installed (not in editable mode), it uses
|
||||||
a different directory for the instance folder. You can find it at
|
a different directory for the instance folder. You can find it at
|
||||||
|
|
@ -127,7 +101,7 @@ first install it in the virtual environment:
|
||||||
$ pip install waitress
|
$ pip install waitress
|
||||||
|
|
||||||
You need to tell Waitress about your application, but it doesn't use
|
You need to tell Waitress about your application, but it doesn't use
|
||||||
``FLASK_APP`` like ``flask run`` does. You need to tell it to import and
|
``--app`` like ``flask run`` does. You need to tell it to import and
|
||||||
call the application factory to get an application object.
|
call the application factory to get an application object.
|
||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
|
||||||
|
|
@ -135,43 +135,13 @@ exception, and restarts the server whenever you make changes to the
|
||||||
code. You can leave it running and just reload the browser page as you
|
code. You can leave it running and just reload the browser page as you
|
||||||
follow the tutorial.
|
follow the tutorial.
|
||||||
|
|
||||||
.. tabs::
|
.. code-block:: text
|
||||||
|
|
||||||
.. group-tab:: Bash
|
$ flask --app flaskr --env development run
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ export FLASK_APP=flaskr
|
|
||||||
$ export FLASK_ENV=development
|
|
||||||
$ flask run
|
|
||||||
|
|
||||||
.. group-tab:: Fish
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ set -x FLASK_APP flaskr
|
|
||||||
$ set -x FLASK_ENV development
|
|
||||||
$ flask run
|
|
||||||
|
|
||||||
.. group-tab:: CMD
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> set FLASK_APP=flaskr
|
|
||||||
> set FLASK_ENV=development
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
.. group-tab:: Powershell
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
> $env:FLASK_APP = "flaskr"
|
|
||||||
> $env:FLASK_ENV = "development"
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
You'll see output similar to this:
|
You'll see output similar to this:
|
||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: text
|
||||||
|
|
||||||
* Serving Flask app "flaskr"
|
* Serving Flask app "flaskr"
|
||||||
* Environment: development
|
* Environment: development
|
||||||
|
|
@ -179,7 +149,7 @@ You'll see output similar to this:
|
||||||
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
|
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
|
||||||
* Restarting with stat
|
* Restarting with stat
|
||||||
* Debugger is active!
|
* Debugger is active!
|
||||||
* Debugger PIN: 855-212-761
|
* Debugger PIN: nnn-nnn-nnn
|
||||||
|
|
||||||
Visit http://127.0.0.1:5000/hello in a browser and you should see the
|
Visit http://127.0.0.1:5000/hello in a browser and you should see the
|
||||||
"Hello, World!" message. Congratulations, you're now running your Flask
|
"Hello, World!" message. Congratulations, you're now running your Flask
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ You can observe that the project is now installed with ``pip list``.
|
||||||
wheel 0.30.0
|
wheel 0.30.0
|
||||||
|
|
||||||
Nothing changes from how you've been running your project so far.
|
Nothing changes from how you've been running your project so far.
|
||||||
``FLASK_APP`` is still set to ``flaskr`` and ``flask run`` still runs
|
``--app`` is still set to ``flaskr`` and ``flask run`` still runs
|
||||||
the application, but you can call it from anywhere, not just the
|
the application, but you can call it from anywhere, not just the
|
||||||
``flask-tutorial`` directory.
|
``flask-tutorial`` directory.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,7 @@ Run
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
$ export FLASK_APP=js_example
|
$ flask --app js_example run
|
||||||
$ flask run
|
|
||||||
|
|
||||||
Open http://127.0.0.1:5000 in a browser.
|
Open http://127.0.0.1:5000 in a browser.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,19 +45,10 @@ installing Flaskr::
|
||||||
Run
|
Run
|
||||||
---
|
---
|
||||||
|
|
||||||
::
|
.. code-block:: text
|
||||||
|
|
||||||
$ export FLASK_APP=flaskr
|
$ flask --app flaskr init-db
|
||||||
$ export FLASK_ENV=development
|
$ flask --app flaskr --env development run
|
||||||
$ flask init-db
|
|
||||||
$ flask run
|
|
||||||
|
|
||||||
Or on Windows cmd::
|
|
||||||
|
|
||||||
> set FLASK_APP=flaskr
|
|
||||||
> set FLASK_ENV=development
|
|
||||||
> flask init-db
|
|
||||||
> flask run
|
|
||||||
|
|
||||||
Open http://127.0.0.1:5000 in a browser.
|
Open http://127.0.0.1:5000 in a browser.
|
||||||
|
|
||||||
|
|
|
||||||
239
src/flask/cli.py
239
src/flask/cli.py
|
|
@ -1,3 +1,5 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import ast
|
import ast
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
import os
|
||||||
|
|
@ -12,6 +14,7 @@ from threading import Lock
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
from click.core import ParameterSource
|
||||||
from werkzeug.serving import is_running_from_reloader
|
from werkzeug.serving import is_running_from_reloader
|
||||||
from werkzeug.utils import import_string
|
from werkzeug.utils import import_string
|
||||||
|
|
||||||
|
|
@ -20,6 +23,9 @@ from .helpers import get_debug_flag
|
||||||
from .helpers import get_env
|
from .helpers import get_env
|
||||||
from .helpers import get_load_dotenv
|
from .helpers import get_load_dotenv
|
||||||
|
|
||||||
|
if t.TYPE_CHECKING:
|
||||||
|
from .app import Flask
|
||||||
|
|
||||||
|
|
||||||
class NoAppException(click.UsageError):
|
class NoAppException(click.UsageError):
|
||||||
"""Raised if an application cannot be found or loaded."""
|
"""Raised if an application cannot be found or loaded."""
|
||||||
|
|
@ -46,8 +52,8 @@ def find_best_app(module):
|
||||||
elif len(matches) > 1:
|
elif len(matches) > 1:
|
||||||
raise NoAppException(
|
raise NoAppException(
|
||||||
"Detected multiple Flask applications in module"
|
"Detected multiple Flask applications in module"
|
||||||
f" {module.__name__!r}. Use 'FLASK_APP={module.__name__}:name'"
|
f" '{module.__name__}'. Use '{module.__name__}:name'"
|
||||||
f" to specify the correct one."
|
" to specify the correct one."
|
||||||
)
|
)
|
||||||
|
|
||||||
# Search for app factory functions.
|
# Search for app factory functions.
|
||||||
|
|
@ -65,15 +71,15 @@ def find_best_app(module):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
raise NoAppException(
|
raise NoAppException(
|
||||||
f"Detected factory {attr_name!r} in module {module.__name__!r},"
|
f"Detected factory '{attr_name}' in module '{module.__name__}',"
|
||||||
" but could not call it without arguments. Use"
|
" but could not call it without arguments. Use"
|
||||||
f" \"FLASK_APP='{module.__name__}:{attr_name}(args)'\""
|
f" '{module.__name__}:{attr_name}(args)'"
|
||||||
" to specify arguments."
|
" to specify arguments."
|
||||||
) from e
|
) from e
|
||||||
|
|
||||||
raise NoAppException(
|
raise NoAppException(
|
||||||
"Failed to find Flask application or factory in module"
|
"Failed to find Flask application or factory in module"
|
||||||
f" {module.__name__!r}. Use 'FLASK_APP={module.__name__}:name'"
|
f" '{module.__name__}'. Use '{module.__name__}:name'"
|
||||||
" to specify one."
|
" to specify one."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -253,7 +259,7 @@ def get_version(ctx, param, value):
|
||||||
|
|
||||||
version_option = click.Option(
|
version_option = click.Option(
|
||||||
["--version"],
|
["--version"],
|
||||||
help="Show the flask version",
|
help="Show the Flask version.",
|
||||||
expose_value=False,
|
expose_value=False,
|
||||||
callback=get_version,
|
callback=get_version,
|
||||||
is_flag=True,
|
is_flag=True,
|
||||||
|
|
@ -338,19 +344,24 @@ class ScriptInfo:
|
||||||
onwards as click object.
|
onwards as click object.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, app_import_path=None, create_app=None, set_debug_flag=True):
|
def __init__(
|
||||||
|
self,
|
||||||
|
app_import_path: str | None = None,
|
||||||
|
create_app: t.Callable[..., Flask] | None = None,
|
||||||
|
set_debug_flag: bool = True,
|
||||||
|
) -> None:
|
||||||
#: Optionally the import path for the Flask application.
|
#: Optionally the import path for the Flask application.
|
||||||
self.app_import_path = app_import_path or os.environ.get("FLASK_APP")
|
self.app_import_path = app_import_path
|
||||||
#: Optionally a function that is passed the script info to create
|
#: Optionally a function that is passed the script info to create
|
||||||
#: the instance of the application.
|
#: the instance of the application.
|
||||||
self.create_app = create_app
|
self.create_app = create_app
|
||||||
#: A dictionary with arbitrary data that can be associated with
|
#: A dictionary with arbitrary data that can be associated with
|
||||||
#: this script info.
|
#: this script info.
|
||||||
self.data = {}
|
self.data: t.Dict[t.Any, t.Any] = {}
|
||||||
self.set_debug_flag = set_debug_flag
|
self.set_debug_flag = set_debug_flag
|
||||||
self._loaded_app = None
|
self._loaded_app: Flask | None = None
|
||||||
|
|
||||||
def load_app(self):
|
def load_app(self) -> Flask:
|
||||||
"""Loads the Flask app (if not yet loaded) and returns it. Calling
|
"""Loads the Flask app (if not yet loaded) and returns it. Calling
|
||||||
this multiple times will just result in the already loaded app to
|
this multiple times will just result in the already loaded app to
|
||||||
be returned.
|
be returned.
|
||||||
|
|
@ -379,9 +390,10 @@ class ScriptInfo:
|
||||||
|
|
||||||
if not app:
|
if not app:
|
||||||
raise NoAppException(
|
raise NoAppException(
|
||||||
"Could not locate a Flask application. You did not provide "
|
"Could not locate a Flask application. Use the"
|
||||||
'the "FLASK_APP" environment variable, and a "wsgi.py" or '
|
" 'flask --app' option, 'FLASK_APP' environment"
|
||||||
'"app.py" module was not found in the current directory.'
|
" variable, or a 'wsgi.py' or 'app.py' file in the"
|
||||||
|
" current directory."
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.set_debug_flag:
|
if self.set_debug_flag:
|
||||||
|
|
@ -442,6 +454,117 @@ class AppGroup(click.Group):
|
||||||
return click.Group.group(self, *args, **kwargs)
|
return click.Group.group(self, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def _set_app(ctx: click.Context, param: click.Option, value: str | None) -> str | None:
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
info = ctx.ensure_object(ScriptInfo)
|
||||||
|
info.app_import_path = value
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
# This option is eager so the app will be available if --help is given.
|
||||||
|
# --help is also eager, so --app must be before it in the param list.
|
||||||
|
# no_args_is_help bypasses eager processing, so this option must be
|
||||||
|
# processed manually in that case to ensure FLASK_APP gets picked up.
|
||||||
|
_app_option = click.Option(
|
||||||
|
["-A", "--app"],
|
||||||
|
metavar="IMPORT",
|
||||||
|
help=(
|
||||||
|
"The Flask application or factory function to load, in the form 'module:name'."
|
||||||
|
" Module can be a dotted import or file path. Name is not required if it is"
|
||||||
|
" 'app', 'application', 'create_app', or 'make_app', and can be 'name(args)' to"
|
||||||
|
" pass arguments."
|
||||||
|
),
|
||||||
|
is_eager=True,
|
||||||
|
expose_value=False,
|
||||||
|
callback=_set_app,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _set_env(ctx: click.Context, param: click.Option, value: str | None) -> str | None:
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Set with env var instead of ScriptInfo.load so that it can be
|
||||||
|
# accessed early during a factory function.
|
||||||
|
os.environ["FLASK_ENV"] = value
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
_env_option = click.Option(
|
||||||
|
["-E", "--env"],
|
||||||
|
metavar="NAME",
|
||||||
|
help=(
|
||||||
|
"The execution environment name to set in 'app.env'. Defaults to"
|
||||||
|
" 'production'. 'development' will enable 'app.debug' and start the"
|
||||||
|
" debugger and reloader when running the server."
|
||||||
|
),
|
||||||
|
expose_value=False,
|
||||||
|
callback=_set_env,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _set_debug(ctx: click.Context, param: click.Option, value: bool) -> bool | None:
|
||||||
|
# If the flag isn't provided, it will default to False. Don't use
|
||||||
|
# that, let debug be set by env in that case.
|
||||||
|
source = ctx.get_parameter_source(param.name) # type: ignore[arg-type]
|
||||||
|
|
||||||
|
if source is not None and source in (
|
||||||
|
ParameterSource.DEFAULT,
|
||||||
|
ParameterSource.DEFAULT_MAP,
|
||||||
|
):
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Set with env var instead of ScriptInfo.load so that it can be
|
||||||
|
# accessed early during a factory function.
|
||||||
|
os.environ["FLASK_DEBUG"] = "1" if value else "0"
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
_debug_option = click.Option(
|
||||||
|
["--debug/--no-debug"],
|
||||||
|
help="Set 'app.debug' separately from '--env'.",
|
||||||
|
expose_value=False,
|
||||||
|
callback=_set_debug,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _env_file_callback(
|
||||||
|
ctx: click.Context, param: click.Option, value: str | None
|
||||||
|
) -> str | None:
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
|
||||||
|
try:
|
||||||
|
importlib.import_module("dotenv")
|
||||||
|
except ImportError:
|
||||||
|
raise click.BadParameter(
|
||||||
|
"python-dotenv must be installed to load an env file.",
|
||||||
|
ctx=ctx,
|
||||||
|
param=param,
|
||||||
|
) from None
|
||||||
|
|
||||||
|
# Don't check FLASK_SKIP_DOTENV, that only disables automatically
|
||||||
|
# loading .env and .flaskenv files.
|
||||||
|
load_dotenv(value)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
# This option is eager so env vars are loaded as early as possible to be
|
||||||
|
# used by other options.
|
||||||
|
_env_file_option = click.Option(
|
||||||
|
["-e", "--env-file"],
|
||||||
|
type=click.Path(exists=True, dir_okay=False),
|
||||||
|
help="Load environment variables from this file. python-dotenv must be installed.",
|
||||||
|
is_eager=True,
|
||||||
|
expose_value=False,
|
||||||
|
callback=_env_file_callback,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class FlaskGroup(AppGroup):
|
class FlaskGroup(AppGroup):
|
||||||
"""Special subclass of the :class:`AppGroup` group that supports
|
"""Special subclass of the :class:`AppGroup` group that supports
|
||||||
loading more commands from the configured Flask app. Normally a
|
loading more commands from the configured Flask app. Normally a
|
||||||
|
|
@ -460,6 +583,10 @@ class FlaskGroup(AppGroup):
|
||||||
:param set_debug_flag: Set the app's debug flag based on the active
|
:param set_debug_flag: Set the app's debug flag based on the active
|
||||||
environment
|
environment
|
||||||
|
|
||||||
|
.. versionchanged:: 2.2
|
||||||
|
Added the ``-A/--app``, ``-E/--env``, ``--debug/--no-debug``,
|
||||||
|
and ``-e/--env-file`` options.
|
||||||
|
|
||||||
.. versionchanged:: 1.0
|
.. versionchanged:: 1.0
|
||||||
If installed, python-dotenv will be used to load environment variables
|
If installed, python-dotenv will be used to load environment variables
|
||||||
from :file:`.env` and :file:`.flaskenv` files.
|
from :file:`.env` and :file:`.flaskenv` files.
|
||||||
|
|
@ -467,14 +594,19 @@ class FlaskGroup(AppGroup):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
add_default_commands=True,
|
add_default_commands: bool = True,
|
||||||
create_app=None,
|
create_app: t.Callable[..., Flask] | None = None,
|
||||||
add_version_option=True,
|
add_version_option: bool = True,
|
||||||
load_dotenv=True,
|
load_dotenv: bool = True,
|
||||||
set_debug_flag=True,
|
set_debug_flag: bool = True,
|
||||||
**extra,
|
**extra: t.Any,
|
||||||
):
|
) -> None:
|
||||||
params = list(extra.pop("params", None) or ())
|
params = list(extra.pop("params", None) or ())
|
||||||
|
# Processing is done with option callbacks instead of a group
|
||||||
|
# callback. This allows users to make a custom group callback
|
||||||
|
# without losing the behavior. --env-file must come first so
|
||||||
|
# that it is eagerly evaluated before --app.
|
||||||
|
params.extend((_env_file_option, _app_option, _env_option, _debug_option))
|
||||||
|
|
||||||
if add_version_option:
|
if add_version_option:
|
||||||
params.append(version_option)
|
params.append(version_option)
|
||||||
|
|
@ -555,11 +687,13 @@ class FlaskGroup(AppGroup):
|
||||||
|
|
||||||
def make_context(
|
def make_context(
|
||||||
self,
|
self,
|
||||||
info_name: t.Optional[str],
|
info_name: str | None,
|
||||||
args: t.List[str],
|
args: list[str],
|
||||||
parent: t.Optional[click.Context] = None,
|
parent: click.Context | None = None,
|
||||||
**extra: t.Any,
|
**extra: t.Any,
|
||||||
) -> click.Context:
|
) -> click.Context:
|
||||||
|
# Attempt to load .env and .flask env files. The --env-file
|
||||||
|
# option can cause another file to be loaded.
|
||||||
if get_load_dotenv(self.load_dotenv):
|
if get_load_dotenv(self.load_dotenv):
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
|
|
@ -570,6 +704,16 @@ class FlaskGroup(AppGroup):
|
||||||
|
|
||||||
return super().make_context(info_name, args, parent=parent, **extra)
|
return super().make_context(info_name, args, parent=parent, **extra)
|
||||||
|
|
||||||
|
def parse_args(self, ctx: click.Context, args: list[str]) -> list[str]:
|
||||||
|
if not args and self.no_args_is_help:
|
||||||
|
# Attempt to load --env-file and --app early in case they
|
||||||
|
# were given as env vars. Otherwise no_args_is_help will not
|
||||||
|
# see commands from app.cli.
|
||||||
|
_env_file_option.handle_parse_result(ctx, {}, [])
|
||||||
|
_app_option.handle_parse_result(ctx, {}, [])
|
||||||
|
|
||||||
|
return super().parse_args(ctx, args)
|
||||||
|
|
||||||
|
|
||||||
def _path_is_ancestor(path, other):
|
def _path_is_ancestor(path, other):
|
||||||
"""Take ``other`` and remove the length of ``path`` from it. Then join it
|
"""Take ``other`` and remove the length of ``path`` from it. Then join it
|
||||||
|
|
@ -578,7 +722,7 @@ def _path_is_ancestor(path, other):
|
||||||
return os.path.join(path, other[len(path) :].lstrip(os.sep)) == other
|
return os.path.join(path, other[len(path) :].lstrip(os.sep)) == other
|
||||||
|
|
||||||
|
|
||||||
def load_dotenv(path=None):
|
def load_dotenv(path: str | os.PathLike | None = None) -> bool:
|
||||||
"""Load "dotenv" files in order of precedence to set environment variables.
|
"""Load "dotenv" files in order of precedence to set environment variables.
|
||||||
|
|
||||||
If an env var is already set it is not overwritten, so earlier files in the
|
If an env var is already set it is not overwritten, so earlier files in the
|
||||||
|
|
@ -591,13 +735,17 @@ def load_dotenv(path=None):
|
||||||
:param path: Load the file at this location instead of searching.
|
:param path: Load the file at this location instead of searching.
|
||||||
:return: ``True`` if a file was loaded.
|
:return: ``True`` if a file was loaded.
|
||||||
|
|
||||||
.. versionchanged:: 1.1.0
|
.. versionchanged:: 2.0
|
||||||
Returns ``False`` when python-dotenv is not installed, or when
|
The current directory is not changed to the location of the
|
||||||
the given path isn't a file.
|
loaded file.
|
||||||
|
|
||||||
.. versionchanged:: 2.0
|
.. versionchanged:: 2.0
|
||||||
When loading the env files, set the default encoding to UTF-8.
|
When loading the env files, set the default encoding to UTF-8.
|
||||||
|
|
||||||
|
.. versionchanged:: 1.1.0
|
||||||
|
Returns ``False`` when python-dotenv is not installed, or when
|
||||||
|
the given path isn't a file.
|
||||||
|
|
||||||
.. versionadded:: 1.0
|
.. versionadded:: 1.0
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
|
@ -613,15 +761,15 @@ def load_dotenv(path=None):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# if the given path specifies the actual file then return True,
|
# Always return after attempting to load a given path, don't load
|
||||||
# else False
|
# the default files.
|
||||||
if path is not None:
|
if path is not None:
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
return dotenv.load_dotenv(path, encoding="utf-8")
|
return dotenv.load_dotenv(path, encoding="utf-8")
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
new_dir = None
|
loaded = False
|
||||||
|
|
||||||
for name in (".env", ".flaskenv"):
|
for name in (".env", ".flaskenv"):
|
||||||
path = dotenv.find_dotenv(name, usecwd=True)
|
path = dotenv.find_dotenv(name, usecwd=True)
|
||||||
|
|
@ -629,12 +777,10 @@ def load_dotenv(path=None):
|
||||||
if not path:
|
if not path:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if new_dir is None:
|
|
||||||
new_dir = os.path.dirname(path)
|
|
||||||
|
|
||||||
dotenv.load_dotenv(path, encoding="utf-8")
|
dotenv.load_dotenv(path, encoding="utf-8")
|
||||||
|
loaded = True
|
||||||
|
|
||||||
return new_dir is not None # at least one file was located and loaded
|
return loaded # True if at least one file was located and loaded.
|
||||||
|
|
||||||
|
|
||||||
def show_server_banner(env, debug, app_import_path, eager_loading):
|
def show_server_banner(env, debug, app_import_path, eager_loading):
|
||||||
|
|
@ -837,9 +983,10 @@ def run_command(
|
||||||
This server is for development purposes only. It does not provide
|
This server is for development purposes only. It does not provide
|
||||||
the stability, security, or performance of production WSGI servers.
|
the stability, security, or performance of production WSGI servers.
|
||||||
|
|
||||||
The reloader and debugger are enabled by default if
|
The reloader and debugger are enabled by default with the
|
||||||
FLASK_ENV=development or FLASK_DEBUG=1.
|
'--env development' or '--debug' options.
|
||||||
"""
|
"""
|
||||||
|
app = DispatchingApp(info.load_app, use_eager_loading=eager_loading)
|
||||||
debug = get_debug_flag()
|
debug = get_debug_flag()
|
||||||
|
|
||||||
if reload is None:
|
if reload is None:
|
||||||
|
|
@ -849,7 +996,6 @@ def run_command(
|
||||||
debugger = debug
|
debugger = debug
|
||||||
|
|
||||||
show_server_banner(get_env(), debug, info.app_import_path, eager_loading)
|
show_server_banner(get_env(), debug, info.app_import_path, eager_loading)
|
||||||
app = DispatchingApp(info.load_app, use_eager_loading=eager_loading)
|
|
||||||
|
|
||||||
from werkzeug.serving import run_simple
|
from werkzeug.serving import run_simple
|
||||||
|
|
||||||
|
|
@ -971,19 +1117,10 @@ cli = FlaskGroup(
|
||||||
help="""\
|
help="""\
|
||||||
A general utility script for Flask applications.
|
A general utility script for Flask applications.
|
||||||
|
|
||||||
Provides commands from Flask, extensions, and the application. Loads the
|
An application to load must be given with the '--app' option,
|
||||||
application defined in the FLASK_APP environment variable, or from a wsgi.py
|
'FLASK_APP' environment variable, or with a 'wsgi.py' or 'app.py' file
|
||||||
file. Setting the FLASK_ENV environment variable to 'development' will enable
|
in the current directory.
|
||||||
debug mode.
|
""",
|
||||||
|
|
||||||
\b
|
|
||||||
{prefix}{cmd} FLASK_APP=hello.py
|
|
||||||
{prefix}{cmd} FLASK_ENV=development
|
|
||||||
{prefix}flask run
|
|
||||||
""".format(
|
|
||||||
cmd="export" if os.name == "posix" else "set",
|
|
||||||
prefix="$ " if os.name == "posix" else "> ",
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,9 +48,9 @@ def get_debug_flag() -> bool:
|
||||||
|
|
||||||
|
|
||||||
def get_load_dotenv(default: bool = True) -> bool:
|
def get_load_dotenv(default: bool = True) -> bool:
|
||||||
"""Get whether the user has disabled loading dotenv files by setting
|
"""Get whether the user has disabled loading default dotenv files by
|
||||||
:envvar:`FLASK_SKIP_DOTENV`. The default is ``True``, load the
|
setting :envvar:`FLASK_SKIP_DOTENV`. The default is ``True``, load
|
||||||
files.
|
the files.
|
||||||
|
|
||||||
:param default: What to return if the env var isn't set.
|
:param default: What to return if the env var isn't set.
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ def _standard_os_environ():
|
||||||
"""
|
"""
|
||||||
mp = monkeypatch.MonkeyPatch()
|
mp = monkeypatch.MonkeyPatch()
|
||||||
out = (
|
out = (
|
||||||
|
(os.environ, "FLASK_ENV_FILE", monkeypatch.notset),
|
||||||
(os.environ, "FLASK_APP", monkeypatch.notset),
|
(os.environ, "FLASK_APP", monkeypatch.notset),
|
||||||
(os.environ, "FLASK_ENV", monkeypatch.notset),
|
(os.environ, "FLASK_ENV", monkeypatch.notset),
|
||||||
(os.environ, "FLASK_DEBUG", monkeypatch.notset),
|
(os.environ, "FLASK_DEBUG", monkeypatch.notset),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue