Skip to content

Commit

Permalink
deprecate FLASK_ENV
Browse files Browse the repository at this point in the history
  • Loading branch information
davidism committed Aug 1, 2022
1 parent 4c08e3a commit ef95998
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 96 deletions.
10 changes: 7 additions & 3 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ Unreleased
``g`` instead using a unique prefix, like
``g._extension_name_attr``.

- The ``FLASK_ENV`` environment variable and ``app.env`` attribute are
deprecated, removing the distinction between development and debug
mode. Debug mode should be controlled directly using the ``--debug``
option or ``app.run(debug=True)``. :issue:`4714`
- Add new customization points to the ``Flask`` app object for many
previously global behaviors.

Expand Down Expand Up @@ -60,9 +64,9 @@ Unreleased
instance on every request. :issue:`2520`.
- A ``flask.cli.FlaskGroup`` Click group can be nested as a
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 ``--app`` 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`
Expand Down
73 changes: 47 additions & 26 deletions src/flask/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
from .globals import session
from .helpers import _split_blueprint_path
from .helpers import get_debug_flag
from .helpers import get_env
from .helpers import get_flashed_messages
from .helpers import get_load_dotenv
from .helpers import locked_cached_property
Expand Down Expand Up @@ -691,7 +690,7 @@ def make_config(self, instance_relative: bool = False) -> Config:
if instance_relative:
root_path = self.instance_path
defaults = dict(self.default_config)
defaults["ENV"] = get_env()
defaults["ENV"] = os.environ.get("FLASK_ENV") or "development"
defaults["DEBUG"] = get_debug_flag()
return self.config_class(root_path, defaults)

Expand Down Expand Up @@ -849,31 +848,50 @@ def make_shell_context(self) -> dict:
rv.update(processor())
return rv

#: What environment the app is running in. Flask and extensions may
#: enable behaviors based on the environment, such as enabling debug
#: mode. This maps to the :data:`ENV` config key. This is set by the
#: :envvar:`FLASK_ENV` environment variable and may not behave as
#: expected if set in code.
#:
#: **Do not enable development when deploying in production.**
#:
#: Default: ``'production'``
env = ConfigAttribute("ENV")
@property
def env(self) -> str:
"""What environment the app is running in. This maps to the :data:`ENV` config
key.
**Do not enable development when deploying in production.**
Default: ``'production'``
.. deprecated:: 2.2
Will be removed in Flask 2.3.
"""
import warnings

warnings.warn(
"'app.env' is deprecated and will be removed in Flask 2.3."
" Use 'app.debug' instead.",
DeprecationWarning,
stacklevel=2,
)
return self.config["ENV"]

@env.setter
def env(self, value: str) -> None:
import warnings

warnings.warn(
"'app.env' is deprecated and will be removed in Flask 2.3."
" Use 'app.debug' instead.",
DeprecationWarning,
stacklevel=2,
)
self.config["ENV"] = value

@property
def debug(self) -> bool:
"""Whether debug mode is enabled. When using ``flask run`` to start
the development server, an interactive debugger will be shown for
unhandled exceptions, and the server will be reloaded when code
changes. This maps to the :data:`DEBUG` config key. This is
enabled when :attr:`env` is ``'development'`` and is overridden
by the ``FLASK_DEBUG`` environment variable. It may not behave as
expected if set in code.
"""Whether debug mode is enabled. When using ``flask run`` to start the
development server, an interactive debugger will be shown for unhandled
exceptions, and the server will be reloaded when code changes. This maps to the
:data:`DEBUG` config key. It may not behave as expected if set late.
**Do not enable debug mode when deploying in production.**
Default: ``True`` if :attr:`env` is ``'development'``, or
``False`` otherwise.
Default: ``False``
"""
return self.config["DEBUG"]

Expand Down Expand Up @@ -937,9 +955,7 @@ def run(
If installed, python-dotenv will be used to load environment
variables from :file:`.env` and :file:`.flaskenv` files.
If set, the :envvar:`FLASK_ENV` and :envvar:`FLASK_DEBUG`
environment variables will override :attr:`env` and
:attr:`debug`.
The :envvar:`FLASK_DEBUG` environment variable will override :attr:`debug`.
Threaded mode is enabled by default.
Expand All @@ -966,7 +982,12 @@ def run(

# if set, let env vars override previous values
if "FLASK_ENV" in os.environ:
self.env = get_env()
print(
"'FLASK_ENV' is deprecated and will not be used in"
" Flask 2.3. Use 'FLASK_DEBUG' instead.",
file=sys.stderr,
)
self.config["ENV"] = os.environ.get("FLASK_ENV") or "production"
self.debug = get_debug_flag()
elif "FLASK_DEBUG" in os.environ:
self.debug = get_debug_flag()
Expand Down Expand Up @@ -998,7 +1019,7 @@ def run(
options.setdefault("use_debugger", self.debug)
options.setdefault("threaded", True)

cli.show_server_banner(self.env, self.debug, self.name)
cli.show_server_banner(self.debug, self.name)

from werkzeug.serving import run_simple

Expand Down
62 changes: 16 additions & 46 deletions src/flask/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@

import click
from click.core import ParameterSource
from werkzeug import run_simple
from werkzeug.serving import is_running_from_reloader
from werkzeug.utils import import_string

from .globals import current_app
from .helpers import get_debug_flag
from .helpers import get_env
from .helpers import get_load_dotenv

if t.TYPE_CHECKING:
Expand Down Expand Up @@ -418,29 +418,6 @@ def _set_app(ctx: click.Context, param: click.Option, value: str | None) -> str
)


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.
Expand All @@ -460,7 +437,7 @@ def _set_debug(ctx: click.Context, param: click.Option, value: bool) -> bool | N

_debug_option = click.Option(
["--debug/--no-debug"],
help="Set 'app.debug' separately from '--env'.",
help="Set debug mode.",
expose_value=False,
callback=_set_debug,
)
Expand Down Expand Up @@ -516,12 +493,10 @@ class FlaskGroup(AppGroup):
:param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv`
files to set environment variables. Will also change the working
directory to the directory containing the first file found.
:param set_debug_flag: Set the app's debug flag based on the active
environment
:param set_debug_flag: Set the app's debug flag.
.. versionchanged:: 2.2
Added the ``-A/--app``, ``-E/--env``, ``--debug/--no-debug``,
and ``-e/--env-file`` options.
Added the ``-A/--app``, ``--debug/--no-debug``, ``-e/--env-file`` options.
.. versionchanged:: 2.2
An app context is pushed when running ``app.cli`` commands, so
Expand All @@ -546,7 +521,7 @@ def __init__(
# 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))
params.extend((_env_file_option, _app_option, _debug_option))

if add_version_option:
params.append(version_option)
Expand Down Expand Up @@ -737,26 +712,23 @@ def load_dotenv(path: str | os.PathLike | None = None) -> bool:
return loaded # True if at least one file was located and loaded.


def show_server_banner(env, debug, app_import_path):
def show_server_banner(debug, app_import_path):
"""Show extra startup messages the first time the server is run,
ignoring the reloader.
"""
if is_running_from_reloader():
return

click.secho(
"WARNING: This is a development server. Do not use it in a production"
" deployment. Use a production WSGI server instead.",
fg="red",
bold=True,
)

if app_import_path is not None:
click.echo(f" * Serving Flask app '{app_import_path}'")

click.echo(f" * Environment: {env}")

if env == "production":
click.secho(
" WARNING: This is a development server. Do not use it in"
" a production deployment.\n Use a production WSGI server"
" instead.",
fg="red",
)

if debug is not None:
click.echo(f" * Debug mode: {'on' if debug else 'off'}")

Expand Down Expand Up @@ -925,8 +897,8 @@ def run_command(
This server is for development purposes only. It does not provide
the stability, security, or performance of production WSGI servers.
The reloader and debugger are enabled by default with the
'--env development' or '--debug' options.
The reloader and debugger are enabled by default with the '--debug'
option.
"""
try:
app = info.load_app()
Expand All @@ -953,9 +925,7 @@ def app(environ, start_response):
if debugger is None:
debugger = debug

show_server_banner(get_env(), debug, info.app_import_path)

from werkzeug.serving import run_simple
show_server_banner(debug, info.app_import_path)

run_simple(
host,
Expand Down
31 changes: 25 additions & 6 deletions src/flask/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,41 @@ def get_env() -> str:
"""Get the environment the app is running in, indicated by the
:envvar:`FLASK_ENV` environment variable. The default is
``'production'``.
.. deprecated:: 2.2
Will be removed in Flask 2.3.
"""
import warnings

warnings.warn(
"'FLASK_ENV' and 'get_env' are deprecated and will be removed"
" in Flask 2.3. Use 'FLASK_DEBUG' instead.",
DeprecationWarning,
stacklevel=2,
)
return os.environ.get("FLASK_ENV") or "production"


def get_debug_flag() -> bool:
"""Get whether debug mode should be enabled for the app, indicated
by the :envvar:`FLASK_DEBUG` environment variable. The default is
``True`` if :func:`.get_env` returns ``'development'``, or ``False``
otherwise.
"""Get whether debug mode should be enabled for the app, indicated by the
:envvar:`FLASK_DEBUG` environment variable. The default is ``False``.
"""
val = os.environ.get("FLASK_DEBUG")

if not val:
return get_env() == "development"
env = os.environ.get("FLASK_ENV")

if env is not None:
print(
"'FLASK_ENV' is deprecated and will not be used in"
" Flask 2.3. Use 'FLASK_DEBUG' instead.",
file=sys.stderr,
)
return env == "development"

return False

return val.lower() not in ("0", "false", "no")
return val.lower() not in {"0", "false", "no"}


def get_load_dotenv(default: bool = True) -> bool:
Expand Down
15 changes: 0 additions & 15 deletions tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import flask
from flask.helpers import get_debug_flag
from flask.helpers import get_env


class FakePath:
Expand Down Expand Up @@ -322,20 +321,6 @@ def test_get_debug_flag(
assert get_debug_flag() == expected_flag
assert get_debug_flag() == expected_default_flag

@pytest.mark.parametrize(
"env, ref_env, debug",
[
("", "production", False),
("production", "production", False),
("development", "development", True),
("other", "other", False),
],
)
def test_get_env(self, monkeypatch, env, ref_env, debug):
monkeypatch.setenv("FLASK_ENV", env)
assert get_debug_flag() == debug
assert get_env() == ref_env

def test_make_response(self):
app = flask.Flask(__name__)
with app.test_request_context():
Expand Down

0 comments on commit ef95998

Please sign in to comment.