10
10
import typing as t
11
11
from functools import update_wrapper
12
12
from operator import attrgetter
13
- from threading import Lock
14
- from threading import Thread
15
13
16
14
import click
17
15
from click .core import ParameterSource
@@ -267,74 +265,6 @@ def get_version(ctx, param, value):
267
265
)
268
266
269
267
270
- class DispatchingApp :
271
- """Special application that dispatches to a Flask application which
272
- is imported by name in a background thread. If an error happens
273
- it is recorded and shown as part of the WSGI handling which in case
274
- of the Werkzeug debugger means that it shows up in the browser.
275
- """
276
-
277
- def __init__ (self , loader , use_eager_loading = None ):
278
- self .loader = loader
279
- self ._app = None
280
- self ._lock = Lock ()
281
- self ._bg_loading_exc = None
282
-
283
- if use_eager_loading is None :
284
- use_eager_loading = not is_running_from_reloader ()
285
-
286
- if use_eager_loading :
287
- self ._load_unlocked ()
288
- else :
289
- self ._load_in_background ()
290
-
291
- def _load_in_background (self ):
292
- # Store the Click context and push it in the loader thread so
293
- # script_info is still available.
294
- ctx = click .get_current_context (silent = True )
295
-
296
- def _load_app ():
297
- __traceback_hide__ = True # noqa: F841
298
-
299
- with self ._lock :
300
- if ctx is not None :
301
- click .globals .push_context (ctx )
302
-
303
- try :
304
- self ._load_unlocked ()
305
- except Exception as e :
306
- self ._bg_loading_exc = e
307
-
308
- t = Thread (target = _load_app , args = ())
309
- t .start ()
310
-
311
- def _flush_bg_loading_exception (self ):
312
- __traceback_hide__ = True # noqa: F841
313
- exc = self ._bg_loading_exc
314
-
315
- if exc is not None :
316
- self ._bg_loading_exc = None
317
- raise exc
318
-
319
- def _load_unlocked (self ):
320
- __traceback_hide__ = True # noqa: F841
321
- self ._app = rv = self .loader ()
322
- self ._bg_loading_exc = None
323
- return rv
324
-
325
- def __call__ (self , environ , start_response ):
326
- __traceback_hide__ = True # noqa: F841
327
- if self ._app is not None :
328
- return self ._app (environ , start_response )
329
- self ._flush_bg_loading_exception ()
330
- with self ._lock :
331
- if self ._app is not None :
332
- rv = self ._app
333
- else :
334
- rv = self ._load_unlocked ()
335
- return rv (environ , start_response )
336
-
337
-
338
268
class ScriptInfo :
339
269
"""Helper object to deal with Flask applications. This is usually not
340
270
necessary to interface with as it's used internally in the dispatching
@@ -811,20 +741,15 @@ def load_dotenv(path: str | os.PathLike | None = None) -> bool:
811
741
return loaded # True if at least one file was located and loaded.
812
742
813
743
814
- def show_server_banner (env , debug , app_import_path , eager_loading ):
744
+ def show_server_banner (env , debug , app_import_path ):
815
745
"""Show extra startup messages the first time the server is run,
816
746
ignoring the reloader.
817
747
"""
818
748
if is_running_from_reloader ():
819
749
return
820
750
821
751
if app_import_path is not None :
822
- message = f" * Serving Flask app { app_import_path !r} "
823
-
824
- if not eager_loading :
825
- message += " (lazy loading)"
826
-
827
- click .echo (message )
752
+ click .echo (f" * Serving Flask app '{ app_import_path } '" )
828
753
829
754
click .echo (f" * Environment: { env } " )
830
755
@@ -963,12 +888,6 @@ def convert(self, value, param, ctx):
963
888
help = "Enable or disable the debugger. By default the debugger "
964
889
"is active if debug is enabled." ,
965
890
)
966
- @click .option (
967
- "--eager-loading/--lazy-loading" ,
968
- default = None ,
969
- help = "Enable or disable eager loading. By default eager "
970
- "loading is enabled if the reloader is disabled." ,
971
- )
972
891
@click .option (
973
892
"--with-threads/--without-threads" ,
974
893
default = True ,
@@ -1000,7 +919,6 @@ def run_command(
1000
919
port ,
1001
920
reload ,
1002
921
debugger ,
1003
- eager_loading ,
1004
922
with_threads ,
1005
923
cert ,
1006
924
extra_files ,
@@ -1014,7 +932,23 @@ def run_command(
1014
932
The reloader and debugger are enabled by default with the
1015
933
'--env development' or '--debug' options.
1016
934
"""
1017
- app = DispatchingApp (info .load_app , use_eager_loading = eager_loading )
935
+ try :
936
+ app = info .load_app ()
937
+ except Exception as e :
938
+ if is_running_from_reloader ():
939
+ # When reloading, print out the error immediately, but raise
940
+ # it later so the debugger or server can handle it.
941
+ traceback .print_exc ()
942
+ err = e
943
+
944
+ def app (environ , start_response ):
945
+ raise err from None
946
+
947
+ else :
948
+ # When not reloading, raise the error immediately so the
949
+ # command fails.
950
+ raise e from None
951
+
1018
952
debug = get_debug_flag ()
1019
953
1020
954
if reload is None :
@@ -1023,7 +957,7 @@ def run_command(
1023
957
if debugger is None :
1024
958
debugger = debug
1025
959
1026
- show_server_banner (get_env (), debug , info .app_import_path , eager_loading )
960
+ show_server_banner (get_env (), debug , info .app_import_path )
1027
961
1028
962
from werkzeug .serving import run_simple
1029
963
0 commit comments