mirror of
https://github.com/apache/superset.git
synced 2026-04-29 21:14:22 +00:00
Compare commits
1 Commits
semantic-l
...
sl-1-exten
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91d018c52d |
@@ -64,9 +64,11 @@ x-superset-volumes: &superset-volumes
|
||||
# /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
||||
- ./docker:/app/docker
|
||||
- ./superset:/app/superset
|
||||
- ./superset-core:/app/superset-core
|
||||
- ./superset-frontend:/app/superset-frontend
|
||||
- superset_home_light:/app/superset_home
|
||||
- ./tests:/app/tests
|
||||
- ./extensions:/app/extensions
|
||||
x-common-build: &common-build
|
||||
context: .
|
||||
target: ${SUPERSET_BUILD_TARGET:-dev} # can use `dev` (default) or `lean`
|
||||
|
||||
@@ -105,7 +105,15 @@ class CeleryConfig:
|
||||
|
||||
CELERY_CONFIG = CeleryConfig
|
||||
|
||||
FEATURE_FLAGS = {"ALERT_REPORTS": True}
|
||||
# Extensions configuration
|
||||
# For local development, point to the extensions directory
|
||||
# Note: If running in Docker, this path needs to be accessible from inside the container
|
||||
EXTENSIONS_PATH = os.getenv("EXTENSIONS_PATH", "/app/extensions")
|
||||
|
||||
FEATURE_FLAGS = {
|
||||
"ALERT_REPORTS": True,
|
||||
"ENABLE_EXTENSIONS": True,
|
||||
}
|
||||
ALERT_REPORTS_NOTIFICATION_DRY_RUN = True
|
||||
WEBDRIVER_BASEURL = f"http://superset_app{os.environ.get('SUPERSET_APP_ROOT', '/')}/" # When using docker compose baseurl should be http://superset_nginx{ENV{BASEPATH}}/ # noqa: E501
|
||||
# The base URL for the email report hyperlinks.
|
||||
|
||||
@@ -223,6 +223,34 @@ def build_extension_data(extension: LoadedExtension) -> dict[str, Any]:
|
||||
return extension_data
|
||||
|
||||
|
||||
def load_extension_backend(extension: LoadedExtension) -> None:
|
||||
"""
|
||||
Load an extension's backend code by installing modules and importing entry points.
|
||||
|
||||
Entry points are module names that get imported. The modules are expected to
|
||||
self-register any capabilities (e.g., semantic layers) when imported.
|
||||
"""
|
||||
# Install backend modules in-memory if present
|
||||
if extension.backend:
|
||||
install_in_memory_importer(
|
||||
extension.backend,
|
||||
source_base_path=extension.source_base_path,
|
||||
)
|
||||
|
||||
# Import entry point modules - they self-register on import
|
||||
manifest = extension.manifest
|
||||
if manifest.backend:
|
||||
for module_name in manifest.backend.entryPoints:
|
||||
try:
|
||||
eager_import(module_name)
|
||||
except Exception:
|
||||
logger.exception(
|
||||
"Failed to load entry point '%s' from extension %s",
|
||||
module_name,
|
||||
extension.name,
|
||||
)
|
||||
|
||||
|
||||
def get_extensions() -> dict[str, LoadedExtension]:
|
||||
extensions: dict[str, LoadedExtension] = {}
|
||||
|
||||
@@ -234,6 +262,7 @@ def get_extensions() -> dict[str, LoadedExtension]:
|
||||
extension = get_loaded_extension(files, source_base_path=abs_dist_path)
|
||||
extension_id = extension.manifest.id
|
||||
extensions[extension_id] = extension
|
||||
load_extension_backend(extension)
|
||||
logger.info(
|
||||
"Loading extension %s (ID: %s) from local filesystem",
|
||||
extension.name,
|
||||
@@ -248,6 +277,7 @@ def get_extensions() -> dict[str, LoadedExtension]:
|
||||
extension_id = extension.manifest.id
|
||||
if extension_id not in extensions: # Don't override LOCAL_EXTENSIONS
|
||||
extensions[extension_id] = extension
|
||||
load_extension_backend(extension)
|
||||
logger.info(
|
||||
"Loading extension %s (ID: %s) from discovery path",
|
||||
extension.name,
|
||||
|
||||
@@ -546,37 +546,18 @@ class SupersetAppInitializer: # pylint: disable=too-many-public-methods
|
||||
self.init_extensions()
|
||||
|
||||
def init_extensions(self) -> None:
|
||||
from superset.extensions.utils import (
|
||||
eager_import,
|
||||
get_extensions,
|
||||
install_in_memory_importer,
|
||||
)
|
||||
from superset.extensions.utils import get_extensions
|
||||
|
||||
try:
|
||||
extensions = get_extensions()
|
||||
# get_extensions() discovers and loads all extensions,
|
||||
# including installing in-memory importers and registering entry points
|
||||
get_extensions()
|
||||
except Exception: # pylint: disable=broad-except # noqa: S110
|
||||
# If the db hasn't been initialized yet, an exception will be raised.
|
||||
# It's fine to ignore this, as in this case there are no extensions
|
||||
# present yet.
|
||||
return
|
||||
|
||||
for extension in extensions.values():
|
||||
if backend_files := extension.backend:
|
||||
install_in_memory_importer(
|
||||
backend_files,
|
||||
source_base_path=extension.source_base_path,
|
||||
)
|
||||
|
||||
backend = extension.manifest.backend
|
||||
|
||||
if backend and (entrypoints := backend.entryPoints):
|
||||
for entrypoint in entrypoints:
|
||||
try:
|
||||
eager_import(entrypoint)
|
||||
except Exception as ex: # pylint: disable=broad-except # noqa: S110
|
||||
# Surface exceptions during initialization of extensions
|
||||
print(ex)
|
||||
|
||||
def init_app_in_ctx(self) -> None:
|
||||
"""
|
||||
Runs init logic in the context of the app
|
||||
|
||||
Reference in New Issue
Block a user