| """Package's main module!""" |
| from __future__ import absolute_import |
| from __future__ import division |
| from __future__ import print_function |
| from __future__ import unicode_literals |
| |
| import json |
| import logging |
| from logging.handlers import TimedRotatingFileHandler |
| import os |
| |
| from flask import Flask, redirect |
| from flask_appbuilder import AppBuilder, IndexView, SQLA |
| from flask_appbuilder.baseviews import expose |
| from flask_migrate import Migrate |
| from flask_wtf.csrf import CSRFProtect |
| from werkzeug.contrib.fixers import ProxyFix |
| |
| from superset.connectors.connector_registry import ConnectorRegistry |
| from superset import utils, config # noqa |
| |
| APP_DIR = os.path.dirname(__file__) |
| CONFIG_MODULE = os.environ.get('SUPERSET_CONFIG', 'superset.config') |
| |
| if not os.path.exists(config.DATA_DIR): |
| os.makedirs(config.DATA_DIR) |
| |
| with open(APP_DIR + '/static/assets/backendSync.json', 'r') as f: |
| frontend_config = json.load(f) |
| |
| app = Flask(__name__) |
| app.config.from_object(CONFIG_MODULE) |
| conf = app.config |
| |
| ################################################################# |
| # Handling manifest file logic at app start |
| ################################################################# |
| MANIFEST_FILE = APP_DIR + '/static/assets/dist/manifest.json' |
| manifest = {} |
| |
| |
| def parse_manifest_json(): |
| global manifest |
| try: |
| with open(MANIFEST_FILE, 'r') as f: |
| manifest = json.load(f) |
| except Exception: |
| pass |
| |
| |
| def get_manifest_file(filename): |
| if app.debug: |
| parse_manifest_json() |
| return '/static/assets/dist/' + manifest.get(filename, '') |
| |
| |
| parse_manifest_json() |
| |
| |
| @app.context_processor |
| def get_js_manifest(): |
| return dict(js_manifest=get_manifest_file) |
| |
| |
| ################################################################# |
| |
| for bp in conf.get('BLUEPRINTS'): |
| try: |
| print("Registering blueprint: '{}'".format(bp.name)) |
| app.register_blueprint(bp) |
| except Exception as e: |
| print('blueprint registration failed') |
| logging.exception(e) |
| |
| if conf.get('SILENCE_FAB'): |
| logging.getLogger('flask_appbuilder').setLevel(logging.ERROR) |
| |
| if not app.debug: |
| # In production mode, add log handler to sys.stderr. |
| app.logger.addHandler(logging.StreamHandler()) |
| app.logger.setLevel(logging.INFO) |
| logging.getLogger('pyhive.presto').setLevel(logging.INFO) |
| |
| db = SQLA(app) |
| |
| if conf.get('WTF_CSRF_ENABLED'): |
| csrf = CSRFProtect(app) |
| csrf_exempt_list = conf.get('WTF_CSRF_EXEMPT_LIST', []) |
| for ex in csrf_exempt_list: |
| csrf.exempt(ex) |
| |
| utils.pessimistic_connection_handling(db.engine) |
| |
| cache = utils.setup_cache(app, conf.get('CACHE_CONFIG')) |
| tables_cache = utils.setup_cache(app, conf.get('TABLE_NAMES_CACHE_CONFIG')) |
| |
| migrate = Migrate(app, db, directory=APP_DIR + '/migrations') |
| |
| # Logging configuration |
| logging.basicConfig(format=app.config.get('LOG_FORMAT')) |
| logging.getLogger().setLevel(app.config.get('LOG_LEVEL')) |
| |
| if app.config.get('ENABLE_TIME_ROTATE'): |
| logging.getLogger().setLevel(app.config.get('TIME_ROTATE_LOG_LEVEL')) |
| handler = TimedRotatingFileHandler( |
| app.config.get('FILENAME'), |
| when=app.config.get('ROLLOVER'), |
| interval=app.config.get('INTERVAL'), |
| backupCount=app.config.get('BACKUP_COUNT')) |
| logging.getLogger().addHandler(handler) |
| |
| if app.config.get('ENABLE_CORS'): |
| from flask_cors import CORS |
| CORS(app, **app.config.get('CORS_OPTIONS')) |
| |
| if app.config.get('ENABLE_PROXY_FIX'): |
| app.wsgi_app = ProxyFix(app.wsgi_app) |
| |
| if app.config.get('ENABLE_CHUNK_ENCODING'): |
| |
| class ChunkedEncodingFix(object): |
| def __init__(self, app): |
| self.app = app |
| |
| def __call__(self, environ, start_response): |
| # Setting wsgi.input_terminated tells werkzeug.wsgi to ignore |
| # content-length and read the stream till the end. |
| if environ.get('HTTP_TRANSFER_ENCODING', '').lower() == u'chunked': |
| environ['wsgi.input_terminated'] = True |
| return self.app(environ, start_response) |
| |
| app.wsgi_app = ChunkedEncodingFix(app.wsgi_app) |
| |
| if app.config.get('UPLOAD_FOLDER'): |
| try: |
| os.makedirs(app.config.get('UPLOAD_FOLDER')) |
| except OSError: |
| pass |
| |
| for middleware in app.config.get('ADDITIONAL_MIDDLEWARE'): |
| app.wsgi_app = middleware(app.wsgi_app) |
| |
| |
| class MyIndexView(IndexView): |
| @expose('/') |
| def index(self): |
| return redirect('/superset/welcome') |
| |
| |
| appbuilder = AppBuilder( |
| app, |
| db.session, |
| base_template='superset/base.html', |
| indexview=MyIndexView, |
| security_manager_class=app.config.get('CUSTOM_SECURITY_MANAGER'), |
| update_perms=utils.get_update_perms_flag(), |
| ) |
| |
| sm = appbuilder.sm |
| |
| results_backend = app.config.get('RESULTS_BACKEND') |
| |
| # Registering sources |
| module_datasource_map = app.config.get('DEFAULT_MODULE_DS_MAP') |
| module_datasource_map.update(app.config.get('ADDITIONAL_MODULE_DS_MAP')) |
| ConnectorRegistry.register_sources(module_datasource_map) |
| |
| # Hook that provides administrators a handle on the Flask APP |
| # after initialization |
| flask_app_mutator = app.config.get('FLASK_APP_MUTATOR') |
| if flask_app_mutator: |
| flask_app_mutator(app) |
| |
| from superset import views # noqa |