Browse Source

Merge pull request #2378 from miguelgrinberg/default-flask-app

Import app from wsgi.py or app.py if FLASK_APP is not defined
pull/2381/head
David Lord 8 years ago committed by GitHub
parent
commit
29c055a2b4
  1. 12
      docs/cli.rst
  2. 51
      flask/cli.py
  3. 6
      tests/test_apps/helloworld/hello.py
  4. 1
      tests/test_apps/helloworld/wsgi.py
  5. 24
      tests/test_cli.py

12
docs/cli.rst

@ -25,10 +25,14 @@ your Flask application's :attr:`Flask.cli` instance as well as some
built-in commands that are always there. Flask extensions can also built-in commands that are always there. Flask extensions can also
register more commands there if they desire so. register more commands there if they desire so.
For the :command:`flask` script to work, an application needs to be For the :command:`flask` script to work, an application needs to be discovered.
discovered. This is achieved by exporting the ``FLASK_APP`` environment Flask looks for a module named :file:`wsgi.py` or :file:`app.py` by default,
variable. It can be either set to an import path or to a filename of a and if it finds one it assumes the application is defined in it.
Python module that contains a Flask application.
You can instruct Flask to look for the application in a different module by
exporting the ``FLASK_APP`` environment variable. It can be either set to an
import path or to a filename of a Python module that contains a Flask
application.
In that imported file the name of the app needs to be called ``app`` or In that imported file the name of the app needs to be called ``app`` or
optionally be specified after a colon. For instance optionally be specified after a colon. For instance

51
flask/cli.py

@ -172,13 +172,16 @@ def prepare_exec_for_file(filename):
if not os.path.isfile(os.path.join(dirpath, '__init__.py')): if not os.path.isfile(os.path.join(dirpath, '__init__.py')):
break break
sys.path.insert(0, dirpath) if sys.path[0] != dirpath:
sys.path.insert(0, dirpath)
return '.'.join(module[::-1]) return '.'.join(module[::-1])
def locate_app(script_info, app_id): def locate_app(script_info, app_id, raise_if_not_found=True):
"""Attempts to locate the application.""" """Attempts to locate the application."""
__traceback_hide__ = True __traceback_hide__ = True
if ':' in app_id: if ':' in app_id:
module, app_obj = app_id.split(':', 1) module, app_obj = app_id.split(':', 1)
else: else:
@ -192,15 +195,23 @@ def locate_app(script_info, app_id):
# Determine this by checking whether the trace has a depth > 1. # Determine this by checking whether the trace has a depth > 1.
if sys.exc_info()[-1].tb_next: if sys.exc_info()[-1].tb_next:
stack_trace = traceback.format_exc() stack_trace = traceback.format_exc()
raise NoAppException('There was an error trying to import' raise NoAppException(
' the app (%s):\n%s' % (module, stack_trace)) 'There was an error trying to import the app ({module}):\n'
'{stack_trace}'.format(
module=module, stack_trace=stack_trace
)
)
elif raise_if_not_found:
raise NoAppException(
'The file/path provided (%s) does not appear to exist. Please'
' verify the path is correct. If app is not on PYTHONPATH,'
' ensure the extension is .py.'.format(module=module)
)
else: else:
raise NoAppException('The file/path provided (%s) does not appear' return
' to exist. Please verify the path is '
'correct. If app is not on PYTHONPATH, '
'ensure the extension is .py' % module)
mod = sys.modules[module] mod = sys.modules[module]
if app_obj is None: if app_obj is None:
return find_best_app(script_info, mod) return find_best_app(script_info, mod)
else: else:
@ -326,14 +337,26 @@ class ScriptInfo(object):
if self.create_app is not None: if self.create_app is not None:
rv = call_factory(self.create_app, self) rv = call_factory(self.create_app, self)
else: else:
if not self.app_import_path: if self.app_import_path:
rv = locate_app(self, self.app_import_path)
else:
for module in ['wsgi.py', 'app.py']:
import_path = prepare_exec_for_file(module)
rv = locate_app(
self, import_path, raise_if_not_found=False
)
if rv:
break
if not rv:
raise NoAppException( raise NoAppException(
'Could not locate Flask application. You did not provide ' 'Could not locate Flask application. You did not provide '
'the FLASK_APP environment variable.\n\nFor more ' 'the FLASK_APP environment variable, and a wsgi.py or '
'information see ' 'app.py module was not found in the current directory.\n\n'
'http://flask.pocoo.org/docs/latest/quickstart/') 'For more information see '
'http://flask.pocoo.org/docs/latest/quickstart/'
rv = locate_app(self, self.app_import_path) )
debug = get_debug_flag() debug = get_debug_flag()

6
tests/test_apps/helloworld/hello.py

@ -0,0 +1,6 @@
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"

1
tests/test_apps/helloworld/wsgi.py

@ -0,0 +1 @@
from hello import app

24
tests/test_cli.py

@ -181,6 +181,9 @@ def test_locate_app(test_apps):
script_info, "cliapp.factory:create_app ()") script_info, "cliapp.factory:create_app ()")
pytest.raises( pytest.raises(
NoAppException, locate_app, script_info, "cliapp.importerrorapp") NoAppException, locate_app, script_info, "cliapp.importerrorapp")
assert locate_app(
script_info, "notanpp.py", raise_if_not_found=False
) is None
def test_find_default_import_path(test_apps, monkeypatch, tmpdir): def test_find_default_import_path(test_apps, monkeypatch, tmpdir):
@ -214,7 +217,7 @@ def test_get_version(test_apps, capsys):
assert py_ver in out assert py_ver in out
def test_scriptinfo(test_apps): def test_scriptinfo(test_apps, monkeypatch):
"""Test of ScriptInfo.""" """Test of ScriptInfo."""
obj = ScriptInfo(app_import_path="cliapp.app:testapp") obj = ScriptInfo(app_import_path="cliapp.app:testapp")
assert obj.load_app().name == "testapp" assert obj.load_app().name == "testapp"
@ -228,6 +231,25 @@ def test_scriptinfo(test_apps):
assert app.name == "createapp" assert app.name == "createapp"
assert obj.load_app() == app assert obj.load_app() == app
obj = ScriptInfo()
pytest.raises(NoAppException, obj.load_app)
# import app from wsgi.py in current directory
monkeypatch.chdir(os.path.abspath(os.path.join(
os.path.dirname(__file__), 'test_apps', 'helloworld'
)))
obj = ScriptInfo()
app = obj.load_app()
assert app.name == 'hello'
# import app from app.py in current directory
monkeypatch.chdir(os.path.abspath(os.path.join(
os.path.dirname(__file__), 'test_apps', 'cliapp'
)))
obj = ScriptInfo()
app = obj.load_app()
assert app.name == 'testapp'
def test_with_appcontext(runner): def test_with_appcontext(runner):
"""Test of with_appcontext.""" """Test of with_appcontext."""

Loading…
Cancel
Save