databao/visualizers/vega_vis_tool.py (51 lines of code) (raw):

import json import textwrap import uuid from typing import Any import pandas as pd from edaplot.data_utils import spec_add_data, spec_remove_data # Special URL for portus that allows us to deliver fixes without requiring version updates to portus. # All updates at this link will maintain backward compatibility with the existing usage code. # If there are changes in the usage API, the version will be incremented (e.g., v1, v2, etc.). # Versioned links are also available, but using "latest" is suggested _DATA_TOOLS_URL = "https://resources.jetbrains.com/storage/data-tools/portus" _VEGA_LITE_SCHEMA_URL = "https://vega.github.io/schema/vega-lite/v5.json" class VegaVisTool: def __init__( self, spec: dict[str, Any], df: pd.DataFrame, *, version: str = "v0/latest", debug: bool = True ) -> None: self._spec = spec self._df = df self._version = version # Using the debug flag will print error information in some cases. # You can use the developer tools available in VS Code (Help > Toggle Developer Tools). self._debug = debug def _repr_html_(self) -> str: return self.get_html() def get_html(self) -> str: spec = self.prepare_spec(self._spec, self._df) # Convert to JSON to correctly deal with JS types (e.g., "None" to "null") spec_json = json.dumps(spec) debug = json.dumps(self._debug) div_id = uuid.uuid4() # Usage based on https://github.com/JetBrains/data-tools/tree/main/embed return textwrap.dedent(f''' <div id="{div_id}"> <script type="application/javascript"> (function() {{ const script = document.createElement("script"); script.onload = function() {{ const container = document.getElementById("{div_id}"); if (container && renderVisualizationTool) {{ renderVisualizationTool({spec_json}, container, {debug}) }} }}; script.src = "{_DATA_TOOLS_URL}/{self._version}/vistool.js"; document.getElementById("{div_id}").appendChild(script); }})(); </script> </div> ''') def display(self) -> None: from IPython.display import display display(self) # type: ignore[no-untyped-call] @classmethod def prepare_spec(cls, spec: dict[str, Any], df: pd.DataFrame) -> dict[str, Any]: spec = spec.copy() if "$schema" not in spec: spec["$schema"] = _VEGA_LITE_SCHEMA_URL # Remove fields not supported by data-tools that cause no html to be rendered spec_remove_data(spec) # The data must be included in the spec directly spec = spec_add_data(spec, df) return spec