From ced719ea18a56f6c4075e08dbe05f0e77eac1866 Mon Sep 17 00:00:00 2001 From: Hendrik Makait Date: Mon, 22 May 2017 12:30:18 -0700 Subject: [PATCH] Auto-detect create_app and make_app factory functions --- flask/cli.py | 15 +++++++++++++++ tests/test_cli.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/flask/cli.py b/flask/cli.py index 3d361be8..cdb7f094 100644 --- a/flask/cli.py +++ b/flask/cli.py @@ -46,6 +46,21 @@ def find_best_app(module): if len(matches) == 1: return matches[0] + + # Search for app factory callables. + for attr_name in 'create_app', 'make_app': + app_factory = getattr(module, attr_name, None) + if app_factory is not None and callable(app_factory): + try: + app = app_factory() + if app is not None and isinstance(app, Flask): + return app + except TypeError: + raise NoAppException('Auto-detected "%s()" in module "%s", ' + 'but could not call it without ' + 'specifying arguments.' + % (attr_name, module.__name__)) + raise NoAppException('Failed to find application in module "%s". Are ' 'you sure it contains a Flask application? Maybe ' 'you wrapped it in a WSGI middleware or you are ' diff --git a/tests/test_cli.py b/tests/test_cli.py index ab875cef..bbb6fe58 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -51,6 +51,34 @@ def test_find_best_app(test_apps): myapp = Flask('appname') assert find_best_app(Module) == Module.myapp + class Module: + @staticmethod + def create_app(): + return Flask('appname') + assert isinstance(find_best_app(Module), Flask) + assert find_best_app(Module).name == 'appname' + + class Module: + @staticmethod + def make_app(): + return Flask('appname') + assert isinstance(find_best_app(Module), Flask) + assert find_best_app(Module).name == 'appname' + + class Module: + myapp = Flask('appname1') + @staticmethod + def create_app(): + return Flask('appname2') + assert find_best_app(Module) == Module.myapp + + class Module: + myapp = Flask('appname1') + @staticmethod + def create_app(foo): + return Flask('appname2') + assert find_best_app(Module) == Module.myapp + class Module: pass pytest.raises(NoAppException, find_best_app, Module) @@ -60,6 +88,12 @@ def test_find_best_app(test_apps): myapp2 = Flask('appname2') pytest.raises(NoAppException, find_best_app, Module) + class Module: + @staticmethod + def create_app(foo): + return Flask('appname2') + pytest.raises(NoAppException, find_best_app, Module) + def test_prepare_exec_for_file(test_apps): """Expect the correct path to be set and the correct module name to be returned.