chore: encapsulate flask app into superset app (#15281)

This commit is contained in:
ofekisr 2021-06-21 16:05:05 +03:00 committed by GitHub
parent b28d7eace3
commit cd0e03a57f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 34 deletions

View File

@ -26,7 +26,7 @@ logger = logging.getLogger(__name__)
def create_app() -> Flask: def create_app() -> Flask:
app = Flask(__name__) app = SupersetApp(__name__)
try: try:
# Allow user to override our config completely # Allow user to override our config completely
@ -42,3 +42,7 @@ def create_app() -> Flask:
except Exception as ex: except Exception as ex:
logger.exception("Failed to create app") logger.exception("Failed to create app")
raise ex raise ex
class SupersetApp(Flask):
pass

View File

@ -14,10 +14,11 @@
# KIND, either express or implied. See the License for the # KIND, either express or implied. See the License for the
# specific language governing permissions and limitations # specific language governing permissions and limitations
# under the License. # under the License.
from __future__ import annotations
import logging import logging
import os import os
from typing import Any, Callable, Dict from typing import Any, Callable, Dict, TYPE_CHECKING
import wtforms_json import wtforms_json
from flask import Flask, redirect from flask import Flask, redirect
@ -48,15 +49,18 @@ from superset.typing import FlaskResponse
from superset.utils.core import pessimistic_connection_handling from superset.utils.core import pessimistic_connection_handling
from superset.utils.log import DBEventLogger, get_event_logger_from_cfg_value from superset.utils.log import DBEventLogger, get_event_logger_from_cfg_value
if TYPE_CHECKING:
from superset.app import SupersetApp
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# pylint: disable=R0904 # pylint: disable=R0904
class SupersetAppInitializer: class SupersetAppInitializer:
def __init__(self, app: Flask) -> None: def __init__(self, app: SupersetApp) -> None:
super().__init__() super().__init__()
self.flask_app = app self.superset_app = app
self.config = app.config self.config = app.config
self.manifest: Dict[Any, Any] = {} self.manifest: Dict[Any, Any] = {}
@ -77,7 +81,7 @@ class SupersetAppInitializer:
def configure_celery(self) -> None: def configure_celery(self) -> None:
celery_app.config_from_object(self.config["CELERY_CONFIG"]) celery_app.config_from_object(self.config["CELERY_CONFIG"])
celery_app.set_default() celery_app.set_default()
flask_app = self.flask_app superset_app = self.superset_app
# Here, we want to ensure that every call into Celery task has an app context # Here, we want to ensure that every call into Celery task has an app context
# setup properly # setup properly
@ -89,7 +93,7 @@ class SupersetAppInitializer:
# Grab each call into the task and set up an app context # Grab each call into the task and set up an app context
def __call__(self, *args: Any, **kwargs: Any) -> Any: def __call__(self, *args: Any, **kwargs: Any) -> Any:
with flask_app.app_context(): # type: ignore with superset_app.app_context(): # type: ignore
return task_base.__call__(self, *args, **kwargs) return task_base.__call__(self, *args, **kwargs)
celery_app.Task = AppContextTask celery_app.Task = AppContextTask
@ -538,7 +542,7 @@ class SupersetAppInitializer:
# after initialization # after initialization
flask_app_mutator = self.config["FLASK_APP_MUTATOR"] flask_app_mutator = self.config["FLASK_APP_MUTATOR"]
if flask_app_mutator: if flask_app_mutator:
flask_app_mutator(self.flask_app) flask_app_mutator(self.superset_app)
self.init_views() self.init_views()
@ -563,17 +567,17 @@ class SupersetAppInitializer:
self.configure_middlewares() self.configure_middlewares()
self.configure_cache() self.configure_cache()
with self.flask_app.app_context(): # type: ignore with self.superset_app.app_context(): # type: ignore
self.init_app_in_ctx() self.init_app_in_ctx()
self.post_init() self.post_init()
def configure_auth_provider(self) -> None: def configure_auth_provider(self) -> None:
machine_auth_provider_factory.init_app(self.flask_app) machine_auth_provider_factory.init_app(self.superset_app)
def setup_event_logger(self) -> None: def setup_event_logger(self) -> None:
_event_logger["event_logger"] = get_event_logger_from_cfg_value( _event_logger["event_logger"] = get_event_logger_from_cfg_value(
self.flask_app.config.get("EVENT_LOGGER", DBEventLogger()) self.superset_app.config.get("EVENT_LOGGER", DBEventLogger())
) )
def configure_data_sources(self) -> None: def configure_data_sources(self) -> None:
@ -583,11 +587,11 @@ class SupersetAppInitializer:
ConnectorRegistry.register_sources(module_datasource_map) ConnectorRegistry.register_sources(module_datasource_map)
def configure_cache(self) -> None: def configure_cache(self) -> None:
cache_manager.init_app(self.flask_app) cache_manager.init_app(self.superset_app)
results_backend_manager.init_app(self.flask_app) results_backend_manager.init_app(self.superset_app)
def configure_feature_flags(self) -> None: def configure_feature_flags(self) -> None:
feature_flag_manager.init_app(self.flask_app) feature_flag_manager.init_app(self.superset_app)
def configure_fab(self) -> None: def configure_fab(self) -> None:
if self.config["SILENCE_FAB"]: if self.config["SILENCE_FAB"]:
@ -604,7 +608,7 @@ class SupersetAppInitializer:
appbuilder.indexview = SupersetIndexView appbuilder.indexview = SupersetIndexView
appbuilder.base_template = "superset/base.html" appbuilder.base_template = "superset/base.html"
appbuilder.security_manager_class = custom_sm appbuilder.security_manager_class = custom_sm
appbuilder.init_app(self.flask_app, db.session) appbuilder.init_app(self.superset_app, db.session)
def configure_url_map_converters(self) -> None: def configure_url_map_converters(self) -> None:
# #
@ -616,20 +620,20 @@ class SupersetAppInitializer:
RegexConverter, RegexConverter,
) )
self.flask_app.url_map.converters["regex"] = RegexConverter self.superset_app.url_map.converters["regex"] = RegexConverter
self.flask_app.url_map.converters["object_type"] = ObjectTypeConverter self.superset_app.url_map.converters["object_type"] = ObjectTypeConverter
def configure_middlewares(self) -> None: def configure_middlewares(self) -> None:
if self.config["ENABLE_CORS"]: if self.config["ENABLE_CORS"]:
from flask_cors import CORS from flask_cors import CORS
CORS(self.flask_app, **self.config["CORS_OPTIONS"]) CORS(self.superset_app, **self.config["CORS_OPTIONS"])
if self.config["ENABLE_PROXY_FIX"]: if self.config["ENABLE_PROXY_FIX"]:
from werkzeug.middleware.proxy_fix import ProxyFix from werkzeug.middleware.proxy_fix import ProxyFix
self.flask_app.wsgi_app = ProxyFix( # type: ignore self.superset_app.wsgi_app = ProxyFix( # type: ignore
self.flask_app.wsgi_app, **self.config["PROXY_FIX_CONFIG"] self.superset_app.wsgi_app, **self.config["PROXY_FIX_CONFIG"]
) )
if self.config["ENABLE_CHUNK_ENCODING"]: if self.config["ENABLE_CHUNK_ENCODING"]:
@ -647,8 +651,8 @@ class SupersetAppInitializer:
environ["wsgi.input_terminated"] = True environ["wsgi.input_terminated"] = True
return self.app(environ, start_response) return self.app(environ, start_response)
self.flask_app.wsgi_app = ChunkedEncodingFix( # type: ignore self.superset_app.wsgi_app = ChunkedEncodingFix( # type: ignore
self.flask_app.wsgi_app # type: ignore self.superset_app.wsgi_app # type: ignore
) )
if self.config["UPLOAD_FOLDER"]: if self.config["UPLOAD_FOLDER"]:
@ -658,53 +662,53 @@ class SupersetAppInitializer:
pass pass
for middleware in self.config["ADDITIONAL_MIDDLEWARE"]: for middleware in self.config["ADDITIONAL_MIDDLEWARE"]:
self.flask_app.wsgi_app = middleware( # type: ignore self.superset_app.wsgi_app = middleware( # type: ignore
self.flask_app.wsgi_app self.superset_app.wsgi_app
) )
# Flask-Compress # Flask-Compress
Compress(self.flask_app) Compress(self.superset_app)
if self.config["TALISMAN_ENABLED"]: if self.config["TALISMAN_ENABLED"]:
talisman.init_app(self.flask_app, **self.config["TALISMAN_CONFIG"]) talisman.init_app(self.superset_app, **self.config["TALISMAN_CONFIG"])
def configure_logging(self) -> None: def configure_logging(self) -> None:
self.config["LOGGING_CONFIGURATOR"].configure_logging( self.config["LOGGING_CONFIGURATOR"].configure_logging(
self.config, self.flask_app.debug self.config, self.superset_app.debug
) )
def configure_db_encrypt(self) -> None: def configure_db_encrypt(self) -> None:
encrypted_field_factory.init_app(self.flask_app) encrypted_field_factory.init_app(self.superset_app)
def setup_db(self) -> None: def setup_db(self) -> None:
db.init_app(self.flask_app) db.init_app(self.superset_app)
with self.flask_app.app_context(): # type: ignore with self.superset_app.app_context(): # type: ignore
pessimistic_connection_handling(db.engine) pessimistic_connection_handling(db.engine)
migrate.init_app(self.flask_app, db=db, directory=APP_DIR + "/migrations") migrate.init_app(self.superset_app, db=db, directory=APP_DIR + "/migrations")
def configure_wtf(self) -> None: def configure_wtf(self) -> None:
if self.config["WTF_CSRF_ENABLED"]: if self.config["WTF_CSRF_ENABLED"]:
csrf.init_app(self.flask_app) csrf.init_app(self.superset_app)
csrf_exempt_list = self.config["WTF_CSRF_EXEMPT_LIST"] csrf_exempt_list = self.config["WTF_CSRF_EXEMPT_LIST"]
for ex in csrf_exempt_list: for ex in csrf_exempt_list:
csrf.exempt(ex) csrf.exempt(ex)
def configure_async_queries(self) -> None: def configure_async_queries(self) -> None:
if feature_flag_manager.is_feature_enabled("GLOBAL_ASYNC_QUERIES"): if feature_flag_manager.is_feature_enabled("GLOBAL_ASYNC_QUERIES"):
async_query_manager.init_app(self.flask_app) async_query_manager.init_app(self.superset_app)
def register_blueprints(self) -> None: def register_blueprints(self) -> None:
for bp in self.config["BLUEPRINTS"]: for bp in self.config["BLUEPRINTS"]:
try: try:
logger.info("Registering blueprint: %s", bp.name) logger.info("Registering blueprint: %s", bp.name)
self.flask_app.register_blueprint(bp) self.superset_app.register_blueprint(bp)
except Exception: # pylint: disable=broad-except except Exception: # pylint: disable=broad-except
logger.exception("blueprint registration failed") logger.exception("blueprint registration failed")
def setup_bundle_manifest(self) -> None: def setup_bundle_manifest(self) -> None:
manifest_processor.init_app(self.flask_app) manifest_processor.init_app(self.superset_app)
class SupersetIndexView(IndexView): class SupersetIndexView(IndexView):