def test_lazy_load_error(monkeypatch): """When using lazy loading, the correct exception should be re-raised. """ class BadExc(Exception): pass def bad_load(): raise BadExc lazy = DispatchingApp(bad_load, use_eager_loading=False) with pytest.raises(BadExc): lazy._flush_bg_loading_exception()
def test_lazy_load_error(monkeypatch): """When using lazy loading, the correct exception should be re-raised. """ class BadExc(Exception): pass def bad_load(): raise BadExc lazy = DispatchingApp(bad_load, use_eager_loading=False) with pytest.raises(BadExc): # reduce flakiness by waiting for the internal loading lock with lazy._lock: lazy._flush_bg_loading_exception()
def run_command(info, host, port, reload, debugger, eager_loading, with_threads, cert): env = get_env() click.echo(' * Environment: {0}'.format(env)) if env == 'production': from ..gunicorn import WSGIApplication app = WSGIApplication(loader=info.load_app) app.run() else: debug = get_debug_flag() if reload is None: reload = debug if debugger is None: debugger = debug if eager_loading is None: eager_loading = not reload click.echo(' * Debug mode: {0}'.format('on' if debug else 'off')) app = DispatchingApp(info.load_app, use_eager_loading=eager_loading) from werkzeug.serving import run_simple run_simple(host, port, app, use_reloader=reload, use_debugger=debugger, threaded=with_threads, ssl_context=cert)
def staged(info, host, port, *args, **kwargs): import waitress app = DispatchingApp(info.load_app, use_eager_loading=True) applic = info.load_app() host = applic.config.get('HOST', host) port = applic.config.get('PORT', port) API.logger.info("Serving application on http://{}:{}".format(host, port)) waitress.serve(app, host=host, port=port) return
def production(info, host, port, *args, **kwargs): import waitress app = DispatchingApp(info.load_app, use_eager_loading=True) applic = info.load_app() host = applic.config.get('HOST', host) port = applic.config.get('PORT', port) waitress.serve(app, host=host, port=port) return
def ssl(info, host, port, reload, debugger, eager_loading, with_threads, cert, key): """Run a local development server. This server is for development purposes only. It does not provide the stability, security, or performance of production WSGI servers. The reloader and debugger are enabled by default if FLASK_ENV=development or FLASK_DEBUG=1. """ debug = get_debug_flag() if reload is None: reload = debug if debugger is None: debugger = debug if eager_loading is None: eager_loading = not reload show_server_banner(get_env(), debug, info.app_import_path, eager_loading) app = DispatchingApp(info.load_app, use_eager_loading=eager_loading) if cert is None: ssl = info._loaded_app.config.get('SSL', {}) if ssl is {}: raise Exception("'SSL' section in configuration is missing") try: certificate = ssl['CERTIFICATE'] if not os.path.isfile(certificate): raise Exception("Certificate file '%s' not preset.") keyfile = ssl['KEYFILE'] if not os.path.isfile(keyfile): raise Exception("Certificate file '%s' not preset.") cert = (certificate, keyfile) except AttributeError: pass except Exception as exc: raise from werkzeug.serving import run_simple run_simple(host, port, app, use_reloader=reload, reloader_type='stat', use_debugger=debugger, threaded=with_threads, ssl_context=cert) return
def _make_wsgi_app(info, url, evalex_whitelist, proxy): def _load_app(): _reset_state() return info.load_app() url_data = url_parse(url) app = DispatchingApp(_load_app) app = Debuggedfossir(app, evalex_whitelist) app = _make_fossir_dispatcher(app, url_data.path) if proxy: app = ProxyFix(app) QuietWSGIRequestHandler.fossir_URL_PREFIX = url_data.path.rstrip('/') return app
def _make_wsgi_app(info, url, evalex_whitelist, proxy): def _load_app(): _reset_state() return info.load_app() url_data = url_parse(url) app = DispatchingApp(_load_app) app = DebuggedIndico(app, evalex_whitelist) app = _make_indico_dispatcher(app, url_data.path) if proxy: app = ProxyFix(app, x_for=1, x_proto=1, x_host=1) QuietWSGIRequestHandler.INDICO_URL_PREFIX = url_data.path.rstrip('/') return app
def run(info): debug = True # Check that the user has added a proper Flask App info.load_app() show_server_banner(get_env(), debug, info.app_import_path, None) app = DispatchingApp(info.load_app, use_eager_loading=None) run_simple('127.0.0.1', 5000, app, use_reloader=debug, use_debugger=debug, threaded=True)
def _run(): with freeze_time("2019-11-27 18:50"): # See https://github.com/pallets/flask/blob/master/src/flask/cli.py#L829 debug = get_debug_flag() app = DispatchingApp(ScriptInfo().load_app, use_eager_loading=None) run_simple( "127.0.0.1", 5000, app, use_reloader=debug, use_debugger=debug, threaded=True, ssl_context=None, extra_files=None, )
def run(info, host, port, debug, reload, debugger, eager_loading, with_threads): """Runs a local development server for the Flask application. This local server is recommended for development purposes only but it can also be used for simple intranet deployments. By default it will not support any sort of concurrency at all to simplify debugging. This can be changed with the --with-threads option which will enable basic multithreading. The reloader and debugger are by default enabled if the debug flag of Flask is enabled and disabled otherwise. """ import os from flask.cli import DispatchingApp from werkzeug.serving import run_simple if debug != FLASK_DEBUG: set_debug_flag(debug) if reload is None: reload = bool(debug) if debugger is None: debugger = bool(debug) if eager_loading is None: eager_loading = not reload app = DispatchingApp(info.load_app, use_eager_loading=eager_loading) # Extra startup messages. This depends a bit on Werkzeug internals to # not double execute when the reloader kicks in. if os.environ.get('WERKZEUG_RUN_MAIN') != 'true': # 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 "{}"'.format(info.app_import_path)) if debug is not None: print(' * Forcing debug mode {}'.format(debug and 'on' or 'off')) run_simple(host, port, app, use_reloader=reload, use_debugger=debugger, threaded=with_threads)
def develop(info: ScriptInfo) -> None: app = DispatchingApp(info.load_app) path_services = [Path.cwd() / "eNMS" / "automation" / "services"] custom_services_path = environ.get("CUSTOM_SERVICES_PATH") if custom_services_path: path_services.append(Path(custom_services_path)) extra_files = [ file for path in path_services for file in path.glob("**/*.py") ] run_simple( "0.0.0.0", 5000, app, use_reloader=True, use_debugger=True, extra_files=extra_files, )
def serve(info, host, port, reload, debugger, eager_loading, with_threads): ''' Runs a local udata development server. This local server is recommended for development purposes only but it can also be used for simple intranet deployments. By default it will not support any sort of concurrency at all to simplify debugging. This can be changed with the --with-threads option which will enable basic multithreading. The reloader and debugger are by default enabled if the debug flag of Flask is enabled and disabled otherwise. ''' # Werkzeug logger is special and is required # with this configuration for development server logger = logging.getLogger('werkzeug') logger.setLevel(logging.INFO) logger.handlers = [] debug = current_app.config['DEBUG'] if reload is None: reload = bool(debug) if debugger is None: debugger = bool(debug) if eager_loading is None: eager_loading = not reload app = DispatchingApp(info.load_app, use_eager_loading=eager_loading) settings = os.environ.get('UDATA_SETTINGS', os.path.join(os.getcwd(), 'udata.cfg')) extra_files = [settings] if reload: extra_files.extend(assets.manifests_paths()) run_simple(host, port, app, use_reloader=reload, use_debugger=debugger, threaded=with_threads, extra_files=extra_files)
def rundev_command(info, host, port, eager_loading, with_threads): """ Modified from the upstream ``flask.cli.run_command`` to add some debugging and reloading features """ # Set a global flag that indicates that we were invoked from the # command line interface provided server command. This is detected # by Flask.run to make the call into a no-op. This is necessary to # avoid ugly errors when the script that is loaded here also attempts # to start a server. os.environ['FLASK_RUN_FROM_CLI_SERVER'] = '1' os.environ['FLASK_DEBUG'] = '1' debug = True reload = True debugger = True if eager_loading is None: eager_loading = not reload app = DispatchingApp(info.load_app, use_eager_loading=eager_loading) # Extra startup messages. This depends a bit on Werkzeug internals to # not double execute when the reloader kicks in. if os.environ.get('WERKZEUG_RUN_MAIN') != 'true': # 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 debug is not None: print(' * Forcing debug mode %s' % (debug and 'on' or 'off')) run_simple(host, port, app, use_reloader=reload, use_debugger=debugger, threaded=with_threads, extra_files=template_paths(), request_handler=CustomLoggingWSGIRequestHandler)
def dev(info, host, port, reload, debugger, eager_loading, with_threads, cert): """Run a local development server. This server is for development purposes only. It does not provide the stability, security, or performance of production WSGI servers. The reloader and debugger are enabled by default if FLASK_ENV=development or FLASK_DEBUG=1. """ debug = get_debug_flag() if reload is None: reload = debug if debugger is None: debugger = debug if eager_loading is None: eager_loading = not reload show_server_banner(get_env(), debug, info.app_import_path, eager_loading) app = DispatchingApp(info.load_app, use_eager_loading=eager_loading) applic = info.load_app() host = applic.config.get('HOST', host) port = applic.config.get('PORT', port) from werkzeug.serving import run_simple run_simple(host, port, app, use_reloader=reload, reloader_type='stat', use_debugger=debugger, threaded=with_threads, ssl_context=cert) return
def ssl(info, host, port, reload, debugger, eager_loading, with_threads, cert, key): """Run a local development server. This server is for development purposes only. It does not provide the stability, security, or performance of production WSGI servers. The reloader and debugger are enabled by default if FLASK_ENV=development or FLASK_DEBUG=1. """ debug = get_debug_flag() if reload is None: reload = debug if debugger is None: debugger = debug if eager_loading is None: eager_loading = not reload show_server_banner(get_env(), debug, info.app_import_path, eager_loading) app = DispatchingApp(info.load_app, use_eager_loading=eager_loading) applic = info.load_app() if cert is None: ssl = applic.config.get('SSL', {}) if ssl is {}: raise Exception("'SSL' section in configuration is missing") try: certificate = ssl['CERTIFICATE'] if not os.path.isfile(certificate): raise Exception("Certificate file '%s' not preset.") keyfile = ssl['KEYFILE'] if not os.path.isfile(keyfile): raise Exception("Certificate file '%s' not preset.") cert = (certificate, keyfile) except AttributeError: pass except Exception as exc: raise appPath = applic.config.get('APP_PATH', os.curdir) appApiMod = applic.config.get('API_MODULE', '') # As those files may change, but are only loaded when the application starts # we monitor them, so that the application restart when they change extra_files = [ os.path.join(appPath, appApiMod, 'menu.yaml'), os.path.join(appPath, appApiMod, 'release.yaml') ] from werkzeug.serving import run_simple API.logger.info("Serving application on https://{}:{}".format(host, port)) run_simple(host, port, app, use_reloader=reload, reloader_type='stat', use_debugger=debugger, threaded=with_threads, ssl_context=cert, extra_files=extra_files) return
def dev(info, host, port, reload, debugger, eager_loading, with_threads, cert): """Run a local development server. This server is for development purposes only. It does not provide the stability, security, or performance of production WSGI servers. The reloader and debugger are enabled by default if FLASK_ENV=development or FLASK_DEBUG=1. """ debug = get_debug_flag() if reload is None: reload = debug if debugger is None: debugger = debug if eager_loading is None: eager_loading = not reload show_server_banner(get_env(), debug, info.app_import_path, eager_loading) app = DispatchingApp(info.load_app, use_eager_loading=eager_loading) applic = info.load_app() if host is None: host = applic.config.get('HOST', 'localhost') if port is None: port = applic.config.get('PORT', 5000) else: port = int(port) API.logger.info("Serving application on http://{}:{}".format(host, port)) # appPath = applic.config.get( 'APP_PATH', os.curdir ) # appApiMod = applic.config.get( 'API_MODULE', '' ) # As those files may change, but are only loaded when the application starts # we monitor them, so that the application restart when they change extra_files = applic.config.get('EXTRA_FILES', []) appPath = applic.config.get('APP_PATH', os.curdir) appApiMod = applic.config.get('API_MODULE', '') extra_files.extend([ os.path.join(appPath, appApiMod, 'menu.yaml'), os.path.join(appPath, appApiMod, 'release.yaml') ]) if API.socketio is not None: app.debug = True API.socketio.run( app, host, port, debug=debugger, use_reloader=reload, # reloader_type = 'stat', # threaded = with_threads, # ssl_context = cert, extra_files=extra_files) else: from werkzeug.serving import run_simple run_simple(host, port, app, use_reloader=reload, reloader_type='stat', use_debugger=debugger, threaded=with_threads, ssl_context=cert, extra_files=extra_files) return
def run_command(info, host, port, reload, debugger, eager_loading, with_threads, adhoc): """Runs a local development server for the Flask application. This local server is recommended for development purposes only but it can also be used for simple intranet deployments. By default it will not support any sort of concurrency at all to simplify debugging. This can be changed with the --with-threads option which will enable basic multithreading. The reloader and debugger are by default enabled if the debug flag of Flask is enabled and disabled otherwise. Runs https with self singed certificates for localhost. """ if adhoc: context = 'adhoc' else: # get certificates or exit base = os.path.abspath(os.path.dirname(__file__)) keyfiles = set(['localhost.crt', 'localhost.key']) dirfiles = set(os.listdir(base)) missing = keyfiles.difference(dirfiles) if not keyfiles.issubset(dirfiles): click.secho('{} not found.'.format(" and ".join(missing)), fg='red') click.echo('Create a certificate with the following command: ') click.secho( 'openssl req -nodes -x509 -subj "/CN=localhost" -sha256 ' '-newkey rsa:4096 -keyout localhost.key -out localhost.crt ' '-days 365', fg='yellow') click.echo( 'Or use --adhoc for the adhoc ssl context (requires pyopenssl).' ) return from flask.globals import _app_ctx_stack app = _app_ctx_stack.top.app context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.load_cert_chain(certfile='localhost.crt', keyfile='localhost.key') from werkzeug.serving import run_simple from flask.cli import get_debug_flag, DispatchingApp debug = get_debug_flag() if reload is None: reload = bool(debug) if debugger is None: debugger = bool(debug) if eager_loading is None: eager_loading = not reload app = DispatchingApp(info.load_app, use_eager_loading=eager_loading) # Extra startup messages. This depends a bit on Werkzeug internals to # not double execute when the reloader kicks in. if os.environ.get('WERKZEUG_RUN_MAIN') != 'true': # 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 debug is not None: print(' * Forcing debug mode %s' % (debug and 'on' or 'off')) run_simple(host, port, app, use_reloader=reload, ssl_context=context, use_debugger=debugger, threaded=with_threads)
def run_server(info, host, port, reload, debugger, eager_loading, debug, wsgi): """Runs a local development server for the Flask application. This local server is recommended for development purposes only but it can also be used for simple intranet deployments. By default it will not support any sort of concurrency at all to simplify debugging. The reloader and debugger are by default enabled if the debug flag of Flask is enabled and disabled otherwise. This is very similar to flask.cli.run_command; with the main addition of the --wsgi flag """ info.app_import_path = 'idb.data_api.api:app' info.debug = debug from idb import config if reload is None: reload = info.debug if debugger is None: debugger = info.debug if eager_loading is None: eager_loading = not reload if wsgi is None: if (debug or debugger or reload or config.ENV in ('dev', )): wsgi = 'werkzeug' else: wsgi = 'gevent' if wsgi == 'werkzeug': from werkzeug.serving import run_simple from flask.cli import DispatchingApp app = DispatchingApp(info.load_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': # 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("Werkzeug server @ http://{0}:{1}/ ENV={2}".format( host, port, config.ENV), file=sys.stderr) if info.debug is not None: print(' * Forcing debug %s' % (info.debug and 'on' or 'off')) run_simple(host, port, app, use_reloader=reload, use_debugger=debugger, threaded=False, passthrough_errors=True) elif wsgi == 'gevent': from gevent.pool import Pool from gevent.wsgi import WSGIServer from idb.helpers.logging import idblogger from requestlogger import WSGILogger, ApacheFormatter logger = idblogger.getChild('api') from werkzeug.contrib.fixers import ProxyFix logger.info("gevent server @ http://%s:%s/ ENV=%s", host, port, config.ENV) app = info.load_app() app = WSGILogger(app, [], ApacheFormatter()) app.logger = logger.getChild('r') app = ProxyFix(app) http_server = WSGIServer(('', 19197), app, spawn=Pool(1000), log=None) http_server.serve_forever() else: raise ValueError('Unknown wsgi backend type', wsgi)