diff --git a/src/evidently/renderers/notebook_utils.py b/src/evidently/renderers/notebook_utils.py deleted file mode 100644 index b6e911abec..0000000000 --- a/src/evidently/renderers/notebook_utils.py +++ /dev/null @@ -1,8 +0,0 @@ -from evidently.utils.dashboard import inline_iframe_html_template - - -def determine_template(mode: str): - """ - :param str mode: Deprecated. Left it for BC - """ - return inline_iframe_html_template diff --git a/src/evidently/suite/base_suite.py b/src/evidently/suite/base_suite.py index 60972a67dd..2f64e379d7 100644 --- a/src/evidently/suite/base_suite.py +++ b/src/evidently/suite/base_suite.py @@ -35,7 +35,6 @@ from evidently.renderers.base_renderer import MetricRenderer from evidently.renderers.base_renderer import RenderersDefinitions from evidently.renderers.base_renderer import TestRenderer -from evidently.renderers.notebook_utils import determine_template from evidently.tests.base_test import Test from evidently.tests.base_test import TestParameters from evidently.tests.base_test import TestResult @@ -44,6 +43,8 @@ from evidently.utils.dashboard import SaveMode from evidently.utils.dashboard import SaveModeMap from evidently.utils.dashboard import TemplateParams +from evidently.utils.dashboard import file_html_template +from evidently.utils.dashboard import inline_iframe_html_template from evidently.utils.dashboard import save_data_file from evidently.utils.dashboard import save_lib_files from evidently.utils.data_preprocessing import DataDefinition @@ -124,7 +125,10 @@ def get_data_definition( if self.engine is None: raise ValueError("Cannot create data definition when engine is not set") self.data_definition = self.engine.get_data_definition( - current_data, reference_data, column_mapping, categorical_features_cardinality + current_data, + reference_data, + column_mapping, + categorical_features_cardinality, ) return self.data_definition @@ -207,7 +211,7 @@ def _repr_html_(self): dashboard_info=dashboard_info, additional_graphs=graphs, ) - return self._render(determine_template("auto"), template_params) + return self._render(inline_iframe_html_template, template_params) def show(self, mode="auto"): """ @@ -227,7 +231,7 @@ def show(self, mode="auto"): try: from IPython.display import HTML - return HTML(self._render(determine_template(mode), template_params)) + return HTML(self._render(inline_iframe_html_template, template_params)) except ImportError as err: raise Exception("Cannot import HTML from IPython.display, no way to show html") from err @@ -238,9 +242,13 @@ def get_html(self): dashboard_info=dashboard_info, additional_graphs=graphs, ) - return self._render(determine_template("inline"), template_params) + return self._render(file_html_template, template_params) - def save_html(self, filename: Union[str, IO], mode: Union[str, SaveMode] = SaveMode.SINGLE_FILE): + def save_html( + self, + filename: Union[str, IO], + mode: Union[str, SaveMode] = SaveMode.SINGLE_FILE, + ): dashboard_id, dashboard_info, graphs = self._build_dashboard_info() if isinstance(mode, str): _mode = SaveModeMap.get(mode) @@ -253,7 +261,7 @@ def save_html(self, filename: Union[str, IO], mode: Union[str, SaveMode] = SaveM dashboard_info=dashboard_info, additional_graphs=graphs, ) - render = self._render(determine_template("inline"), template_params) + render = self._render(file_html_template, template_params) if isinstance(filename, str): with open(filename, "w", encoding="utf-8") as out_file: out_file.write(render) @@ -275,7 +283,7 @@ def save_html(self, filename: Union[str, IO], mode: Union[str, SaveMode] = SaveM include_js_files=[lib_file, data_file], ) with open(filename, "w", encoding="utf-8") as out_file: - out_file.write(self._render(determine_template("inline"), template_params)) + out_file.write(self._render(file_html_template, template_params)) @abc.abstractmethod def as_dict( @@ -296,7 +304,14 @@ def _get_json_content( ) -> dict: """Return all data for json representation""" result = {"version": evidently.__version__} - result.update(self.as_dict(include_render=include_render, include=include, exclude=exclude, **kwargs)) + result.update( + self.as_dict( + include_render=include_render, + include=include, + exclude=exclude, + **kwargs, + ) + ) return result def json( @@ -307,7 +322,12 @@ def json( **kwargs, ) -> str: return json.dumps( - self._get_json_content(include_render=include_render, include=include, exclude=exclude, **kwargs), + self._get_json_content( + include_render=include_render, + include=include, + exclude=exclude, + **kwargs, + ), cls=NumpyEncoder, allow_nan=True, ) diff --git a/src/evidently/ui/base.py b/src/evidently/ui/base.py index 7ca4de56fe..60a628bbc9 100644 --- a/src/evidently/ui/base.py +++ b/src/evidently/ui/base.py @@ -23,7 +23,6 @@ from evidently._pydantic_compat import PrivateAttr from evidently._pydantic_compat import parse_obj_as from evidently.model.dashboard import DashboardInfo -from evidently.renderers.notebook_utils import determine_template from evidently.suite.base_suite import MetadataValueType from evidently.suite.base_suite import ReportBase from evidently.suite.base_suite import Snapshot @@ -50,6 +49,7 @@ from evidently.ui.type_aliases import UserID from evidently.utils import NumpyEncoder from evidently.utils.dashboard import TemplateParams +from evidently.utils.dashboard import inline_iframe_html_template class BlobMetadata(BaseModel): @@ -208,12 +208,16 @@ def get_snapshot_metadata(self, id: SnapshotID) -> SnapshotMetadata: return self.project_manager.get_snapshot_metadata(self._user_id, self.id, id) def build_dashboard_info( - self, timestamp_start: Optional[datetime.datetime], timestamp_end: Optional[datetime.datetime] + self, + timestamp_start: Optional[datetime.datetime], + timestamp_end: Optional[datetime.datetime], ) -> DashboardInfo: return self.dashboard.build(self.project_manager.data, self.id, timestamp_start, timestamp_end) def show_dashboard( - self, timestamp_start: Optional[datetime.datetime] = None, timestamp_end: Optional[datetime.datetime] = None + self, + timestamp_start: Optional[datetime.datetime] = None, + timestamp_end: Optional[datetime.datetime] = None, ): dashboard_info = self.build_dashboard_info(timestamp_start, timestamp_end) template_params = TemplateParams( @@ -225,7 +229,7 @@ def show_dashboard( try: from IPython.display import HTML - return HTML(determine_template("inline")(params=template_params)) + return HTML(inline_iframe_html_template(params=template_params)) except ImportError as err: raise Exception("Cannot import HTML from IPython.display, no way to show html") from err @@ -257,7 +261,11 @@ def list_projects(self, project_ids: Optional[Set[ProjectID]]) -> List[Project]: @abstractmethod def add_snapshot( - self, project_id: ProjectID, snapshot: Snapshot, blob: "BlobMetadata", out_dataset_id: Optional[str] = None + self, + project_id: ProjectID, + snapshot: Snapshot, + blob: "BlobMetadata", + out_dataset_id: Optional[str] = None, ): raise NotImplementedError @@ -271,7 +279,10 @@ def search_project(self, project_name: str, project_ids: Optional[Set[ProjectID] @abstractmethod def list_snapshots( - self, project_id: ProjectID, include_reports: bool = True, include_test_suites: bool = True + self, + project_id: ProjectID, + include_reports: bool = True, + include_test_suites: bool = True, ) -> List[SnapshotMetadata]: raise NotImplementedError @@ -485,7 +496,10 @@ class AuthManager(ABC): allow_default_user: bool = True def refresh_default_roles(self): - for (default_role, entity_type), permissions in DEFAULT_ROLE_PERMISSIONS.items(): + for ( + default_role, + entity_type, + ), permissions in DEFAULT_ROLE_PERMISSIONS.items(): role = self.get_default_role(default_role, entity_type) if role.permissions != permissions: role.permissions = permissions @@ -503,7 +517,11 @@ def get_available_project_ids( @abstractmethod def check_entity_permission( - self, user_id: UserID, entity_type: EntityType, entity_id: EntityID, permission: Permission + self, + user_id: UserID, + entity_type: EntityType, + entity_id: EntityID, + permission: Permission, ) -> bool: raise NotImplementedError @@ -607,7 +625,12 @@ def _revoke_entity_role(self, entity_type: EntityType, entity_id: EntityID, user raise NotImplementedError def revoke_entity_role( - self, manager: UserID, entity_type: EntityType, entity_id: EntityID, user_id: UserID, role: Role + self, + manager: UserID, + entity_type: EntityType, + entity_id: EntityID, + user_id: UserID, + role: Role, ): if not self.check_entity_permission(manager, entity_type, entity_id, Permission.REVOKE_ROLE): raise NotEnoughPermissions() @@ -663,7 +686,13 @@ def list_roles(self, entity_type: Optional[EntityType]) -> List[Role]: class ProjectManager: - def __init__(self, metadata: MetadataStorage, blob: BlobStorage, data: DataStorage, auth: AuthManager): + def __init__( + self, + metadata: MetadataStorage, + blob: BlobStorage, + data: DataStorage, + auth: AuthManager, + ): self.metadata: MetadataStorage = metadata self.blob: BlobStorage = blob self.data: DataStorage = data @@ -680,7 +709,10 @@ def create_project( project = self.add_project( Project( - name=name, description=description, dashboard=DashboardConfig(name=name, panels=[]), team_id=team_id + name=name, + description=description, + dashboard=DashboardConfig(name=name, panels=[]), + team_id=team_id, ), user_id, team_id, @@ -753,14 +785,22 @@ def delete_snapshot(self, user_id: UserID, project_id: ProjectID, snapshot_id: S self.metadata.delete_snapshot(project_id, snapshot_id) def search_project( - self, user_id: UserID, project_name: str, team_id: Optional[TeamID], org_id: Optional[OrgID] + self, + user_id: UserID, + project_name: str, + team_id: Optional[TeamID], + org_id: Optional[OrgID], ) -> List[Project]: user = self.auth.get_or_default_user(user_id) project_ids = self.auth.get_available_project_ids(user.id, team_id, org_id) return [p.bind(self, user.id) for p in self.metadata.search_project(project_name, project_ids)] def list_snapshots( - self, user_id: UserID, project_id: ProjectID, include_reports: bool = True, include_test_suites: bool = True + self, + user_id: UserID, + project_id: ProjectID, + include_reports: bool = True, + include_test_suites: bool = True, ) -> List[SnapshotMetadata]: if not self.auth.check_entity_permission(user_id, EntityType.Project, project_id, Permission.PROJECT_READ): raise NotEnoughPermissions() @@ -770,7 +810,10 @@ def list_snapshots( return snapshots def load_snapshot( - self, user_id: UserID, project_id: ProjectID, snapshot: Union[SnapshotID, SnapshotMetadata] + self, + user_id: UserID, + project_id: ProjectID, + snapshot: Union[SnapshotID, SnapshotMetadata], ) -> Snapshot: if isinstance(snapshot, SnapshotID): snapshot = self.get_snapshot_metadata(user_id, project_id, snapshot) diff --git a/src/evidently/utils/dashboard.py b/src/evidently/utils/dashboard.py index 79e4d6bbae..12b2113dcf 100644 --- a/src/evidently/utils/dashboard.py +++ b/src/evidently/utils/dashboard.py @@ -60,7 +60,13 @@ def save_lib_files(filename: str, mode: SaveMode): return font_file, lib_file -def save_data_file(filename: str, mode: SaveMode, dashboard_id, dashboard_info: DashboardInfo, additional_graphs: Dict): +def save_data_file( + filename: str, + mode: SaveMode, + dashboard_id, + dashboard_info: DashboardInfo, + additional_graphs: Dict, +): if mode == SaveMode.SINGLE_FILE: return None parent_dir = os.path.dirname(filename) @@ -84,54 +90,9 @@ def dashboard_info_to_json(dashboard_info: DashboardInfo): return json.dumps(asdict_result, cls=NumpyEncoder) -def inline_template(params: TemplateParams): - return f""" - - - - -
Loading...
- -""" - - def file_html_template(params: TemplateParams): lib_block = f"""""" if params.embed_lib else "" + data_block = ( f"""' for file in params.include_js_files]) + + style = f""" + + """ + return f""" - - - - -{data_block} - - -
-

Loading...

-
- -{lib_block} -{js_files_block} - - + + + + + + {style} + {data_block} + + +
+

Loading...

+
+ + {lib_block} + {js_files_block} + + + + """