Refactored script info to allow more advanced patterns.
This commit is contained in:
parent
b9013ede22
commit
4532e89efe
1 changed files with 43 additions and 17 deletions
60
flask/cli.py
60
flask/cli.py
|
|
@ -110,38 +110,44 @@ class DispatchingApp(object):
|
|||
errors for import problems into the browser as error.
|
||||
"""
|
||||
|
||||
def __init__(self, app_id, debug=None, use_eager_loading=False):
|
||||
self.app_id = app_id
|
||||
self.app = None
|
||||
self.debug = debug
|
||||
def __init__(self, loader, use_eager_loading=False):
|
||||
self.loader = loader
|
||||
self._app = None
|
||||
self._lock = Lock()
|
||||
if use_eager_loading:
|
||||
self._load_unlocked()
|
||||
|
||||
def _load_unlocked(self):
|
||||
self.app = rv = locate_app(self.app_id, self.debug)
|
||||
self._app = rv = self.loader()
|
||||
return rv
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
if self.app is not None:
|
||||
return self.app(environ, start_response)
|
||||
if self._app is not None:
|
||||
return self._app(environ, start_response)
|
||||
with self._lock:
|
||||
if self.app is not None:
|
||||
rv = self.app
|
||||
if self._app is not None:
|
||||
rv = self._app
|
||||
else:
|
||||
rv = self._load_unlocked()
|
||||
return rv(environ, start_response)
|
||||
|
||||
|
||||
def _no_such_app():
|
||||
raise NoAppException('Could not locate Flask application. '
|
||||
'You did not provide FLASK_APP or the '
|
||||
'--app parameter.')
|
||||
|
||||
|
||||
class ScriptInfo(object):
|
||||
"""Help object to deal with Flask applications. This is usually not
|
||||
necessary to interface with as it's used internally in the dispatching
|
||||
to click.
|
||||
"""
|
||||
|
||||
def __init__(self, app_import_path=None, debug=None):
|
||||
def __init__(self, app_import_path=None, debug=None, load_callback=None):
|
||||
self.app_import_path = app_import_path
|
||||
self.debug = debug
|
||||
self.load_callback = load_callback
|
||||
self._loaded_app = None
|
||||
|
||||
def get_app_import_path(self):
|
||||
|
|
@ -150,18 +156,33 @@ class ScriptInfo(object):
|
|||
"""
|
||||
if self.app_import_path is not None:
|
||||
return self.app_import_path
|
||||
raise NoAppException('Could not locate application. '
|
||||
'You did not provide FLASK_APP or the '
|
||||
'--app parameter.')
|
||||
_no_such_app()
|
||||
|
||||
def load_app(self):
|
||||
"""Loads the app (if not yet loaded) and returns it."""
|
||||
if self._loaded_app is not None:
|
||||
return self._loaded_app
|
||||
rv = locate_app(self.get_app_import_path(), self.debug)
|
||||
if self.load_callback is not None:
|
||||
rv = self.load_callback()
|
||||
else:
|
||||
rv = locate_app(self.get_app_import_path(), self.debug)
|
||||
self._loaded_app = rv
|
||||
return rv
|
||||
|
||||
def make_wsgi_app(self, use_eager_loading=False):
|
||||
"""Returns a WSGI app that loads the actual application at a
|
||||
later stage.
|
||||
"""
|
||||
if self.app_import_path is not None:
|
||||
def loader():
|
||||
return locate_app(self.app_import_path, self.debug)
|
||||
else:
|
||||
if self.load_callback is None:
|
||||
_no_such_app()
|
||||
def loader():
|
||||
return self.load_callback()
|
||||
return DispatchingApp(loader, use_eager_loading=use_eager_loading)
|
||||
|
||||
@contextmanager
|
||||
def conditional_context(self, with_context=True):
|
||||
"""Creates an application context or not, depending on the
|
||||
|
|
@ -281,7 +302,6 @@ def run_command(info, host, port, reload, debugger, eager_loading,
|
|||
with_threads):
|
||||
"""Runs a local development server for the Flask application."""
|
||||
from werkzeug.serving import run_simple
|
||||
app_id = info.get_app_import_path()
|
||||
if reload is None:
|
||||
reload = info.debug
|
||||
if debugger is None:
|
||||
|
|
@ -289,14 +309,20 @@ def run_command(info, host, port, reload, debugger, eager_loading,
|
|||
if eager_loading is None:
|
||||
eager_loading = not reload
|
||||
|
||||
app = info.make_wsgi_app(use_eager_loading=eager_loading)
|
||||
|
||||
# Extra startup messages. This depends a but on Werkzeug internals to
|
||||
# not double execute when the reloader kicks in.
|
||||
if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
|
||||
print(' * Serving Flask app "%s"' % app_id)
|
||||
# If we have an import path we can print it out now which can help
|
||||
# people understand what's being served. If we do not have an
|
||||
# import path because the app was loaded through a callback then
|
||||
# we won't print anything.
|
||||
if info.app_import_path is not None:
|
||||
print(' * Serving Flask app "%s"' % info.app_import_path)
|
||||
if info.debug is not None:
|
||||
print(' * Forcing debug %s' % (info.debug and 'on' or 'off'))
|
||||
|
||||
app = DispatchingApp(app_id, info.debug, eager_loading)
|
||||
run_simple(host, port, app, use_reloader=reload,
|
||||
use_debugger=debugger, threaded=with_threads)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue