forked from orbit-oss/flask
load env vars using python-dotenv
This commit is contained in:
parent
77b98a2762
commit
491d331e6e
13 changed files with 235 additions and 42 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,4 +1,6 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.env
|
||||||
|
.flaskenv
|
||||||
*.pyc
|
*.pyc
|
||||||
*.pyo
|
*.pyo
|
||||||
env
|
env
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,11 @@ script:
|
||||||
cache:
|
cache:
|
||||||
- pip
|
- pip
|
||||||
|
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
- /^.*-maintenance$/
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
irc:
|
irc:
|
||||||
|
|
|
||||||
4
CHANGES
4
CHANGES
|
|
@ -101,6 +101,9 @@ Major release, unreleased
|
||||||
- The ``request.json`` property is no longer deprecated. (`#1421`_)
|
- The ``request.json`` property is no longer deprecated. (`#1421`_)
|
||||||
- Support passing an existing ``EnvironBuilder`` or ``dict`` to
|
- Support passing an existing ``EnvironBuilder`` or ``dict`` to
|
||||||
``test_client.open``. (`#2412`_)
|
``test_client.open``. (`#2412`_)
|
||||||
|
- The ``flask`` command and ``app.run`` will load environment variables using
|
||||||
|
from ``.env`` and ``.flaskenv`` files if python-dotenv is installed.
|
||||||
|
(`#2416`_)
|
||||||
|
|
||||||
.. _#1421: https://github.com/pallets/flask/issues/1421
|
.. _#1421: https://github.com/pallets/flask/issues/1421
|
||||||
.. _#1489: https://github.com/pallets/flask/pull/1489
|
.. _#1489: https://github.com/pallets/flask/pull/1489
|
||||||
|
|
@ -130,6 +133,7 @@ Major release, unreleased
|
||||||
.. _#2385: https://github.com/pallets/flask/issues/2385
|
.. _#2385: https://github.com/pallets/flask/issues/2385
|
||||||
.. _#2412: https://github.com/pallets/flask/pull/2412
|
.. _#2412: https://github.com/pallets/flask/pull/2412
|
||||||
.. _#2414: https://github.com/pallets/flask/pull/2414
|
.. _#2414: https://github.com/pallets/flask/pull/2414
|
||||||
|
.. _#2416: https://github.com/pallets/flask/pull/2416
|
||||||
|
|
||||||
Version 0.12.2
|
Version 0.12.2
|
||||||
--------------
|
--------------
|
||||||
|
|
|
||||||
|
|
@ -814,6 +814,8 @@ Command Line Interface
|
||||||
.. autoclass:: ScriptInfo
|
.. autoclass:: ScriptInfo
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. autofunction:: load_dotenv
|
||||||
|
|
||||||
.. autofunction:: with_appcontext
|
.. autofunction:: with_appcontext
|
||||||
|
|
||||||
.. autofunction:: pass_script_info
|
.. autofunction:: pass_script_info
|
||||||
|
|
|
||||||
34
docs/cli.rst
34
docs/cli.rst
|
|
@ -97,9 +97,8 @@ Custom Commands
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
If you want to add more commands to the shell script you can do this
|
If you want to add more commands to the shell script you can do this
|
||||||
easily. Flask uses `click`_ for the command interface which makes
|
easily. For instance if you want a shell command to initialize the database you
|
||||||
creating custom commands very easy. For instance if you want a shell
|
can do this::
|
||||||
command to initialize the database you can do this::
|
|
||||||
|
|
||||||
import click
|
import click
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
|
|
@ -134,6 +133,35 @@ decorator::
|
||||||
def example():
|
def example():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
.. _dotenv:
|
||||||
|
|
||||||
|
Loading Environment Variables From ``.env`` Files
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
If `python-dotenv`_ is installed, running the :command:`flask` command will set
|
||||||
|
environment variables defined in the files :file:`.env` and :file:`.flaskenv`.
|
||||||
|
This can be used to avoid having to set ``FLASK_APP`` manually every time you
|
||||||
|
open a new terminal, 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`,
|
||||||
|
which are used over those set in :file:`.flaskenv`. :file:`.flaskenv` should be
|
||||||
|
used for public variables, such as ``FLASK_APP``, while :file:`.env` should not
|
||||||
|
be committed to your repository so that it can set private variables.
|
||||||
|
|
||||||
|
Directories are scanned upwards from the directory you call :command:`flask`
|
||||||
|
from to locate the files. The current working directory will be set to the
|
||||||
|
location of the file, with the assumption that that is the top level project
|
||||||
|
directory.
|
||||||
|
|
||||||
|
The files are only loaded by the :command:`flask` command or calling
|
||||||
|
:meth:`~flask.Flask.run`. If you would like to load these files when running in
|
||||||
|
production, you should call :func:`~flask.cli.load_dotenv` manually.
|
||||||
|
|
||||||
|
.. _python-dotenv: https://github.com/theskumar/python-dotenv#readme
|
||||||
|
|
||||||
|
|
||||||
Factory Functions
|
Factory Functions
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,12 @@ use them if you install them.
|
||||||
* `SimpleJSON`_ is a fast JSON implementation that is compatible with
|
* `SimpleJSON`_ is a fast JSON implementation that is compatible with
|
||||||
Python's ``json`` module. It is preferred for JSON operations if it is
|
Python's ``json`` module. It is preferred for JSON operations if it is
|
||||||
installed.
|
installed.
|
||||||
|
* `python-dotenv`_ enables support for :ref:`dotenv` when running ``flask``
|
||||||
|
commands.
|
||||||
|
|
||||||
.. _Blinker: https://pythonhosted.org/blinker/
|
.. _Blinker: https://pythonhosted.org/blinker/
|
||||||
.. _SimpleJSON: https://simplejson.readthedocs.io/
|
.. _SimpleJSON: https://simplejson.readthedocs.io/
|
||||||
|
.. _python-dotenv: https://github.com/theskumar/python-dotenv#readme
|
||||||
|
|
||||||
Virtual environments
|
Virtual environments
|
||||||
--------------------
|
--------------------
|
||||||
|
|
|
||||||
42
flask/app.py
42
flask/app.py
|
|
@ -820,7 +820,9 @@ class Flask(_PackageBoundObject):
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
self.jinja_env.auto_reload = self.templates_auto_reload
|
self.jinja_env.auto_reload = self.templates_auto_reload
|
||||||
|
|
||||||
def run(self, host=None, port=None, debug=None, **options):
|
def run(
|
||||||
|
self, host=None, port=None, debug=None, load_dotenv=True, **options
|
||||||
|
):
|
||||||
"""Runs the application on a local development server.
|
"""Runs the application on a local development server.
|
||||||
|
|
||||||
Do not use ``run()`` in a production setting. It is not intended to
|
Do not use ``run()`` in a production setting. It is not intended to
|
||||||
|
|
@ -849,30 +851,40 @@ class Flask(_PackageBoundObject):
|
||||||
won't catch any exceptions because there won't be any to
|
won't catch any exceptions because there won't be any to
|
||||||
catch.
|
catch.
|
||||||
|
|
||||||
|
:param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to
|
||||||
|
have the server available externally as well. Defaults to
|
||||||
|
``'127.0.0.1'`` or the host in the ``SERVER_NAME`` config variable
|
||||||
|
if present.
|
||||||
|
:param port: the port of the webserver. Defaults to ``5000`` or the
|
||||||
|
port defined in the ``SERVER_NAME`` config variable if present.
|
||||||
|
:param debug: if given, enable or disable debug mode. See
|
||||||
|
:attr:`debug`.
|
||||||
|
: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 options: the options to be forwarded to the underlying Werkzeug
|
||||||
|
server. See :func:`werkzeug.serving.run_simple` for more
|
||||||
|
information.
|
||||||
|
|
||||||
|
.. versionchanged:: 1.0
|
||||||
|
If installed, python-dotenv will be used to load environment
|
||||||
|
variables from :file:`.env` and :file:`.flaskenv` files.
|
||||||
|
|
||||||
.. versionchanged:: 0.10
|
.. versionchanged:: 0.10
|
||||||
The default port is now picked from the ``SERVER_NAME`` variable.
|
The default port is now picked from the ``SERVER_NAME`` variable.
|
||||||
|
|
||||||
:param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to
|
|
||||||
have the server available externally as well. Defaults to
|
|
||||||
``'127.0.0.1'`` or the host in the ``SERVER_NAME`` config
|
|
||||||
variable if present.
|
|
||||||
:param port: the port of the webserver. Defaults to ``5000`` or the
|
|
||||||
port defined in the ``SERVER_NAME`` config variable if
|
|
||||||
present.
|
|
||||||
:param debug: if given, enable or disable debug mode.
|
|
||||||
See :attr:`debug`.
|
|
||||||
:param options: the options to be forwarded to the underlying
|
|
||||||
Werkzeug server. See
|
|
||||||
:func:`werkzeug.serving.run_simple` for more
|
|
||||||
information.
|
|
||||||
"""
|
"""
|
||||||
# Change this into a no-op if the server is invoked from the
|
# Change this into a no-op if the server is invoked from the
|
||||||
# command line. Have a look at cli.py for more information.
|
# command line. Have a look at cli.py for more information.
|
||||||
if os.environ.get('FLASK_RUN_FROM_CLI_SERVER') == '1':
|
if os.environ.get('FLASK_RUN_FROM_CLI') == 'true':
|
||||||
from .debughelpers import explain_ignored_app_run
|
from .debughelpers import explain_ignored_app_run
|
||||||
explain_ignored_app_run()
|
explain_ignored_app_run()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if load_dotenv:
|
||||||
|
from flask.cli import load_dotenv
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
if debug is not None:
|
if debug is not None:
|
||||||
self._reconfigure_for_run_debug(bool(debug))
|
self._reconfigure_for_run_debug(bool(debug))
|
||||||
|
|
||||||
|
|
|
||||||
101
flask/cli.py
101
flask/cli.py
|
|
@ -8,6 +8,7 @@
|
||||||
:copyright: (c) 2015 by Armin Ronacher.
|
:copyright: (c) 2015 by Armin Ronacher.
|
||||||
:license: BSD, see LICENSE for more details.
|
:license: BSD, see LICENSE for more details.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
import ast
|
import ast
|
||||||
import inspect
|
import inspect
|
||||||
|
|
@ -22,10 +23,14 @@ from threading import Lock, Thread
|
||||||
import click
|
import click
|
||||||
|
|
||||||
from . import __version__
|
from . import __version__
|
||||||
from ._compat import iteritems, reraise
|
from ._compat import getargspec, iteritems, reraise
|
||||||
from .globals import current_app
|
from .globals import current_app
|
||||||
from .helpers import get_debug_flag
|
from .helpers import get_debug_flag
|
||||||
from ._compat import getargspec
|
|
||||||
|
try:
|
||||||
|
import dotenv
|
||||||
|
except ImportError:
|
||||||
|
dotenv = None
|
||||||
|
|
||||||
|
|
||||||
class NoAppException(click.UsageError):
|
class NoAppException(click.UsageError):
|
||||||
|
|
@ -394,14 +399,23 @@ class FlaskGroup(AppGroup):
|
||||||
For information as of why this is useful see :ref:`custom-scripts`.
|
For information as of why this is useful see :ref:`custom-scripts`.
|
||||||
|
|
||||||
:param add_default_commands: if this is True then the default run and
|
:param add_default_commands: if this is True then the default run and
|
||||||
shell commands wil be added.
|
shell commands wil be added.
|
||||||
:param add_version_option: adds the ``--version`` option.
|
:param add_version_option: adds the ``--version`` option.
|
||||||
:param create_app: an optional callback that is passed the script info
|
:param create_app: an optional callback that is passed the script info and
|
||||||
and returns the loaded app.
|
returns the loaded app.
|
||||||
|
: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.
|
||||||
|
|
||||||
|
.. versionchanged:: 1.0
|
||||||
|
If installed, python-dotenv will be used to load environment variables
|
||||||
|
from :file:`.env` and :file:`.flaskenv` files.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, add_default_commands=True, create_app=None,
|
def __init__(
|
||||||
add_version_option=True, **extra):
|
self, add_default_commands=True, create_app=None,
|
||||||
|
add_version_option=True, load_dotenv=True, **extra
|
||||||
|
):
|
||||||
params = list(extra.pop('params', None) or ())
|
params = list(extra.pop('params', None) or ())
|
||||||
|
|
||||||
if add_version_option:
|
if add_version_option:
|
||||||
|
|
@ -409,6 +423,7 @@ class FlaskGroup(AppGroup):
|
||||||
|
|
||||||
AppGroup.__init__(self, params=params, **extra)
|
AppGroup.__init__(self, params=params, **extra)
|
||||||
self.create_app = create_app
|
self.create_app = create_app
|
||||||
|
self.load_dotenv = load_dotenv
|
||||||
|
|
||||||
if add_default_commands:
|
if add_default_commands:
|
||||||
self.add_command(run_command)
|
self.add_command(run_command)
|
||||||
|
|
@ -472,12 +487,75 @@ class FlaskGroup(AppGroup):
|
||||||
return sorted(rv)
|
return sorted(rv)
|
||||||
|
|
||||||
def main(self, *args, **kwargs):
|
def main(self, *args, **kwargs):
|
||||||
|
# Set a global flag that indicates that we were invoked from the
|
||||||
|
# command line interface. This is detected by Flask.run to make the
|
||||||
|
# call into a no-op. This is necessary to avoid ugly errors when the
|
||||||
|
# script that is loaded here also attempts to start a server.
|
||||||
|
os.environ['FLASK_RUN_FROM_CLI'] = 'true'
|
||||||
|
|
||||||
|
if self.load_dotenv:
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
obj = kwargs.get('obj')
|
obj = kwargs.get('obj')
|
||||||
|
|
||||||
if obj is None:
|
if obj is None:
|
||||||
obj = ScriptInfo(create_app=self.create_app)
|
obj = ScriptInfo(create_app=self.create_app)
|
||||||
|
|
||||||
kwargs['obj'] = obj
|
kwargs['obj'] = obj
|
||||||
kwargs.setdefault('auto_envvar_prefix', 'FLASK')
|
kwargs.setdefault('auto_envvar_prefix', 'FLASK')
|
||||||
return AppGroup.main(self, *args, **kwargs)
|
return super(FlaskGroup, self).main(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def _path_is_ancestor(path, other):
|
||||||
|
"""Take ``other`` and remove the length of ``path`` from it. Then join it
|
||||||
|
to ``path``. If it is the original value, ``path`` is an ancestor of
|
||||||
|
``other``."""
|
||||||
|
return os.path.join(path, other[len(path):].lstrip(os.sep)) == other
|
||||||
|
|
||||||
|
|
||||||
|
def load_dotenv(path=None):
|
||||||
|
"""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
|
||||||
|
list are preferred over later files.
|
||||||
|
|
||||||
|
Changes the current working directory to the location of the first file
|
||||||
|
found, with the assumption that it is in the top level project directory
|
||||||
|
and will be where the Python path should import local packages from.
|
||||||
|
|
||||||
|
This is a no-op if `python-dotenv`_ is not installed.
|
||||||
|
|
||||||
|
.. _python-dotenv: https://github.com/theskumar/python-dotenv#readme
|
||||||
|
|
||||||
|
:param path: Load the file at this location instead of searching.
|
||||||
|
:return: ``True`` if a file was loaded.
|
||||||
|
|
||||||
|
.. versionadded:: 1.0
|
||||||
|
"""
|
||||||
|
|
||||||
|
if dotenv is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if path is not None:
|
||||||
|
return dotenv.load_dotenv(path)
|
||||||
|
|
||||||
|
new_dir = None
|
||||||
|
|
||||||
|
for name in ('.env', '.flaskenv'):
|
||||||
|
path = dotenv.find_dotenv(name, usecwd=True)
|
||||||
|
|
||||||
|
if not path:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if new_dir is None:
|
||||||
|
new_dir = os.path.dirname(path)
|
||||||
|
|
||||||
|
dotenv.load_dotenv(path)
|
||||||
|
|
||||||
|
if new_dir and os.getcwd() != new_dir:
|
||||||
|
os.chdir(new_dir)
|
||||||
|
|
||||||
|
return new_dir is not None # at least one file was located and loaded
|
||||||
|
|
||||||
|
|
||||||
@click.command('run', short_help='Runs a development server.')
|
@click.command('run', short_help='Runs a development server.')
|
||||||
|
|
@ -512,13 +590,6 @@ def run_command(info, host, port, reload, debugger, eager_loading,
|
||||||
"""
|
"""
|
||||||
from werkzeug.serving import run_simple
|
from werkzeug.serving import run_simple
|
||||||
|
|
||||||
# Set a global flag that indicates that we were invoked from the
|
|
||||||
# command line interface provided server command. This is detected
|
|
||||||
# by Flask.run to make the call into a no-op. This is necessary to
|
|
||||||
# avoid ugly errors when the script that is loaded here also attempts
|
|
||||||
# to start a server.
|
|
||||||
os.environ['FLASK_RUN_FROM_CLI_SERVER'] = '1'
|
|
||||||
|
|
||||||
debug = get_debug_flag()
|
debug = get_debug_flag()
|
||||||
if reload is None:
|
if reload is None:
|
||||||
reload = bool(debug)
|
reload = bool(debug)
|
||||||
|
|
|
||||||
2
setup.py
2
setup.py
|
|
@ -75,8 +75,10 @@ setup(
|
||||||
'click>=4.0',
|
'click>=4.0',
|
||||||
],
|
],
|
||||||
extras_require={
|
extras_require={
|
||||||
|
'dotenv': ['python-dotenv'],
|
||||||
'dev': [
|
'dev': [
|
||||||
'blinker',
|
'blinker',
|
||||||
|
'python-dotenv',
|
||||||
'greenlet',
|
'greenlet',
|
||||||
'pytest>=3',
|
'pytest>=3',
|
||||||
'coverage',
|
'coverage',
|
||||||
|
|
|
||||||
3
tests/test_apps/.env
Normal file
3
tests/test_apps/.env
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
FOO=env
|
||||||
|
SPAM=1
|
||||||
|
EGGS=2
|
||||||
3
tests/test_apps/.flaskenv
Normal file
3
tests/test_apps/.flaskenv
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
FOO=flaskenv
|
||||||
|
BAR=bar
|
||||||
|
EGGS=0
|
||||||
|
|
@ -19,11 +19,31 @@ from functools import partial
|
||||||
|
|
||||||
import click
|
import click
|
||||||
import pytest
|
import pytest
|
||||||
|
from _pytest.monkeypatch import notset
|
||||||
from click.testing import CliRunner
|
from click.testing import CliRunner
|
||||||
|
|
||||||
from flask import Flask, current_app
|
from flask import Flask, current_app
|
||||||
from flask.cli import AppGroup, FlaskGroup, NoAppException, ScriptInfo, \
|
from flask.cli import AppGroup, FlaskGroup, NoAppException, ScriptInfo, dotenv, \
|
||||||
find_best_app, get_version, locate_app, prepare_import, with_appcontext
|
find_best_app, get_version, load_dotenv, locate_app, prepare_import, \
|
||||||
|
with_appcontext
|
||||||
|
|
||||||
|
cwd = os.getcwd()
|
||||||
|
test_path = os.path.abspath(os.path.join(
|
||||||
|
os.path.dirname(__file__), 'test_apps'
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def manage_os_environ(monkeypatch):
|
||||||
|
# can't use monkeypatch.delitem since we don't want to restore a value
|
||||||
|
os.environ.pop('FLASK_APP', None)
|
||||||
|
os.environ.pop('FLASK_DEBUG', None)
|
||||||
|
# use monkeypatch internals to force-delete environ keys
|
||||||
|
monkeypatch._setitem.extend((
|
||||||
|
(os.environ, 'FLASK_APP', notset),
|
||||||
|
(os.environ, 'FLASK_DEBUG', notset),
|
||||||
|
(os.environ, 'FLASK_RUN_FROM_CLI', notset),
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
@ -125,12 +145,6 @@ def test_find_best_app(test_apps):
|
||||||
pytest.raises(NoAppException, find_best_app, script_info, Module)
|
pytest.raises(NoAppException, find_best_app, script_info, Module)
|
||||||
|
|
||||||
|
|
||||||
cwd = os.getcwd()
|
|
||||||
test_path = os.path.abspath(os.path.join(
|
|
||||||
os.path.dirname(__file__), 'test_apps'
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('value,path,result', (
|
@pytest.mark.parametrize('value,path,result', (
|
||||||
('test', cwd, 'test'),
|
('test', cwd, 'test'),
|
||||||
('test.py', cwd, 'test'),
|
('test.py', cwd, 'test'),
|
||||||
|
|
@ -414,3 +428,46 @@ class TestRoutes:
|
||||||
assert 'GET, HEAD, OPTIONS, POST' not in output
|
assert 'GET, HEAD, OPTIONS, POST' not in output
|
||||||
output = invoke(['routes', '--all-methods']).output
|
output = invoke(['routes', '--all-methods']).output
|
||||||
assert 'GET, HEAD, OPTIONS, POST' in output
|
assert 'GET, HEAD, OPTIONS, POST' in output
|
||||||
|
|
||||||
|
|
||||||
|
need_dotenv = pytest.mark.skipif(
|
||||||
|
dotenv is None, reason='dotenv is not installed'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@need_dotenv
|
||||||
|
def test_load_dotenv(monkeypatch):
|
||||||
|
# can't use monkeypatch.delitem since the keys don't exist yet
|
||||||
|
for item in ('FOO', 'BAR', 'SPAM'):
|
||||||
|
monkeypatch._setitem.append((os.environ, item, notset))
|
||||||
|
|
||||||
|
monkeypatch.setenv('EGGS', '3')
|
||||||
|
monkeypatch.chdir(os.path.join(test_path, 'cliapp', 'inner1'))
|
||||||
|
load_dotenv()
|
||||||
|
assert os.getcwd() == test_path
|
||||||
|
# .flaskenv doesn't overwrite .env
|
||||||
|
assert os.environ['FOO'] == 'env'
|
||||||
|
# set only in .flaskenv
|
||||||
|
assert os.environ['BAR'] == 'bar'
|
||||||
|
# set only in .env
|
||||||
|
assert os.environ['SPAM'] == '1'
|
||||||
|
# set manually, files don't overwrite
|
||||||
|
assert os.environ['EGGS'] == '3'
|
||||||
|
|
||||||
|
|
||||||
|
@need_dotenv
|
||||||
|
def test_dotenv_path(monkeypatch):
|
||||||
|
for item in ('FOO', 'BAR', 'EGGS'):
|
||||||
|
monkeypatch._setitem.append((os.environ, item, notset))
|
||||||
|
|
||||||
|
cwd = os.getcwd()
|
||||||
|
load_dotenv(os.path.join(test_path, '.flaskenv'))
|
||||||
|
assert os.getcwd() == cwd
|
||||||
|
assert 'FOO' in os.environ
|
||||||
|
|
||||||
|
|
||||||
|
def test_dotenv_optional(monkeypatch):
|
||||||
|
monkeypatch.setattr('flask.cli.dotenv', None)
|
||||||
|
monkeypatch.chdir(test_path)
|
||||||
|
load_dotenv()
|
||||||
|
assert 'FOO' not in os.environ
|
||||||
|
|
|
||||||
3
tox.ini
3
tox.ini
|
|
@ -15,6 +15,7 @@ deps =
|
||||||
coverage
|
coverage
|
||||||
greenlet
|
greenlet
|
||||||
blinker
|
blinker
|
||||||
|
python-dotenv
|
||||||
|
|
||||||
lowest: Werkzeug==0.9
|
lowest: Werkzeug==0.9
|
||||||
lowest: Jinja2==2.4
|
lowest: Jinja2==2.4
|
||||||
|
|
@ -67,4 +68,4 @@ skip_install = true
|
||||||
deps = detox
|
deps = detox
|
||||||
commands =
|
commands =
|
||||||
detox -e py{36,35,34,33,27,26,py},py{36,27,py}-simplejson,py{36,33,27,26,py}-devel,py{36,33,27,26,py}-lowest
|
detox -e py{36,35,34,33,27,26,py},py{36,27,py}-simplejson,py{36,33,27,26,py}-devel,py{36,33,27,26,py}-lowest
|
||||||
tox -e coverage-report
|
tox -e docs-html,coverage-report
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue