diff --git a/.travis.yml b/.travis.yml index 000d2129dee..81b9edfb9af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -96,6 +96,9 @@ jobs: - language: python python: 3.6 env: TOXENV=pylint + - language: python + python: 3.6 + env: TOXENV=docs script: - tox diff --git a/docs/sqllab.rst b/docs/sqllab.rst index ab6dc47c11a..6060726543c 100644 --- a/docs/sqllab.rst +++ b/docs/sqllab.rst @@ -112,11 +112,11 @@ of queries before executing this. Currently, Presto is supported in SQL Lab. To enable query cost estimation, add the following keys to the "Extra" field in the database configuration: -.. code-block:: json +.. code-block:: text { "version": "0.319", - "cost_estimate_enabled": true, + "cost_estimate_enabled": true ... } @@ -164,7 +164,7 @@ and off at the database configuration level. Note that since ``CREATE TABLE..`` belongs to a SQL DDL category. Specifically on PostgreSQL, DDL is transactional, this means that to properly use this feature you have to set ``autocommit`` to true on your engine parameters: -.. code-block:: json +.. code-block:: text { ... diff --git a/superset/__init__.py b/superset/__init__.py index 1de8778ff94..feffead963e 100644 --- a/superset/__init__.py +++ b/superset/__init__.py @@ -26,6 +26,7 @@ from superset.extensions import ( db, event_logger, feature_flag_manager, + jinja_context_manager, manifest_processor, results_backend_manager, security_manager, @@ -44,6 +45,7 @@ conf = LocalProxy(lambda: current_app.config) get_feature_flags = feature_flag_manager.get_feature_flags get_css_manifest_files = manifest_processor.get_css_manifest_files is_feature_enabled = feature_flag_manager.is_feature_enabled +jinja_base_context = jinja_context_manager.base_context results_backend = LocalProxy(lambda: results_backend_manager.results_backend) results_backend_use_msgpack = LocalProxy( lambda: results_backend_manager.should_use_msgpack diff --git a/superset/app.py b/superset/app.py index 5eb246eb52e..abc6636810d 100644 --- a/superset/app.py +++ b/superset/app.py @@ -33,6 +33,7 @@ from superset.extensions import ( celery_app, db, feature_flag_manager, + jinja_context_manager, manifest_processor, migrate, results_backend_manager, @@ -159,6 +160,8 @@ class SupersetAppInitializer: self.configure_cache() + self.configure_jinja_context() + with self.flask_app.app_context(): self.init_app_in_ctx() @@ -200,6 +203,9 @@ class SupersetAppInitializer: appbuilder.update_perms = False appbuilder.init_app(self.flask_app, db.session) + def configure_jinja_context(self): + jinja_context_manager.init_app(self.flask_app) + def configure_middlewares(self): if self.config["ENABLE_CORS"]: from flask_cors import CORS diff --git a/superset/extensions.py b/superset/extensions.py index 2974739b71f..4cff3b485d4 100644 --- a/superset/extensions.py +++ b/superset/extensions.py @@ -16,8 +16,13 @@ # under the License. import json import os +import random +import time +import uuid +from datetime import datetime, timedelta import celery +from dateutil.relativedelta import relativedelta from flask_appbuilder import AppBuilder, SQLA from flask_migrate import Migrate from flask_talisman import Talisman @@ -27,9 +32,29 @@ from superset.utils.cache_manager import CacheManager from superset.utils.feature_flag_manager import FeatureFlagManager +class JinjaContextManager: + def __init__(self) -> None: + self._base_context = { + "datetime": datetime, + "random": random, + "relativedelta": relativedelta, + "time": time, + "timedelta": timedelta, + "uuid": uuid, + } + + def init_app(self, app): + self._base_context = self._base_context.update( + app.config["JINJA_CONTEXT_ADDONS"] + ) + + @property + def base_context(self): + return self._base_context + + class ResultsBackendManager: def __init__(self) -> None: - super().__init__() self._results_backend = None self._use_msgpack = False @@ -48,7 +73,6 @@ class ResultsBackendManager: class UIManifestProcessor: def __init__(self, app_dir: str) -> None: - super().__init__() self.app = None self.manifest: dict = {} self.manifest_file = f"{app_dir}/static/assets/dist/manifest.json" @@ -106,6 +130,7 @@ db = SQLA() _event_logger: dict = {} event_logger = LocalProxy(lambda: _event_logger.get("event_logger")) feature_flag_manager = FeatureFlagManager() +jinja_context_manager = JinjaContextManager() manifest_processor = UIManifestProcessor(APP_DIR) migrate = Migrate() results_backend_manager = ResultsBackendManager() diff --git a/superset/jinja_context.py b/superset/jinja_context.py index 4f3dd957337..da076d8e365 100644 --- a/superset/jinja_context.py +++ b/superset/jinja_context.py @@ -18,28 +18,12 @@ """Defines the templating context for SQL Lab""" import inspect import json -import random -import time -import uuid -from datetime import datetime, timedelta from typing import Any, List, Optional, Tuple -from dateutil.relativedelta import relativedelta from flask import g, request from jinja2.sandbox import SandboxedEnvironment -from superset import app - -config = app.config -BASE_CONTEXT = { - "datetime": datetime, - "random": random, - "relativedelta": relativedelta, - "time": time, - "timedelta": timedelta, - "uuid": uuid, -} -BASE_CONTEXT.update(config["JINJA_CONTEXT_ADDONS"]) +from superset import jinja_base_context def url_param(param: str, default: Optional[str] = None) -> Optional[Any]: @@ -209,7 +193,7 @@ class BaseTemplateProcessor: "form_data": {}, } self.context.update(kwargs) - self.context.update(BASE_CONTEXT) + self.context.update(jinja_base_context) if self.engine: self.context[self.engine] = self self.env = SandboxedEnvironment() diff --git a/tox.ini b/tox.ini index 5f2d017af1c..8da0d303061 100644 --- a/tox.ini +++ b/tox.ini @@ -148,6 +148,14 @@ deps = -rrequirements.txt -rrequirements-dev.txt +[testenv:docs] +commands = + sphinx-build -b html docs _build/html -W +deps = + -rrequirements.txt + -rrequirements-dev.txt + -rdocs/requirements.txt + [tox] envlist = fossa @@ -162,4 +170,5 @@ envlist = mypy pylint license-check + docs skipsdist = true