From 59cb87db36648b79691ac9b2d7640e3c4a0e234f Mon Sep 17 00:00:00 2001 From: Mike Gouline <1960272+gouline@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:49:20 +1100 Subject: [PATCH] Meta description (#292) * feat: allow column description to be overwritten (#291) * feat: allow column description to be overwritten * feat: Consider Model description as well * chore: Update tests * chore: Column test * fix: fmt * fix: test v2 manifest instead of v12 * Apply suggestions from code review --------- Co-authored-by: Mike Gouline <1960272+gouline@users.noreply.github.com> * fix type issue --------- Co-authored-by: Felipe Guilherme Sabino <982190+sabino@users.noreply.github.com> --- dbtmetabase/manifest.py | 38 +++++++++++++++++++++------------ tests/fixtures/manifest-v2.json | 8 +++++-- tests/test_manifest.py | 4 ++-- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/dbtmetabase/manifest.py b/dbtmetabase/manifest.py index f4908491..40350d24 100644 --- a/dbtmetabase/manifest.py +++ b/dbtmetabase/manifest.py @@ -7,6 +7,7 @@ from enum import Enum from pathlib import Path from typing import ( + Any, Iterable, Mapping, MutableMapping, @@ -26,6 +27,7 @@ _COMMON_META_FIELDS = [ "display_name", "visibility_type", + "description", ] # Must be covered by Column attributes _COLUMN_META_FIELDS = _COMMON_META_FIELDS + [ @@ -110,6 +112,13 @@ def _read_model( for column in manifest_model.get("columns", {}).values() ] + meta = self._scan_fields( + manifest_model.get("meta", {}), + fields=_MODEL_META_FIELDS, + ns=_META_NS, + ) + description = meta.pop("description", manifest_model.get("description")) + return Model( database=database, schema=schema, @@ -118,16 +127,12 @@ def _read_model( alias=manifest_model.get( "alias", manifest_model.get("identifier", manifest_model["name"]) ), - description=manifest_model.get("description"), + description=description, columns=columns, unique_id=unique_id, source=source, tags=manifest_model.get("tags", []), - **self._scan_fields( - manifest_model.get("meta", {}), - fields=_MODEL_META_FIELDS, - ns=_META_NS, - ), + **meta, ) def _read_column( @@ -136,14 +141,17 @@ def _read_column( schema: str, relationship: Optional[Mapping], ) -> Column: + meta = self._scan_fields( + manifest_column.get("meta", {}), + fields=_COLUMN_META_FIELDS, + ns=_META_NS, + ) + description = meta.pop("description", manifest_column.get("description")) + column = Column( name=manifest_column.get("name", ""), - description=manifest_column.get("description"), - **self._scan_fields( - manifest_column.get("meta", {}), - fields=_COLUMN_META_FIELDS, - ns=_META_NS, - ), + description=description, + **meta, ) self._set_column_relationship( @@ -320,12 +328,14 @@ def _set_column_relationship( ) @staticmethod - def _scan_fields(t: Mapping, fields: Iterable[str], ns: str) -> Mapping: + def _scan_fields( + t: Mapping, fields: Iterable[str], ns: str + ) -> MutableMapping[str, Any]: """Reads meta fields from a schem object. Args: t (Mapping): Target to scan for fields. - fields (List): List of fields to accept. + fields (Iterable): List of fields to accept. ns (str): Field namespace (separated by .). Returns: diff --git a/tests/fixtures/manifest-v2.json b/tests/fixtures/manifest-v2.json index ead8cc04..4bda07be 100644 --- a/tests/fixtures/manifest-v2.json +++ b/tests/fixtures/manifest-v2.json @@ -99,7 +99,9 @@ "status": { "name": "status", "description": "Orders can be one of the following statuses:\n\n| status | description |\n|----------------|------------------------------------------------------------------------------------------------------------------------|\n| placed | The order has been placed but has not yet left the warehouse |\n| shipped | The order has ben shipped to the customer and is currently in transit |\n| completed | The order has been received by the customer |\n| return_pending | The customer has indicated that they would like to return the order, but it has not yet been received at the warehouse |\n| returned | The order has been returned by the customer and received at the warehouse |", - "meta": {}, + "meta": { + "metabase.description": "Order status: placed, shipped, completed, return_pending, or returned." + }, "data_type": null, "quote": null, "tags": [] @@ -145,7 +147,9 @@ "tags": [] } }, - "meta": {}, + "meta": { + "metabase.description": "Basic and derived order information from payments" + }, "docs": { "show": true }, diff --git a/tests/test_manifest.py b/tests/test_manifest.py index 938390cc..e8755799 100644 --- a/tests/test_manifest.py +++ b/tests/test_manifest.py @@ -258,7 +258,7 @@ def test_v2(): group=Group.nodes, name="orders", alias="orders", - description="This table has basic information about orders, as well as some derived facts based on payments", + description="Basic and derived order information from payments", unique_id="model.jaffle_shop.orders", columns=[ Column( @@ -278,7 +278,7 @@ def test_v2(): ), Column( name="status", - description="Orders can be one of the following statuses:\n\n| status | description |\n|----------------|------------------------------------------------------------------------------------------------------------------------|\n| placed | The order has been placed but has not yet left the warehouse |\n| shipped | The order has ben shipped to the customer and is currently in transit |\n| completed | The order has been received by the customer |\n| return_pending | The customer has indicated that they would like to return the order, but it has not yet been received at the warehouse |\n| returned | The order has been returned by the customer and received at the warehouse |", + description="Order status: placed, shipped, completed, return_pending, or returned.", ), Column( name="amount",