Browse Source

Check if app factory takes script_info argument and call it with(out) script_info as an argument depending on that

pull/2319/head
Hendrik Makait 8 years ago
parent
commit
ae41df9a77
  1. 2
      flask/_compat.py
  2. 30
      flask/cli.py
  3. 62
      tests/test_cli.py

2
flask/_compat.py

@ -25,6 +25,7 @@ if not PY2:
itervalues = lambda d: iter(d.values()) itervalues = lambda d: iter(d.values())
iteritems = lambda d: iter(d.items()) iteritems = lambda d: iter(d.items())
from inspect import getfullargspec as getargspec
from io import StringIO from io import StringIO
def reraise(tp, value, tb=None): def reraise(tp, value, tb=None):
@ -43,6 +44,7 @@ else:
itervalues = lambda d: d.itervalues() itervalues = lambda d: d.itervalues()
iteritems = lambda d: d.iteritems() iteritems = lambda d: d.iteritems()
from inspect import getargspec
from cStringIO import StringIO from cStringIO import StringIO
exec('def reraise(tp, value, tb=None):\n raise tp, value, tb') exec('def reraise(tp, value, tb=None):\n raise tp, value, tb')

30
flask/cli.py

@ -22,13 +22,14 @@ from . import __version__
from ._compat import iteritems, reraise from ._compat import 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
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."""
def find_best_app(module): def find_best_app(script_info, module):
"""Given a module instance this tries to find the best possible """Given a module instance this tries to find the best possible
application in the module or raises an exception. application in the module or raises an exception.
""" """
@ -60,8 +61,8 @@ def find_best_app(module):
if callable(app_factory): if callable(app_factory):
try: try:
app = app_factory() app = check_factory_for_script_info_and_call(app_factory,
script_info)
if isinstance(app, Flask): if isinstance(app, Flask):
return app return app
except TypeError: except TypeError:
@ -79,6 +80,21 @@ def find_best_app(module):
) )
def check_factory_for_script_info_and_call(func, script_info):
"""Given a function this checks if the function has an argument named
script_info or just a single argument and calls the function with
script_info if so. Otherwise calls the function without any arguments and
returns the result."""
arguments = getargspec(func).args
if 'script_info' in arguments:
result = func(script_info=script_info)
elif len(arguments) == 1:
result = func(script_info)
else:
result = func()
return result
def prepare_exec_for_file(filename): def prepare_exec_for_file(filename):
"""Given a filename this will try to calculate the python path, add it """Given a filename this will try to calculate the python path, add it
to the search path and return the actual module name that is expected. to the search path and return the actual module name that is expected.
@ -108,7 +124,7 @@ def prepare_exec_for_file(filename):
return '.'.join(module[::-1]) return '.'.join(module[::-1])
def locate_app(app_id): def locate_app(script_info, app_id):
"""Attempts to locate the application.""" """Attempts to locate the application."""
__traceback_hide__ = True __traceback_hide__ = True
if ':' in app_id: if ':' in app_id:
@ -134,7 +150,7 @@ def locate_app(app_id):
mod = sys.modules[module] mod = sys.modules[module]
if app_obj is None: if app_obj is None:
app = find_best_app(mod) app = find_best_app(script_info, mod)
else: else:
app = getattr(mod, app_obj, None) app = getattr(mod, app_obj, None)
if app is None: if app is None:
@ -259,7 +275,7 @@ class ScriptInfo(object):
if self._loaded_app is not None: if self._loaded_app is not None:
return self._loaded_app return self._loaded_app
if self.create_app is not None: if self.create_app is not None:
rv = self.create_app(self) rv = check_factory_for_script_info_and_call(self.create_app, self)
else: else:
if not self.app_import_path: if not self.app_import_path:
raise NoAppException( raise NoAppException(
@ -267,7 +283,7 @@ class ScriptInfo(object):
'the FLASK_APP environment variable.\n\nFor more ' 'the FLASK_APP environment variable.\n\nFor more '
'information see ' 'information see '
'http://flask.pocoo.org/docs/latest/quickstart/') 'http://flask.pocoo.org/docs/latest/quickstart/')
rv = locate_app(self.app_import_path) rv = locate_app(self, self.app_import_path)
debug = get_debug_flag() debug = get_debug_flag()
if debug is not None: if debug is not None:
rv.debug = debug rv.debug = debug

62
tests/test_cli.py

@ -39,60 +39,75 @@ def test_cli_name(test_apps):
def test_find_best_app(test_apps): def test_find_best_app(test_apps):
"""Test if `find_best_app` behaves as expected with different combinations of input.""" """Test if `find_best_app` behaves as expected with different combinations of input."""
script_info = ScriptInfo()
class Module: class Module:
app = Flask('appname') app = Flask('appname')
assert find_best_app(Module) == Module.app assert find_best_app(script_info, Module) == Module.app
class Module: class Module:
application = Flask('appname') application = Flask('appname')
assert find_best_app(Module) == Module.application assert find_best_app(script_info, Module) == Module.application
class Module: class Module:
myapp = Flask('appname') myapp = Flask('appname')
assert find_best_app(Module) == Module.myapp assert find_best_app(script_info, Module) == Module.myapp
class Module: class Module:
@staticmethod @staticmethod
def create_app(): def create_app():
return Flask('appname') return Flask('appname')
assert isinstance(find_best_app(Module), Flask) assert isinstance(find_best_app(script_info, Module), Flask)
assert find_best_app(Module).name == 'appname' assert find_best_app(script_info, Module).name == 'appname'
class Module:
@staticmethod
def create_app(foo):
return Flask('appname')
assert isinstance(find_best_app(script_info, Module), Flask)
assert find_best_app(script_info, Module).name == 'appname'
class Module:
@staticmethod
def create_app(foo=None, script_info=None):
return Flask('appname')
assert isinstance(find_best_app(script_info, Module), Flask)
assert find_best_app(script_info, Module).name == 'appname'
class Module: class Module:
@staticmethod @staticmethod
def make_app(): def make_app():
return Flask('appname') return Flask('appname')
assert isinstance(find_best_app(Module), Flask) assert isinstance(find_best_app(script_info, Module), Flask)
assert find_best_app(Module).name == 'appname' assert find_best_app(script_info, Module).name == 'appname'
class Module: class Module:
myapp = Flask('appname1') myapp = Flask('appname1')
@staticmethod @staticmethod
def create_app(): def create_app():
return Flask('appname2') return Flask('appname2')
assert find_best_app(Module) == Module.myapp assert find_best_app(script_info, Module) == Module.myapp
class Module: class Module:
myapp = Flask('appname1') myapp = Flask('appname1')
@staticmethod @staticmethod
def create_app(foo): def create_app():
return Flask('appname2') return Flask('appname2')
assert find_best_app(Module) == Module.myapp assert find_best_app(script_info, Module) == Module.myapp
class Module: class Module:
pass pass
pytest.raises(NoAppException, find_best_app, Module) pytest.raises(NoAppException, find_best_app, script_info, Module)
class Module: class Module:
myapp1 = Flask('appname1') myapp1 = Flask('appname1')
myapp2 = Flask('appname2') myapp2 = Flask('appname2')
pytest.raises(NoAppException, find_best_app, Module) pytest.raises(NoAppException, find_best_app, script_info, Module)
class Module: class Module:
@staticmethod @staticmethod
def create_app(foo): def create_app(foo, bar):
return Flask('appname2') return Flask('appname2')
pytest.raises(NoAppException, find_best_app, Module) pytest.raises(NoAppException, find_best_app, script_info, Module)
def test_prepare_exec_for_file(test_apps): def test_prepare_exec_for_file(test_apps):
@ -117,13 +132,18 @@ def test_prepare_exec_for_file(test_apps):
def test_locate_app(test_apps): def test_locate_app(test_apps):
"""Test of locate_app.""" """Test of locate_app."""
assert locate_app("cliapp.app").name == "testapp" script_info = ScriptInfo()
assert locate_app("cliapp.app:testapp").name == "testapp" assert locate_app(script_info, "cliapp.app").name == "testapp"
assert locate_app("cliapp.multiapp:app1").name == "app1" assert locate_app(script_info, "cliapp.app:testapp").name == "testapp"
pytest.raises(NoAppException, locate_app, "notanpp.py") assert locate_app(script_info, "cliapp.multiapp:app1").name == "app1"
pytest.raises(NoAppException, locate_app, "cliapp/app") pytest.raises(NoAppException, locate_app,
pytest.raises(RuntimeError, locate_app, "cliapp.app:notanapp") script_info, "notanpp.py")
pytest.raises(NoAppException, locate_app, "cliapp.importerrorapp") pytest.raises(NoAppException, locate_app,
script_info, "cliapp/app")
pytest.raises(RuntimeError, locate_app,
script_info, "cliapp.app:notanapp")
pytest.raises(NoAppException, locate_app,
script_info, "cliapp.importerrorapp")
def test_find_default_import_path(test_apps, monkeypatch, tmpdir): def test_find_default_import_path(test_apps, monkeypatch, tmpdir):

Loading…
Cancel
Save