Skip to content

Commit

Permalink
Support setting widget title and description (#166)
Browse files Browse the repository at this point in the history
Resolves #165
Stacked on #161
  • Loading branch information
JCZuurmond committed Jun 19, 2024
1 parent 95f7297 commit d7ae1fe
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 7 deletions.
15 changes: 13 additions & 2 deletions src/databricks/labs/lsql/dashboards.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
TableEncodingMap,
TableV2Spec,
Widget,
WidgetFrameSpec,
WidgetSpec,
)

Expand Down Expand Up @@ -120,6 +121,8 @@ def _get_arguments_parser() -> ArgumentParser:
parser.add_argument("-o", "--order", type=int)
parser.add_argument("-w", "--width", type=int)
parser.add_argument("-h", "--height", type=int)
parser.add_argument("-t", "--title", type=str)
parser.add_argument("-d", "--description", type=str)
return parser

def _parse_header(self, header: str) -> dict[str, str]:
Expand Down Expand Up @@ -181,12 +184,16 @@ def __init__(
width: int = 0,
height: int = 0,
_id: str = "",
title: str = "",
description: str = "",
):
self._path = path
self.order = order
self.width = width
self.height = height
self.id = _id or path.stem
self.title = title
self.description = description

size = self._size
self.width = self.width or size[0]
Expand Down Expand Up @@ -236,9 +243,13 @@ def from_dict(cls, *, path: str | Path, **optionals) -> "WidgetMetadata":
return cls(path, **optionals)

def as_dict(self) -> dict[str, str]:
exclude_attributes = {
"handler", # Handler is inferred from file extension
"path", # Path is set explicitly below
}
body = {"path": self._path.as_posix()}
for attribute in "order", "width", "height", "id":
if attribute in body:
for attribute in dir(self):
if attribute.startswith("_") or callable(getattr(self, attribute)) or attribute in exclude_attributes:
continue
value = getattr(self, attribute)
if value is not None:
Expand Down
14 changes: 14 additions & 0 deletions tests/integration/test_dashboards.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,17 @@ def test_dashboards_deploys_dashboard_with_markdown_header(ws, make_dashboard, t
sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id)

assert ws.lakeview.get(sdk_dashboard.dashboard_id)


def test_dashboards_deploys_dashboard_with_widget_title_and_description(ws, make_dashboard, tmp_path):
sdk_dashboard = make_dashboard()

description = "-- --title 'Counting' --description 'The answer to life'\nSELECT 42"
(tmp_path / "counter.sql").write_text(description)

dashboards = Dashboards(ws)
lakeview_dashboard = dashboards.create_dashboard(tmp_path)

sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id)

assert ws.lakeview.get(sdk_dashboard.dashboard_id)
53 changes: 48 additions & 5 deletions tests/unit/test_dashboards.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ def test_query_handler_ignores_non_header_comment(tmp_path, query):
assert all(value is None for value in header.values())


@pytest.mark.parametrize("attribute", ["id", "order", "height", "width"])
@pytest.mark.parametrize("attribute", ["id", "order", "height", "width", "title", "description"])
def test_query_handler_parses_attribute_from_header(tmp_path, attribute):
path = tmp_path / "query.sql"
path.write_text(f"-- --{attribute} 10\nSELECT 1")
Expand Down Expand Up @@ -260,20 +260,35 @@ def test_widget_metadata_replaces_width_and_height(tmp_path):
assert updated_metadata.height == 10


@pytest.mark.parametrize("attribute", ["id", "order", "width", "height"])
@pytest.mark.parametrize("attribute", ["id", "order", "width", "height", "title", "description"])
def test_widget_metadata_replaces_attribute(tmp_path, attribute: str):
path = tmp_path / "test.sql"
path.write_text("SELECT 1")
widget_metadata = WidgetMetadata(path, 1, 1, 1)
widget_metadata = WidgetMetadata(path, 1, 1, 1, "1", "1", "1")
updated_metadata = widget_metadata.from_dict(**{"path": path, attribute: "10"})
assert str(getattr(updated_metadata, attribute)) == "10"


def test_widget_metadata_as_dict(tmp_path):
path = tmp_path / "test.sql"
path.write_text("SELECT 1")
raw = {"path": path.as_posix(), "id": "test", "order": "10", "width": "10", "height": "10"}
widget_metadata = WidgetMetadata(path, 10, 10, 10)
raw = {
"path": path.as_posix(),
"id": "test",
"order": "-1",
"width": "3",
"height": "6",
"title": "Test widget",
"description": "Longer explanation",
}
widget_metadata = WidgetMetadata(
path,
order=-1,
width=3,
height=6,
title="Test widget",
description="Longer explanation",
)
assert widget_metadata.as_dict() == raw


Expand Down Expand Up @@ -695,6 +710,34 @@ def test_dashboard_creates_dashboard_with_custom_sized_widget(tmp_path, header):
ws.assert_not_called()


def test_dashboard_creates_dashboard_with_title(tmp_path):
ws = create_autospec(WorkspaceClient)

query = "-- --title 'Count me in'\nSELECT 2918"
(tmp_path / "counter.sql").write_text(query)

lakeview_dashboard = Dashboards(ws).create_dashboard(tmp_path)

frame = lakeview_dashboard.pages[0].layout[0].widget.spec.frame
assert frame.title == "Count me in"
assert frame.show_title
ws.assert_not_called()


def test_dashboard_creates_dashboard_with_description(tmp_path):
ws = create_autospec(WorkspaceClient)

query = "-- --description 'Only when it counts'\nSELECT 2918"
(tmp_path / "counter.sql").write_text(query)

lakeview_dashboard = Dashboards(ws).create_dashboard(tmp_path)

frame = lakeview_dashboard.pages[0].layout[0].widget.spec.frame
assert frame.description == "Only when it counts"
assert frame.show_description
ws.assert_not_called()


def test_dashboard_handles_incorrect_query_header(tmp_path, caplog):
ws = create_autospec(WorkspaceClient)

Expand Down

0 comments on commit d7ae1fe

Please sign in to comment.