Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tags): Added self.contents in database, datasets and query for import #13

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/pythonpath_dev/superset_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class CeleryConfig:

CELERY_CONFIG = CeleryConfig

FEATURE_FLAGS = {"ALERT_REPORTS": True}
FEATURE_FLAGS = {"ALERT_REPORTS": True}
ALERT_REPORTS_NOTIFICATION_DRY_RUN = True
WEBDRIVER_BASEURL = "http://superset:8088/" # When using docker compose baseurl should be http://superset_app:8088/
# The base URL for the email report hyperlinks.
Expand Down
1 change: 1 addition & 0 deletions superset/charts/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -1552,6 +1552,7 @@ class ImportV1ChartSchema(Schema):
external_url = fields.String(allow_none=True)
tags = fields.List(fields.String(), allow_none=True)


class ChartCacheWarmUpRequestSchema(Schema):
chart_id = fields.Integer(
required=True,
Expand Down
29 changes: 15 additions & 14 deletions superset/commands/chart/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# under the License.
# isort:skip_file

import inspect
import logging
from collections.abc import Iterator
from typing import Callable
Expand Down Expand Up @@ -76,22 +77,15 @@ def _file_content(model: Slice) -> str:

# Fetch tags from the database if TAGGING_SYSTEM is enabled
if feature_flag_manager.is_feature_enabled("TAGGING_SYSTEM"):
tags = (
model.tags if hasattr(model, "tags") else []
)
tags = model.tags if hasattr(model, "tags") else []
payload["tags"] = [tag.name for tag in tags if tag.type == TagType.custom]
file_content = yaml.safe_dump(payload, sort_keys=False)
return file_content

# Add a parameter for should_export_tags in the constructor
def __init__(self, chart_ids, should_export_tags=True, export_related=True):
super().__init__(chart_ids)
self.should_export_tags = should_export_tags
self.export_related = export_related

# Change to an instance method
@staticmethod
def _export(
self, model: Slice, export_related: bool = True
model: Slice, export_related: bool = True
) -> Iterator[tuple[str, Callable[[], str]]]:
yield (
ExportChartsCommand._file_name(model),
Expand All @@ -101,7 +95,14 @@ def _export(
if model.table and export_related:
yield from ExportDatasetsCommand([model.table.id]).run()


if export_related and self.should_export_tags and feature_flag_manager.is_feature_enabled("TAGGING_SYSTEM"):
chart_id = model.id
yield from ExportTagsCommand._export(chart_ids=[chart_id])
# Check if the calling class is ExportDashboardCommands
if export_related and feature_flag_manager.is_feature_enabled("TAGGING_SYSTEM"):
stack = inspect.stack()
for frame_info in stack:
environ = frame_info.frame.f_locals.get("environ")
if environ:
path_info = environ.get("PATH_INFO")
if path_info:
# Check if PATH_INFO contains the substring 'dashboard/export' else export tags of Charts
if "dashboard/export" not in path_info:
yield from ExportTagsCommand.export(chart_ids=[model.id])
22 changes: 16 additions & 6 deletions superset/commands/chart/importers/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,26 @@
# specific language governing permissions and limitations
# under the License.

from typing import Any
from typing import Any, Optional

from marshmallow import Schema
from sqlalchemy.orm import Session # noqa: F401
from superset import db

from superset import db
from superset.charts.schemas import ImportV1ChartSchema
from superset.commands.chart.exceptions import ChartImportError
from superset.commands.chart.importers.v1.utils import import_chart
from superset.commands.database.importers.v1.utils import import_database
from superset.commands.dataset.importers.v1.utils import import_dataset
from superset.commands.importers.v1 import ImportModelsCommand
from superset.commands.importers.v1.utils import import_tag
from superset.connectors.sqla.models import SqlaTable
from superset.daos.chart import ChartDAO
from superset.databases.schemas import ImportV1DatabaseSchema
from superset.datasets.schemas import ImportV1DatasetSchema
from superset.commands.importers.v1.utils import import_tag
from superset.extensions import feature_flag_manager


class ImportChartsCommand(ImportModelsCommand):
"""Import charts"""

Expand All @@ -48,7 +49,14 @@ class ImportChartsCommand(ImportModelsCommand):
import_error = ChartImportError

@staticmethod
def _import(configs: dict[str, Any], overwrite: bool = False, contents: dict[str, Any] = None) -> None:
def _import(
configs: dict[str, Any],
overwrite: bool = False,
contents: Optional[dict[str, Any]] = None,
) -> None:
if contents is None:
contents = {}

# discover datasets associated with charts
dataset_uuids: set[str] = set()
for file_name, config in configs.items():
Expand Down Expand Up @@ -101,9 +109,11 @@ def _import(configs: dict[str, Any], overwrite: bool = False, contents: dict[str
config["query_context"] = None

chart = import_chart(config, overwrite=overwrite)

# Handle tags using import_tag function
if feature_flag_manager.is_feature_enabled("TAGGING_SYSTEM"):
if "tags" in config:
new_tag_names = config["tags"]
import_tag(new_tag_names, contents, chart.id, "chart", db.session)
import_tag(
new_tag_names, contents, chart.id, "chart", db.session
)
12 changes: 6 additions & 6 deletions superset/commands/dashboard/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,7 @@ def _file_content(model: Dashboard) -> str:

# Check if the TAGGING_SYSTEM feature is enabled
if feature_flag_manager.is_feature_enabled("TAGGING_SYSTEM"):
tags = (
model.tags if hasattr(model, "tags") else []
)
tags = model.tags if hasattr(model, "tags") else []
payload["tags"] = [tag.name for tag in tags if tag.type == TagType.custom]

file_content = yaml.safe_dump(payload, sort_keys=False)
Expand All @@ -184,10 +182,12 @@ def _export(
if export_related:
chart_ids = [chart.id for chart in model.slices]
dashboard_ids = model.id
yield from ExportChartsCommand(chart_ids, should_export_tags=False).run()
yield from ExportChartsCommand(chart_ids).run()
if feature_flag_manager.is_feature_enabled("TAGGING_SYSTEM"):
yield from ExportTagsCommand._export(dashboard_ids=dashboard_ids, chart_ids=chart_ids)

yield from ExportTagsCommand.export(
dashboard_ids=dashboard_ids, chart_ids=chart_ids
)

payload = model.export_to_dict(
recursive=False,
include_parent_ref=False,
Expand Down
31 changes: 23 additions & 8 deletions superset/commands/dashboard/importers/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.

from typing import Any
from typing import Any, Optional

from marshmallow import Schema
from sqlalchemy.orm import Session # noqa: F401
Expand All @@ -34,14 +34,15 @@
from superset.commands.database.importers.v1.utils import import_database
from superset.commands.dataset.importers.v1.utils import import_dataset
from superset.commands.importers.v1 import ImportModelsCommand
from superset.commands.importers.v1.utils import import_tag
from superset.daos.dashboard import DashboardDAO
from superset.dashboards.schemas import ImportV1DashboardSchema
from superset.databases.schemas import ImportV1DatabaseSchema
from superset.datasets.schemas import ImportV1DatasetSchema
from superset.extensions import feature_flag_manager
from superset.migrations.shared.native_filters import migrate_dashboard
from superset.models.dashboard import Dashboard, dashboard_slices
from superset.commands.importers.v1.utils import import_tag
from superset.extensions import feature_flag_manager


class ImportDashboardsCommand(ImportModelsCommand):
"""Import dashboards"""
Expand All @@ -58,9 +59,15 @@ class ImportDashboardsCommand(ImportModelsCommand):
import_error = DashboardImportError

# TODO (betodealmeida): refactor to use code from other commands
# pylint: disable=too-many-branches, too-many-locals
# pylint: disable=too-many-branches, too-many-locals, too-many-statements
@staticmethod
def _import(configs: dict[str, Any], overwrite: bool = False, contents: dict[str, Any] = None) -> None:
def _import(
configs: dict[str, Any],
overwrite: bool = False,
contents: Optional[dict[str, Any]] = None,
) -> None:
if contents is None:
contents = {}
# discover charts and datasets associated with dashboards
chart_uuids: set[str] = set()
dataset_uuids: set[str] = set()
Expand Down Expand Up @@ -123,12 +130,14 @@ def _import(configs: dict[str, Any], overwrite: bool = False, contents: dict[str
chart = import_chart(config, overwrite=False)
charts.append(chart)
chart_ids[str(chart.uuid)] = chart.id

# Handle tags using import_tag function
if feature_flag_manager.is_feature_enabled("TAGGING_SYSTEM"):
if "tags" in config:
new_tag_names = config["tags"]
import_tag(new_tag_names, contents, chart.id, "chart", db.session)
import_tag(
new_tag_names, contents, chart.id, "chart", db.session
)

# store the existing relationship between dashboards and charts
existing_relationships = db.session.execute(
Expand All @@ -154,7 +163,13 @@ def _import(configs: dict[str, Any], overwrite: bool = False, contents: dict[str
if feature_flag_manager.is_feature_enabled("TAGGING_SYSTEM"):
if "tags" in config:
new_tag_names = config["tags"]
import_tag(new_tag_names, contents, dashboard.id, "dashboard", db.session)
import_tag(
new_tag_names,
contents,
dashboard.id,
"dashboard",
db.session,
)

# set ref in the dashboard_slices table
values = [
Expand Down
8 changes: 6 additions & 2 deletions superset/commands/database/importers/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.

from typing import Any
from typing import Any, Optional

from marshmallow import Schema
from sqlalchemy.orm import Session # noqa: F401
Expand All @@ -42,7 +42,11 @@ class ImportDatabasesCommand(ImportModelsCommand):
import_error = DatabaseImportError

@staticmethod
def _import(configs: dict[str, Any], overwrite: bool = False) -> None:
def _import(
configs: dict[str, Any],
overwrite: bool = False,
contents: Optional[dict[str, Any]] = None,
) -> None:
# first import databases
database_ids: dict[str, int] = {}
for file_name, config in configs.items():
Expand Down
10 changes: 8 additions & 2 deletions superset/commands/dataset/importers/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.

from typing import Any
from typing import Any, Optional

from marshmallow import Schema
from sqlalchemy.orm import Session # noqa: F401
Expand All @@ -42,7 +42,13 @@ class ImportDatasetsCommand(ImportModelsCommand):
import_error = DatasetImportError

@staticmethod
def _import(configs: dict[str, Any], overwrite: bool = False) -> None:
def _import(
configs: dict[str, Any],
overwrite: bool = False,
contents: Optional[dict[str, Any]] = None,
) -> None:
if contents is None:
contents = {}
# discover databases associated with datasets
database_uuids: set[str] = set()
for file_name, config in configs.items():
Expand Down
13 changes: 7 additions & 6 deletions superset/commands/export/assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@

from superset.commands.base import BaseCommand
from superset.commands.chart.export import ExportChartsCommand
from superset.commands.tag.export import ExportTagsCommand
from superset.commands.dashboard.export import ExportDashboardsCommand
from superset.commands.database.export import ExportDatabasesCommand
from superset.commands.dataset.export import ExportDatasetsCommand
from superset.commands.query.export import ExportSavedQueriesCommand
from superset.commands.tag.export import ExportTagsCommand
from superset.utils.dict_import_export import EXPORT_VERSION

METADATA_FILE_NAME = "metadata.yaml"
Expand Down Expand Up @@ -56,11 +56,12 @@ def run(self) -> Iterator[tuple[str, Callable[[], str]]]:
ExportSavedQueriesCommand,
]
for command in commands:
ids = [model.id for model in command.dao.find_all()]
for file_name, file_content in command(ids, export_related=False).run():
if file_name not in seen:
yield file_name, file_content
seen.add(file_name)
if hasattr(command, "dao"):
ids = [model.id for model in command.dao.find_all()]
for file_name, file_content in command(ids, export_related=False).run():
if file_name not in seen:
yield file_name, file_content
seen.add(file_name)

def validate(self) -> None:
pass
8 changes: 7 additions & 1 deletion superset/commands/importers/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,13 @@ def __init__(self, contents: dict[str, str], *args: Any, **kwargs: Any):
self._configs: dict[str, Any] = {}

@staticmethod
def _import(configs: dict[str, Any], overwrite: bool = False) -> None:
def _import(
configs: dict[str, Any],
overwrite: bool = False,
contents: Optional[
dict[str, Any]
] = None, # Use dict[str, str] to match the parent class signature
) -> None:
raise NotImplementedError("Subclasses MUST implement _import")

@classmethod
Expand Down
5 changes: 3 additions & 2 deletions superset/commands/importers/v1/examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from typing import Any
from typing import Any, Optional

from marshmallow import Schema
from sqlalchemy.exc import MultipleResultsFound
Expand Down Expand Up @@ -90,6 +90,7 @@ def _get_uuids(cls) -> set[str]:
def _import( # pylint: disable=too-many-locals, too-many-branches
configs: dict[str, Any],
overwrite: bool = False,
contents: Optional[dict[str, Any]] = None,
force_data: bool = False,
) -> None:
# import databases
Expand Down Expand Up @@ -129,7 +130,7 @@ def _import( # pylint: disable=too-many-locals, too-many-branches
dataset = import_dataset(
config,
overwrite=overwrite,
force_data=force_data,
force_data=bool(force_data),
ignore_permissions=True,
)
except MultipleResultsFound:
Expand Down
Loading
Loading