From 9ead5349def83f2531f50a41a9f69ed5abafc00e Mon Sep 17 00:00:00 2001 From: Beto Dealmeida Date: Tue, 5 Mar 2024 12:16:24 -0500 Subject: [PATCH] Add tests --- .../cli/superset/sync/dbt/command.py | 7 +- tests/cli/superset/sync/dbt/command_test.py | 1668 +++++++++++++++-- tests/cli/superset/sync/dbt/metrics_test.py | 4 + 3 files changed, 1538 insertions(+), 141 deletions(-) diff --git a/src/preset_cli/cli/superset/sync/dbt/command.py b/src/preset_cli/cli/superset/sync/dbt/command.py index 3f1c8253..3bd8fc1b 100644 --- a/src/preset_cli/cli/superset/sync/dbt/command.py +++ b/src/preset_cli/cli/superset/sync/dbt/command.py @@ -139,9 +139,6 @@ def dbt_core( # pylint: disable=too-many-arguments, too-many-branches, too-many if profiles is None: profiles = os.path.expanduser("~/.dbt/profiles.yml") - with open(profiles, encoding="utf-8") as inp: - config = yaml.safe_load(inp) - dialect = MFSQLEngine(config[project]["outputs"][target]["type"].upper()) file_path = Path(file) @@ -185,6 +182,10 @@ def dbt_core( # pylint: disable=too-many-arguments, too-many-branches, too-many with open(manifest, encoding="utf-8") as input_: configs = yaml.load(input_, Loader=yaml.SafeLoader) + with open(profiles, encoding="utf-8") as input_: + config = yaml.safe_load(input_) + dialect = MFSQLEngine(config[project]["outputs"][target]["type"].upper()) + model_schema = ModelSchema() models = [] for config in configs["nodes"].values(): diff --git a/tests/cli/superset/sync/dbt/command_test.py b/tests/cli/superset/sync/dbt/command_test.py index 04714e5d..0258fc3e 100644 --- a/tests/cli/superset/sync/dbt/command_test.py +++ b/tests/cli/superset/sync/dbt/command_test.py @@ -1,11 +1,12 @@ """ Tests for the dbt import command. """ -# pylint: disable=invalid-name, too-many-lines +# pylint: disable=invalid-name, too-many-lines, line-too-long import os import warnings from pathlib import Path +from subprocess import CalledProcessError import pytest import yaml @@ -25,6 +26,28 @@ dirname, _ = os.path.split(os.path.abspath(__file__)) with open(os.path.join(dirname, "manifest.json"), encoding="utf-8") as fp: manifest_contents = fp.read() +with open(os.path.join(dirname, "manifest-metricflow.json"), encoding="utf-8") as fp: + manifest_metricflow_contents = fp.read() + + +profiles_contents = yaml.dump( + { + "default": { + "outputs": { + "dev": { + "type": "bigquery", + }, + }, + }, + "my_project": { + "outputs": { + "dev": { + "type": "bigquery", + }, + }, + }, + }, +) dbt_core_models = [ { @@ -40,18 +63,1071 @@ "children": ["metric.superset_examples.cnt"], "depends_on": { "macros": [], - "nodes": [ - "source.superset_examples.public.channels", - "source.superset_examples.public.messages", - ], + "nodes": [ + "source.superset_examples.public.channels", + "source.superset_examples.public.messages", + ], + }, + "unrendered_config": {"materialized": "view"}, + "resource_type": "model", + "path": "slack/messages_channels.sql", + "extra_ctes": [], + "package_name": "superset_examples", + "alias": "messages_channels", + "relation_name": '"examples_dev"."public"."messages_channels"', + "config": { + "enabled": True, + "alias": None, + "schema": None, + "database": None, + "tags": [], + "meta": {}, + "materialized": "view", + "persist_docs": {}, + "quoting": {}, + "column_types": {}, + "full_refresh": None, + "on_schema_change": "ignore", + "post-hook": [], + "pre-hook": [], + }, + "patch_path": None, + "compiled_sql": ( + "SELECT messages.ts, channels.name, messages.text " + 'FROM "examples_dev"."public"."messages" messages ' + 'JOIN "examples_dev"."public"."channels" channels ' + "ON messages.channel_id = channels.id" + ), + "extra_ctes_injected": True, + "deferred": False, + "root_path": "/Users/beto/Projects/dbt-examples/superset_examples", + "original_file_path": "models/slack/messages_channels.sql", + "refs": [], + "fqn": ["superset_examples", "slack", "messages_channels"], + "raw_sql": ( + "SELECT messages.ts, channels.name, messages.text " + "FROM {{ source ('public', 'messages') }} messages " + "JOIN {{ source ('public', 'channels') }} channels " + "ON messages.channel_id = channels.id" + ), + "build_path": None, + "sources": [["public", "channels"], ["public", "messages"]], + "checksum": { + "name": "sha256", + "checksum": "b4ce232b28280daa522b37e12c36b67911e2a98456b8a3b99440075ec5564609", + }, + "docs": {"show": True}, + "compiled_path": "target/compiled/superset_examples/models/slack/messages_channels.sql", + "compiled": True, + }, +] + +dbt_core_metrics = [ + { + "label": "", + "sql": "*", + "depends_on": ["model.superset_examples.messages_channels"], + "meta": {}, + "description": "", + "name": "cnt", + "type": "count", + "filters": [], + "unique_id": "metric.superset_examples.cnt", + "created_at": 1642630986.1942852, + "package_name": "superset_examples", + "sources": [], + "root_path": "/Users/beto/Projects/dbt-examples/superset_examples", + "path": "slack/schema.yml", + "resource_type": "metric", + "original_file_path": "models/slack/schema.yml", + "model": "ref('messages_channels')", + "timestamp": None, + "fqn": ["superset_examples", "slack", "cnt"], + "time_grains": [], + "tags": [], + "refs": [["messages_channels"]], + "dimensions": [], + }, +] + +superset_metrics = { + "model.superset_examples.messages_channels": [ + { + "description": "", + "expression": "COUNT(*)", + "extra": "{}", + "metric_name": "cnt", + "metric_type": "count", + "verbose_name": "", + }, + ], +} + +dbt_cloud_models = [ + { + "database": "examples_dev", + "description": "", + "meta": {}, + "name": "messages_channels", + "schema": "public", + "unique_id": "model.superset_examples.messages_channels", + }, + { + "database": "some_other_table", + "description": "", + "meta": {}, + "name": "some_other_table", + "schema": "public", + "unique_id": "model.superset_examples.some_other_table", + }, +] + +dbt_cloud_metrics = [ + { + "depends_on": ["model.superset_examples.messages_channels"], + "description": "", + "filters": [], + "label": "", + "meta": {}, + "name": "cnt", + "sql": "*", + "type": "count", + "unique_id": "metric.superset_examples.cnt", + }, + { + "depends_on": ["a", "b"], + "description": "", + "filters": [], + "label": "", + "meta": {}, + "name": "multiple parents", + "sql": "*", + "type": "count", + "unique_id": "c", + }, +] + +dbt_metricflow_metrics = [ + {"name": "a", "type": "Simple", "description": "The simplest metric"}, + {"name": "b", "type": "derived", "description": "Too complex for Superset"}, + {"name": "c", "type": "derived", "description": "Multiple models"}, +] + + +dbt_metricflow_models = [ + { + "unique_id": "model.jaffle_shop.stg_products", + "description": "Product (food and drink items that can be ordered) data with basic cleaning and transformation applied, one row per product.", + "tags": [], + "columns": [ + { + "name": "product_id", + "description": "The unique key for each product.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + ], + "schema": "dbt_beto", + "meta": {}, + "database": "dbt-tutorial-347100", + "config": { + "enabled": True, + "alias": None, + "schema": None, + "database": None, + "tags": [], + "meta": {}, + "group": None, + "materialized": "view", + "incremental_strategy": None, + "persist_docs": {}, + "quoting": {}, + "column_types": {}, + "full_refresh": None, + "unique_key": None, + "on_schema_change": "ignore", + "on_configuration_change": "apply", + "grants": {}, + "packages": [], + "docs": {"show": True, "node_color": None}, + "contract": {"enforced": False}, + "post-hook": [], + "pre-hook": [], + }, + "name": "stg_products", + "deferred": False, + "contract": {"enforced": False, "checksum": None}, + "metrics": [], + "docs": {"show": True, "node_color": None}, + "package_name": "jaffle_shop", + "raw_code": "with\n\nsource as (\n\n select * from {{ source('ecom', 'raw_products') }}\n\n),\n\nrenamed as (\n\n select\n\n ---------- ids\n sku as product_id,\n\n ---------- text\n name as product_name,\n type as product_type,\n description as product_description,\n\n\n ---------- numerics\n (price / 100.0) as product_price,\n\n ---------- booleans\n case\n when type = 'jaffle' then 1\n else 0\n end as is_food_item,\n\n case\n when type = 'beverage' then 1\n else 0\n end as is_drink_item\n\n from source\n\n)\n\nselect * from renamed", + "access": "protected", + "original_file_path": "models/staging/stg_products.sql", + "group": None, + "patch_path": "jaffle_shop://models/staging/stg_products.yml", + "build_path": None, + "extra_ctes": [], + "fqn": ["jaffle_shop", "staging", "stg_products"], + "language": "sql", + "extra_ctes_injected": True, + "checksum": { + "name": "sha256", + "checksum": "76a701136875b4f04bcd365446a2dc3e3c433136a2d30b2d9ede55298c84404e", + }, + "path": "staging/stg_products.sql", + "unrendered_config": {"materialized": "view"}, + "deprecation_date": None, + "resource_type": "model", + "relation_name": "`dbt-tutorial-347100`.`dbt_beto`.`stg_products`", + "compiled_path": "target/compiled/jaffle_shop/models/staging/stg_products.sql", + "children": [ + "model.jaffle_shop.order_items", + "semantic_model.jaffle_shop.stg_products", + "test.jaffle_shop.not_null_stg_products_product_id.6373b0acf3", + "test.jaffle_shop.unique_stg_products_product_id.7d950a1467", + ], + "refs": [], + "latest_version": None, + "sources": [["ecom", "raw_products"]], + "alias": "stg_products", + "version": None, + "compiled": True, + "created_at": 1702514525.401679, + "compiled_code": "with\n\nsource as (\n\n select * from `dbt-tutorial-347100`.`dbt_beto`.`raw_products`\n\n),\n\nrenamed as (\n\n select\n\n ---------- ids\n sku as product_id,\n\n ---------- text\n name as product_name,\n type as product_type,\n description as product_description,\n\n\n ---------- numerics\n (price / 100.0) as product_price,\n\n ---------- booleans\n case\n when type = 'jaffle' then 1\n else 0\n end as is_food_item,\n\n case\n when type = 'beverage' then 1\n else 0\n end as is_drink_item\n\n from source\n\n)\n\nselect * from renamed", + "constraints": [], + "depends_on": {"macros": [], "nodes": ["source.jaffle_shop.ecom.raw_products"]}, + }, + { + "unique_id": "model.jaffle_shop.stg_customers", + "description": "Customer data with basic cleaning and transformation applied, one row per customer.", + "tags": [], + "columns": [ + { + "name": "customer_id", + "description": "The unique key for each customer.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + ], + "schema": "dbt_beto", + "meta": {}, + "database": "dbt-tutorial-347100", + "config": { + "enabled": True, + "alias": None, + "schema": None, + "database": None, + "tags": [], + "meta": {}, + "group": None, + "materialized": "view", + "incremental_strategy": None, + "persist_docs": {}, + "quoting": {}, + "column_types": {}, + "full_refresh": None, + "unique_key": None, + "on_schema_change": "ignore", + "on_configuration_change": "apply", + "grants": {}, + "packages": [], + "docs": {"show": True, "node_color": None}, + "contract": {"enforced": False}, + "post-hook": [], + "pre-hook": [], + }, + "name": "stg_customers", + "deferred": False, + "contract": {"enforced": False, "checksum": None}, + "metrics": [], + "docs": {"show": True, "node_color": None}, + "package_name": "jaffle_shop", + "raw_code": "with\n\nsource as (\n\n select * from {{ source('ecom', 'raw_customers') }}\n\n),\n\nrenamed as (\n\n select\n\n ---------- ids\n id as customer_id,\n\n ---------- text\n name as customer_name\n\n from source\n\n)\n\nselect * from renamed", + "access": "protected", + "original_file_path": "models/staging/stg_customers.sql", + "group": None, + "patch_path": "jaffle_shop://models/staging/stg_customers.yml", + "build_path": None, + "extra_ctes": [], + "fqn": ["jaffle_shop", "staging", "stg_customers"], + "language": "sql", + "extra_ctes_injected": True, + "checksum": { + "name": "sha256", + "checksum": "37b269b48f94b4526ee48b7123397b9a2f457266e97bf5b876b988cbce9eeef6", + }, + "path": "staging/stg_customers.sql", + "unrendered_config": {"materialized": "view"}, + "deprecation_date": None, + "resource_type": "model", + "relation_name": "`dbt-tutorial-347100`.`dbt_beto`.`stg_customers`", + "compiled_path": "target/compiled/jaffle_shop/models/staging/stg_customers.sql", + "children": [ + "model.jaffle_shop.customers", + "test.jaffle_shop.not_null_stg_customers_customer_id.e2cfb1f9aa", + "test.jaffle_shop.relationships_orders_customer_id__customer_id__ref_stg_customers_.918495ce16", + "test.jaffle_shop.unique_stg_customers_customer_id.c7614daada", + ], + "refs": [], + "latest_version": None, + "sources": [["ecom", "raw_customers"]], + "alias": "stg_customers", + "version": None, + "compiled": True, + "created_at": 1702514525.416814, + "compiled_code": "with\n\nsource as (\n\n select * from `dbt-tutorial-347100`.`dbt_beto`.`raw_customers`\n\n),\n\nrenamed as (\n\n select\n\n ---------- ids\n id as customer_id,\n\n ---------- text\n name as customer_name\n\n from source\n\n)\n\nselect * from renamed", + "constraints": [], + "depends_on": { + "macros": [], + "nodes": ["source.jaffle_shop.ecom.raw_customers"], + }, + }, + { + "unique_id": "model.jaffle_shop.stg_supplies", + "description": "List of our supply expenses data with basic cleaning and transformation applied.\nOne row per supply cost, not per supply. As supply costs fluctuate they receive a new row with a new UUID. Thus there can be multiple rows per supply_id.\n", + "tags": [], + "columns": [ + { + "name": "supply_uuid", + "description": "The unique key of our supplies per cost.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + ], + "schema": "dbt_beto", + "meta": {}, + "database": "dbt-tutorial-347100", + "config": { + "enabled": True, + "alias": None, + "schema": None, + "database": None, + "tags": [], + "meta": {}, + "group": None, + "materialized": "view", + "incremental_strategy": None, + "persist_docs": {}, + "quoting": {}, + "column_types": {}, + "full_refresh": None, + "unique_key": None, + "on_schema_change": "ignore", + "on_configuration_change": "apply", + "grants": {}, + "packages": [], + "docs": {"show": True, "node_color": None}, + "contract": {"enforced": False}, + "post-hook": [], + "pre-hook": [], + }, + "name": "stg_supplies", + "deferred": False, + "contract": {"enforced": False, "checksum": None}, + "metrics": [], + "docs": {"show": True, "node_color": None}, + "package_name": "jaffle_shop", + "raw_code": "with\n\nsource as (\n\n select * from {{ source('ecom', 'raw_supplies') }}\n\n),\n\nrenamed as (\n\n select\n\n ---------- ids\n {{ dbt_utils.generate_surrogate_key(['id', 'sku']) }} as supply_uuid,\n id as supply_id,\n sku as product_id,\n\n ---------- text\n name as supply_name,\n\n---------- numerics\n (cost / 100.0) as supply_cost,\n\n ---------- booleans\n perishable as is_perishable_supply\n\n from source\n\n)\n\nselect * from renamed", + "access": "protected", + "original_file_path": "models/staging/stg_supplies.sql", + "group": None, + "patch_path": "jaffle_shop://models/staging/stg_supplies.yml", + "build_path": None, + "extra_ctes": [], + "fqn": ["jaffle_shop", "staging", "stg_supplies"], + "language": "sql", + "extra_ctes_injected": True, + "checksum": { + "name": "sha256", + "checksum": "f3e61efc6f6c2d522c3c9385d9914eae23ff7bf129c6fb6f11b2dbdecef6f50f", + }, + "path": "staging/stg_supplies.sql", + "unrendered_config": {"materialized": "view"}, + "deprecation_date": None, + "resource_type": "model", + "relation_name": "`dbt-tutorial-347100`.`dbt_beto`.`stg_supplies`", + "compiled_path": "target/compiled/jaffle_shop/models/staging/stg_supplies.sql", + "children": [ + "model.jaffle_shop.order_items", + "test.jaffle_shop.not_null_stg_supplies_supply_uuid.515c6eda6d", + "test.jaffle_shop.unique_stg_supplies_supply_uuid.c9e3edcfed", + ], + "refs": [], + "latest_version": None, + "sources": [["ecom", "raw_supplies"]], + "alias": "stg_supplies", + "version": None, + "compiled": True, + "created_at": 1702514525.3776808, + "compiled_code": "with\n\nsource as (\n\n select * from `dbt-tutorial-347100`.`dbt_beto`.`raw_supplies`\n\n),\n\nrenamed as (\n\n select\n\n ---------- ids\n \n \nto_hex(md5(cast(coalesce(cast(id as STRING), '_dbt_utils_surrogate_key_null_') || '-' || coalesce(cast(sku as STRING), '_dbt_utils_surrogate_key_null_') as STRING))) as supply_uuid,\n id as supply_id,\n sku as product_id,\n\n ---------- text\n name as supply_name,\n\n ---------- numerics\n (cost / 100.0) as supply_cost,\n\n ---------- booleans\n perishable as is_perishable_supply\n\n from source\n\n)\n\nselect * from renamed", + "constraints": [], + "depends_on": { + "macros": ["macro.dbt_utils.generate_surrogate_key"], + "nodes": ["source.jaffle_shop.ecom.raw_supplies"], + }, + }, + { + "unique_id": "model.jaffle_shop.stg_orders", + "description": "Order data with basic cleaning and transformation applied, one row per order.", + "tags": [], + "columns": [ + { + "name": "order_id", + "description": "The unique key for each order.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + ], + "schema": "dbt_beto", + "meta": {}, + "database": "dbt-tutorial-347100", + "config": { + "enabled": True, + "alias": None, + "schema": None, + "database": None, + "tags": [], + "meta": {}, + "group": None, + "materialized": "view", + "incremental_strategy": None, + "persist_docs": {}, + "quoting": {}, + "column_types": {}, + "full_refresh": None, + "unique_key": None, + "on_schema_change": "ignore", + "on_configuration_change": "apply", + "grants": {}, + "packages": [], + "docs": {"show": True, "node_color": None}, + "contract": {"enforced": False}, + "post-hook": [], + "pre-hook": [], + }, + "name": "stg_orders", + "deferred": False, + "contract": {"enforced": False, "checksum": None}, + "metrics": [], + "docs": {"show": True, "node_color": None}, + "package_name": "jaffle_shop", + "raw_code": "with\n\nsource as (\n\n select * from {{ source('ecom', 'raw_orders') }}\n -- if you generate a larger dataset, you can limit the timespan to the current time with the following line\n -- where ordered_at <= {{ var('truncate_timespan_to') }}\n\n),\n\nrenamed as (\n\n select\n\n ---------- ids\n id as order_id,\n store_id as location_id,\n customer as customer_id,\n\n ---------- numerics\n (order_total / 100.0) as order_total,\n(tax_paid / 100.0) as tax_paid,\n\n ---------- timestamps\n {{dbt.date_trunc('day','ordered_at')}} as ordered_at\n\n from source\n\n)\n\nselect * from renamed", + "access": "protected", + "original_file_path": "models/staging/stg_orders.sql", + "group": None, + "patch_path": "jaffle_shop://models/staging/stg_orders.yml", + "build_path": None, + "extra_ctes": [], + "fqn": ["jaffle_shop", "staging", "stg_orders"], + "language": "sql", + "extra_ctes_injected": True, + "checksum": { + "name": "sha256", + "checksum": "64e9b156a536566cf07b1f90d7650a6d3af1c25eabfadefad04ba5533b82a83d", + }, + "path": "staging/stg_orders.sql", + "unrendered_config": {"materialized": "view"}, + "deprecation_date": None, + "resource_type": "model", + "relation_name": "`dbt-tutorial-347100`.`dbt_beto`.`stg_orders`", + "compiled_path": "target/compiled/jaffle_shop/models/staging/stg_orders.sql", + "children": [ + "model.jaffle_shop.order_items", + "model.jaffle_shop.orders", + "test.jaffle_shop.not_null_stg_orders_order_id.81cfe2fe64", + "test.jaffle_shop.unique_stg_orders_order_id.e3b841c71a", + ], + "refs": [], + "latest_version": None, + "sources": [["ecom", "raw_orders"]], + "alias": "stg_orders", + "version": None, + "compiled": True, + "created_at": 1702514525.396977, + "compiled_code": "with\n\nsource as (\n\n select * from `dbt-tutorial-347100`.`dbt_beto`.`raw_orders`\n -- if you generate a larger dataset, you can limit the timespan to the current time with the following line\n -- where ordered_at <= current_timestamp()\n\n),\n\nrenamed as (\n\n select\n\n ---------ids\n id as order_id,\n store_id as location_id,\n customer as customer_id,\n\n ---------- numerics\n (order_total / 100.0) as order_total,\n (tax_paid / 100.0) as tax_paid,\n\n ---------- timestamps\n timestamp_trunc(\n cast(ordered_at as timestamp),\n day\n ) as ordered_at\n\n from source\n\n)\n\nselect * from renamed", + "constraints": [], + "depends_on": { + "macros": ["macro.dbt.current_timestamp", "macro.dbt.date_trunc"], + "nodes": ["source.jaffle_shop.ecom.raw_orders"], + }, + }, + { + "unique_id": "model.jaffle_shop.stg_order_items", + "description": "Individual food and drink items that make up our orders, one row per item.", + "tags": [], + "columns": [ + { + "name": "order_item_id", + "description": "The unique key for each order item.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + ], + "schema": "dbt_beto", + "meta": {}, + "database": "dbt-tutorial-347100", + "config": { + "enabled": True, + "alias": None, + "schema": None, + "database": None, + "tags": [], + "meta": {}, + "group": None, + "materialized": "view", + "incremental_strategy": None, + "persist_docs": {}, + "quoting": {}, + "column_types": {}, + "full_refresh": None, + "unique_key": None, + "on_schema_change": "ignore", + "on_configuration_change": "apply", + "grants": {}, + "packages": [], + "docs": {"show": True, "node_color": None}, + "contract": {"enforced": False}, + "post-hook": [], + "pre-hook": [], + }, + "name": "stg_order_items", + "deferred": False, + "contract": {"enforced": False, "checksum": None}, + "metrics": [], + "docs": {"show": True, "node_color": None}, + "package_name": "jaffle_shop", + "raw_code": "with\n\nsource as (\n\n select * from {{ source('ecom', 'raw_items') }}\n\n),\n\nrenamed as (\n\n select\n\n ---------- ids\n id as order_item_id,\n order_id,\n sku as product_id\n\n from source\n\n)\n\nselect * from renamed", + "access": "protected", + "original_file_path": "models/staging/stg_order_items.sql", + "group": None, + "patch_path": "jaffle_shop://models/staging/stg_order_items.yml", + "build_path": None, + "extra_ctes": [], + "fqn": ["jaffle_shop", "staging", "stg_order_items"], + "language": "sql", + "extra_ctes_injected": True, + "checksum": { + "name": "sha256", + "checksum": "c4551967544f92a36cf257eccdb2c2806343ce82e1c6d96c59adbd9263539ce2", + }, + "path": "staging/stg_order_items.sql", + "unrendered_config": {"materialized": "view"}, + "deprecation_date": None, + "resource_type": "model", + "relation_name": "`dbt-tutorial-347100`.`dbt_beto`.`stg_order_items`", + "compiled_path": "target/compiled/jaffle_shop/models/staging/stg_order_items.sql", + "children": [ + "model.jaffle_shop.order_items", + "test.jaffle_shop.not_null_stg_order_items_order_item_id.26a7e2bc35", + "test.jaffle_shop.unique_stg_order_items_order_item_id.90e333a108", + ], + "refs": [], + "latest_version": None, + "sources": [["ecom", "raw_items"]], + "alias": "stg_order_items", + "version": None, + "compiled": True, + "created_at": 1702514525.436424, + "compiled_code": "with\n\nsource as (\n\n select * from `dbt-tutorial-347100`.`dbt_beto`.`raw_items`\n\n),\n\nrenamed as (\n\n select\n\n ---------- ids\n id as order_item_id,\n order_id,\n sku as product_id\n\n from source\n\n)\n\nselect * from renamed", + "constraints": [], + "depends_on": {"macros": [], "nodes": ["source.jaffle_shop.ecom.raw_items"]}, + }, + { + "unique_id": "model.jaffle_shop.stg_locations", + "description": "List of open locations with basic cleaning and transformation applied, one row per location.", + "tags": [], + "columns": [ + { + "name": "location_id", + "description": "The unique key for each location.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + ], + "schema": "dbt_beto", + "meta": {}, + "database": "dbt-tutorial-347100", + "config": { + "enabled": True, + "alias": None, + "schema": None, + "database": None, + "tags": [], + "meta": {}, + "group": None, + "materialized": "view", + "incremental_strategy": None, + "persist_docs": {}, + "quoting": {}, + "column_types": {}, + "full_refresh": None, + "unique_key": None, + "on_schema_change": "ignore", + "on_configuration_change": "apply", + "grants": {}, + "packages": [], + "docs": {"show": True, "node_color": None}, + "contract": {"enforced": False}, + "post-hook": [], + "pre-hook": [], + }, + "name": "stg_locations", + "deferred": False, + "contract": {"enforced": False, "checksum": None}, + "metrics": [], + "docs": {"show": True, "node_color": None}, + "package_name": "jaffle_shop", + "raw_code": "with\n\nsource as (\n\n select * from {{ source('ecom', 'raw_stores') }}\n\n -- if you generate a larger dataset, you can limit the timespan to the current time with the following line\n -- where ordered_at <= {{ var('truncate_timespan_to') }}\n),\n\nrenamed as (\n\n select\n\n ---------- ids\n id as location_id,\n\n ---------- text\n name as location_name,\n\n ---------- numerics\n tax_rate,\n\n ---------- timestamps\n {{dbt.date_trunc('day', 'opened_at')}} as opened_at\n\n from source\n\n)\n\nselect * from renamed", + "access": "protected", + "original_file_path": "models/staging/stg_locations.sql", + "group": None, + "patch_path": "jaffle_shop://models/staging/stg_locations.yml", + "build_path": None, + "extra_ctes": [], + "fqn": ["jaffle_shop", "staging", "stg_locations"], + "language": "sql", + "extra_ctes_injected": True, + "checksum": { + "name": "sha256", + "checksum": "9e3a52c057340df711ad32e83c567143175fd1fc54f2d5c75ff4fbc198a597e3", + }, + "path": "staging/stg_locations.sql", + "unrendered_config": {"materialized": "view"}, + "deprecation_date": None, + "resource_type": "model", + "relation_name": "`dbt-tutorial-347100`.`dbt_beto`.`stg_locations`", + "compiled_path": "target/compiled/jaffle_shop/models/staging/stg_locations.sql", + "children": [ + "semantic_model.jaffle_shop.locations", + "test.jaffle_shop.not_null_stg_locations_location_id.3d237927d2", + "test.jaffle_shop.unique_stg_locations_location_id.2e2fc58ecc", + ], + "refs": [], + "latest_version": None, + "sources": [["ecom", "raw_stores"]], + "alias": "stg_locations", + "version": None, + "compiled": True, + "created_at": 1702514525.44064, + "compiled_code": "with\n\nsource as (\n\n select * from `dbt-tutorial-347100`.`dbt_beto`.`raw_stores`\n\n -- if you generate a larger dataset, you can limit the timespan to the current time with the following line\n -- where ordered_at <= current_timestamp()\n),\n\nrenamed as (\n\n select\n\n ---------- ids\n id as location_id,\n\n ---------- text\n name as location_name,\n\n ---------- numerics\n tax_rate,\n\n ---------- timestamps\n timestamp_trunc(\n cast(opened_at as timestamp),\n day\n ) as opened_at\n\n from source\n\n)\n\nselect * from renamed", + "constraints": [], + "depends_on": { + "macros": ["macro.dbt.current_timestamp", "macro.dbt.date_trunc"], + "nodes": ["source.jaffle_shop.ecom.raw_stores"], + }, + }, + { + "unique_id": "model.jaffle_shop.customers", + "description": "Customer overview data mart, offering key details for each unique customer. One row per customer.", + "tags": [], + "columns": [ + { + "name": "customer_id", + "description": "The unique key of the orders mart.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "customer_name", + "description": "Customers' full name.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "count_lifetime_orders", + "description": "Total number of orders a customer has ever placed.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "first_ordered_at", + "description": "The timestamp when a customer placed their first order.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "last_ordered_at", + "description": "The timestamp of a customer's most recent order.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "lifetime_spend_pretax", + "description": "The sum of all the pre-tax subtotals of every order a customer has placed.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "lifetime_spend", + "description": "The sum of all the order totals (including tax) that a customer has ever placed.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "customer_type", + "description": "Options are 'new' or 'returning', indicating if a customer has ordered more than once or has only placed their first order to date.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + ], + "schema": "dbt_beto", + "meta": {}, + "database": "dbt-tutorial-347100", + "config": { + "enabled": True, + "alias": None, + "schema": None, + "database": None, + "tags": [], + "meta": {}, + "group": None, + "materialized": "table", + "incremental_strategy": None, + "persist_docs": {}, + "quoting": {}, + "column_types": {}, + "full_refresh": None, + "unique_key": None, + "on_schema_change": "ignore", + "on_configuration_change": "apply", + "grants": {}, + "packages": [], + "docs": {"show": True, "node_color": None}, + "contract": {"enforced": False}, + "post-hook": [], + "pre-hook": [], + }, + "name": "customers", + "deferred": False, + "contract": {"enforced": False, "checksum": None}, + "metrics": [], + "docs": {"show": True, "node_color": None}, + "package_name": "jaffle_shop", + "raw_code": "with\n\ncustomers as (\n\n select * from {{ ref('stg_customers') }}\n\n),\n\norders_table as (\n\n select * from {{ ref('orders') }}\n\n),\n\norder_items_table as (\n\n select * from {{ ref('order_items') }}\n),\n\norder_summary as (\n\n select\n customer_id,\n\n count(distinct orders.order_id) as count_lifetime_orders,\n count(distinct orders.order_id) > 1 as is_repeat_buyer,\n min(orders.ordered_at) as first_ordered_at,\n max(orders.ordered_at) as last_ordered_at,\n sum(order_items.product_price) as lifetime_spend_pretax,\n sum(orders.order_total) as lifetime_spend\n\n from orders_table as orders\n \n left join order_items_table as order_items on orders.order_id = order_items.order_id\n \n group by 1\n\n),\n\njoined as (\n\n select\n customers.*,\n order_summary.count_lifetime_orders,\n order_summary.first_ordered_at,\n order_summary.last_ordered_at,\n order_summary.lifetime_spend_pretax,\n order_summary.lifetime_spend,\n\n case\n when order_summary.is_repeat_buyer then 'returning'\n else 'new'\n end as customer_type\n\n from customers\n\n left join order_summary\n on customers.customer_id = order_summary.customer_id\n\n)\n\nselect * from joined", + "access": "protected", + "original_file_path": "models/marts/customers.sql", + "group": None, + "patch_path": "jaffle_shop://models/marts/customers.yml", + "build_path": None, + "extra_ctes": [], + "fqn": ["jaffle_shop", "marts", "customers"], + "language": "sql", + "extra_ctes_injected": True, + "checksum": { + "name": "sha256", + "checksum": "aab6679f91377f285bfb321bce22611ae372aabbdeb6081457bcb2fa9ac40b10", + }, + "path": "marts/customers.sql", + "unrendered_config": {"materialized": "table"}, + "deprecation_date": None, + "resource_type": "model", + "relation_name": "`dbt-tutorial-347100`.`dbt_beto`.`customers`", + "compiled_path": "target/compiled/jaffle_shop/models/marts/customers.sql", + "children": [ + "semantic_model.jaffle_shop.customers", + "test.jaffle_shop.accepted_values_customers_customer_type__new__returning.d12f0947c8", + "test.jaffle_shop.not_null_customers_customer_id.5c9bf9911d", + "test.jaffle_shop.unique_customers_customer_id.c5af1ff4b1", + ], + "refs": [ + {"name": "stg_customers", "package": None, "version": None}, + {"name": "orders", "package": None, "version": None}, + {"name": "order_items", "package": None, "version": None}, + ], + "latest_version": None, + "sources": [], + "alias": "customers", + "version": None, + "compiled": True, + "created_at": 1702514525.450856, + "compiled_code": "with\n\ncustomers as (\n\n select * from `dbt-tutorial-347100`.`dbt_beto`.`stg_customers`\n\n),\n\norders_table as (\n\n select * from `dbt-tutorial-347100`.`dbt_beto`.`orders`\n\n),\n\norder_items_table as (\n\n select * from `dbt-tutorial-347100`.`dbt_beto`.`order_items`\n),\n\norder_summary as (\n\n select\n customer_id,\n\n count(distinct orders.order_id) as count_lifetime_orders,\n count(distinct orders.order_id) > 1 as is_repeat_buyer,\n min(orders.ordered_at) as first_ordered_at,\n max(orders.ordered_at) as last_ordered_at,\n sum(order_items.product_price) as lifetime_spend_pretax,\n sum(orders.order_total) as lifetime_spend\n\n from orders_table as orders\n \n left join order_items_table as order_items on orders.order_id = order_items.order_id\n \n group by 1\n\n),\n\njoined as (\n\n select\n customers.*,\norder_summary.count_lifetime_orders,\n order_summary.first_ordered_at,\n order_summary.last_ordered_at,\n order_summary.lifetime_spend_pretax,\n order_summary.lifetime_spend,\n\n case\n when order_summary.is_repeat_buyer then 'returning'\n else 'new'\n end as customer_type\n\n from customers\n\n left join order_summary\n on customers.customer_id = order_summary.customer_id\n\n)\n\nselect * from joined", + "constraints": [], + "depends_on": { + "macros": [], + "nodes": [ + "model.jaffle_shop.stg_customers", + "model.jaffle_shop.orders", + "model.jaffle_shop.order_items", + ], + }, + }, + { + "unique_id": "model.jaffle_shop.orders", + "description": "Order overview data mart, offering key details for each order inlcluding if it's a customer's first order and a food vs. drink item breakdown. One row per order.", + "tags": [], + "columns": [ + { + "name": "order_id", + "description": "The unique key of the orders mart.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "customer_id", + "description": "The foreign key relating to the customer who placed the order.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "location_id", + "description": "The foreign key relating to the location the order was placed at.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "order_total", + "description": "The total amount of the order in USD including tax.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "ordered_at", + "description": "The timestamp the order was placed at.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "count_food_items", + "description": "The number of individual food items ordered.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "count_drink_items", + "description": "The number of individual drink items ordered.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "count_items", + "description": "The total number of both food and drink items ordered.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "subtotal_food_items", + "description": "The sum of all the food item prices without tax.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "subtotal_drink_items", + "description": "The sum of all the drink item prices without tax.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "subtotal", + "description": "The sum total of both food and drink item prices without tax.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "order_cost", + "description": "The sum of supply expenses to fulfill the order.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "location_name", + "description": "The full location name of where this order was placed. Denormalized from `stg_locations`.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "is_first_order", + "description": "A boolean indicating if this order is from a new customer placing their first order.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "is_food_order", + "description": "A boolean indicating if this order included any food items.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + { + "name": "is_drink_order", + "description": "A boolean indicating if this order included any drink items.", + "meta": {}, + "data_type": None, + "constraints": [], + "quote": None, + "tags": [], + }, + ], + "schema": "dbt_beto", + "meta": {}, + "database": "dbt-tutorial-347100", + "config": { + "enabled": True, + "alias": None, + "schema": None, + "database": None, + "tags": [], + "meta": {}, + "group": None, + "materialized": "table", + "incremental_strategy": None, + "persist_docs": {}, + "quoting": {}, + "column_types": {}, + "full_refresh": None, + "unique_key": None, + "on_schema_change": "ignore", + "on_configuration_change": "apply", + "grants": {}, + "packages": [], + "docs": {"show": True, "node_color": None}, + "contract": {"enforced": False}, + "post-hook": [], + "pre-hook": [], + }, + "name": "orders", + "deferred": False, + "contract": {"enforced": False, "checksum": None}, + "metrics": [], + "docs": {"show": True, "node_color": None}, + "package_name": "jaffle_shop", + "raw_code": "with \n\norders as (\n \n select * from {{ ref('stg_orders')}}\n\n),\n\norder_items_table as (\n \n select * from {{ ref('order_items')}}\n\n),\n\norder_items_summary as (\n\n select\n\n order_items.order_id,\n\n sum(supply_cost) as order_cost,\n sum(is_food_item) as count_food_items,\n sum(is_drink_item) as count_drink_items\n\n\n from order_items_table as order_items\n\n group by 1\n\n),\n\n\ncompute_booleans as (\n select\n\n orders.*,\n count_food_items > 0 as is_food_order,\n count_drink_items > 0 as is_drink_order,\n order_cost\n\n from orders\n \n left join order_items_summary on orders.order_id = order_items_summary.order_id\n)\n\nselect * from compute_booleans", + "access": "protected", + "original_file_path": "models/marts/orders.sql", + "group": None, + "patch_path": "jaffle_shop://models/marts/orders.yml", + "build_path": None, + "extra_ctes": [], + "fqn": ["jaffle_shop", "marts", "orders"], + "language": "sql", + "extra_ctes_injected": True, + "checksum": { + "name": "sha256", + "checksum": "82065db130ac94225e37c84233aba8621ccab7b2317b8d6cf01e86471cbb19a3", + }, + "path": "marts/orders.sql", + "unrendered_config": {"materialized": "table"}, + "deprecation_date": None, + "resource_type": "model", + "relation_name": "`dbt-tutorial-347100`.`dbt_beto`.`orders`", + "compiled_path": "target/compiled/jaffle_shop/models/marts/orders.sql", + "children": [ + "model.jaffle_shop.customers", + "semantic_model.jaffle_shop.orders", + "test.jaffle_shop.not_null_orders_order_id.cf6c17daed", + "test.jaffle_shop.relationships_orders_customer_id__customer_id__ref_stg_customers_.918495ce16", + "test.jaffle_shop.unique_orders_order_id.fed79b3a6e", + ], + "refs": [ + {"name": "stg_orders", "package": None, "version": None}, + {"name": "order_items", "package": None, "version": None}, + ], + "latest_version": None, + "sources": [], + "alias": "orders", + "version": None, + "compiled": True, + "created_at": 1702514525.4792378, + "compiled_code": "with \n\norders as (\n \n select * from `dbt-tutorial-347100`.`dbt_beto`.`stg_orders`\n\n),\n\norder_items_table as (\n \n select * from `dbt-tutorial-347100`.`dbt_beto`.`order_items`\n\n),\n\norder_items_summary as (\n\n select\n\n order_items.order_id,\n\n sum(supply_cost) as order_cost,\n sum(is_food_item) as count_food_items,\n sum(is_drink_item) as count_drink_items\n\n\n from order_items_table as order_items\n\n group by 1\n\n),\n\n\ncompute_booleans as (\n select\n\n orders.*,\n count_food_items > 0 as is_food_order,\n count_drink_items > 0 as is_drink_order,\n order_cost\n\n from orders\n \n left join order_items_summary on orders.order_id = order_items_summary.order_id\n)\n\nselect * from compute_booleans", + "constraints": [], + "depends_on": { + "macros": [], + "nodes": ["model.jaffle_shop.stg_orders", "model.jaffle_shop.order_items"], }, - "unrendered_config": {"materialized": "view"}, - "resource_type": "model", - "path": "slack/messages_channels.sql", - "extra_ctes": [], - "package_name": "superset_examples", - "alias": "messages_channels", - "relation_name": '"examples_dev"."public"."messages_channels"', + }, + { + "unique_id": "model.jaffle_shop.metricflow_time_spine", + "description": "", + "tags": [], + "columns": [], + "schema": "dbt_beto", + "meta": {}, + "database": "dbt-tutorial-347100", "config": { "enabled": True, "alias": None, @@ -59,137 +1135,228 @@ "database": None, "tags": [], "meta": {}, - "materialized": "view", + "group": None, + "materialized": "table", + "incremental_strategy": None, "persist_docs": {}, "quoting": {}, "column_types": {}, "full_refresh": None, + "unique_key": None, "on_schema_change": "ignore", + "on_configuration_change": "apply", + "grants": {}, + "packages": [], + "docs": {"show": True, "node_color": None}, + "contract": {"enforced": False}, "post-hook": [], "pre-hook": [], }, - "patch_path": None, - "compiled_sql": ( - "SELECT messages.ts, channels.name, messages.text " - 'FROM "examples_dev"."public"."messages" messages ' - 'JOIN "examples_dev"."public"."channels" channels ' - "ON messages.channel_id = channels.id" - ), - "extra_ctes_injected": True, + "name": "metricflow_time_spine", "deferred": False, - "root_path": "/Users/beto/Projects/dbt-examples/superset_examples", - "original_file_path": "models/slack/messages_channels.sql", - "refs": [], - "fqn": ["superset_examples", "slack", "messages_channels"], - "raw_sql": ( - "SELECT messages.ts, channels.name, messages.text " - "FROM {{ source ('public', 'messages') }} messages " - "JOIN {{ source ('public', 'channels') }} channels " - "ON messages.channel_id = channels.id" - ), + "contract": {"enforced": False, "checksum": None}, + "metrics": [], + "docs": {"show": True, "node_color": None}, + "package_name": "jaffle_shop", + "raw_code": "-- metricflow_time_spine.sql\nwith \n\ndays as (\n \n --for BQ adapters use \"DATE('01/01/2000','mm/dd/yyyy')\"\n {{ dbt_date.get_base_dates(n_dateparts=365*10, datepart=\"day\") }}\n\n),\n\ncast_to_date as (\n\n select \n cast(date_day as date) as date_day\n \n from days\n\n)\n\nselect * from cast_to_date", + "access": "protected", + "original_file_path": "models/marts/metricflow_time_spine.sql", + "group": None, + "patch_path": None, "build_path": None, - "sources": [["public", "channels"], ["public", "messages"]], + "extra_ctes": [], + "fqn": ["jaffle_shop", "marts", "metricflow_time_spine"], + "language": "sql", + "extra_ctes_injected": True, "checksum": { "name": "sha256", - "checksum": "b4ce232b28280daa522b37e12c36b67911e2a98456b8a3b99440075ec5564609", + "checksum": "2c46f934140af8bb4e9f5b66b9764dab4e6830cd5c6358e66ab51d70238f60e6", }, - "docs": {"show": True}, - "compiled_path": "target/compiled/superset_examples/models/slack/messages_channels.sql", + "path": "marts/metricflow_time_spine.sql", + "unrendered_config": {"materialized": "table"}, + "deprecation_date": None, + "resource_type": "model", + "relation_name": "`dbt-tutorial-347100`.`dbt_beto`.`metricflow_time_spine`", + "compiled_path": "target/compiled/jaffle_shop/models/marts/metricflow_time_spine.sql", + "children": [], + "refs": [], + "latest_version": None, + "sources": [], + "alias": "metricflow_time_spine", + "version": None, "compiled": True, + "created_at": 1702514525.26042, + "compiled_code": "-- metricflow_time_spine.sql\nwith \n\ndays as (\n \n --for BQ adapters use \"DATE('01/01/2000','mm/dd/yyyy')\"\n \n with date_spine as\n(\n\n \n\n\n\n\n\nwith rawdata as (\n\n \n\n \n\n with p as (\n select 0 as generated_number union all select 1\n ), unioned as (\n\n select\n\n \n p0.generated_number * power(2, 0)\n + \n \n p1.generated_number * power(2, 1)\n + \n \n p2.generated_number * power(2, 2)\n + \n \n p3.generated_number * power(2, 3)\n + \n \n p4.generated_number * power(2, 4)\n + \n \n p5.generated_number * power(2, 5)\n + \n \n p6.generated_number * power(2, 6)\n + \n \n p7.generated_number * power(2, 7)\n + \n \n p8.generated_number * power(2, 8)\n + \n \n p9.generated_number * power(2, 9)\n + \n \n p10.generated_number * power(2, 10)\n + \n \n p11.generated_number * power(2, 11)\n \n \n + 1\n as generated_number\n\n from\n\n \n p as p0\n cross join \n \n p as p1\n cross join \n \n p as p2\n cross join \n \n p as p3\n cross join \n \n p as p4\n cross join \n \n p as p5\n cross join \n \n p as p6\n cross join \n \n p as p7\n cross join \n \n p as p8\n cross join \n \n p as p9\n cross join \n \n p as p10\n cross join \n \n p as p11\n \n \n\n )\n\n select *\n from unioned\n where generated_number <= 3651\n order by generated_number\n\n\n\n),\n\nall_periods as (\n\n select (\n \n\n datetime_add(\n cast( \n\n datetime_add(\n cast( cast(timestamp(datetime(current_timestamp(), 'America/Los_Angeles')) as date) as datetime),\n interval -3650 day\n )\n\n as datetime),\n interval row_number() over (order by 1) - 1 day\n )\n\n\n ) as date_day\n from rawdata\n\n),\n\nfiltered as (\n\n select *\n from all_periods\n where date_day <= cast(\n\n datetime_add(\n cast( cast(timestamp(datetime(current_timestamp(), 'America/Los_Angeles')) as date) as datetime),\n interval 1 day\n )\n\n as date)\n\n)\n\nselect * from filtered\n\n\n\n)\nselect\n cast(d.date_day as TIMESTAMP) as date_day\nfrom\n date_spine d\n\n\n\n),\n\ncast_to_date as (\n\n select \n cast(date_day as date) as date_day\n \n from days\n\n)\n\nselect * from cast_to_date", + "constraints": [], + "depends_on": {"macros": ["macro.dbt_date.get_base_dates"], "nodes": []}, }, -] - -dbt_core_metrics = [ { - "label": "", - "sql": "*", - "depends_on": ["model.superset_examples.messages_channels"], - "meta": {}, + "unique_id": "model.jaffle_shop.order_items", "description": "", - "name": "cnt", - "type": "count", - "filters": [], - "unique_id": "metric.superset_examples.cnt", - "created_at": 1642630986.1942852, - "package_name": "superset_examples", - "sources": [], - "root_path": "/Users/beto/Projects/dbt-examples/superset_examples", - "path": "slack/schema.yml", - "resource_type": "metric", - "original_file_path": "models/slack/schema.yml", - "model": "ref('messages_channels')", - "timestamp": None, - "fqn": ["superset_examples", "slack", "cnt"], - "time_grains": [], "tags": [], - "refs": [["messages_channels"]], - "dimensions": [], + "columns": [], + "schema": "dbt_beto", + "meta": {}, + "database": "dbt-tutorial-347100", + "config": { + "enabled": True, + "alias": None, + "schema": None, + "database": None, + "tags": [], + "meta": {}, + "group": None, + "materialized": "table", + "incremental_strategy": None, + "persist_docs": {}, + "quoting": {}, + "column_types": {}, + "full_refresh": None, + "unique_key": None, + "on_schema_change": "ignore", + "on_configuration_change": "apply", + "grants": {}, + "packages": [], + "docs": {"show": True, "node_color": None}, + "contract": {"enforced": False}, + "post-hook": [], + "pre-hook": [], + }, + "name": "order_items", + "deferred": False, + "contract": {"enforced": False, "checksum": None}, + "metrics": [], + "docs": {"show": True, "node_color": None}, + "package_name": "jaffle_shop", + "raw_code": "with \n\norder_items as (\n\n select * from {{ ref('stg_order_items') }}\n\n),\n\n\norders as (\n \n select * from {{ ref('stg_orders')}}\n),\n\nproducts as (\n\n select * from {{ ref('stg_products') }}\n\n),\n\nsupplies as (\n\n select * from {{ ref('stg_supplies') }}\n\n),\n\norder_supplies_summary as (\n\n select\n product_id,\n sum(supply_cost) as supply_cost\n\n from supplies\n\ngroup by 1\n),\n\njoined as (\n select\n order_items.*,\n products.product_price,\n order_supplies_summary.supply_cost,\n products.is_food_item,\n products.is_drink_item,\n orders.ordered_at\n\n from order_items\n\n left join orders on order_items.order_id = orders.order_id\n \n left join products on order_items.product_id = products.product_id\n \n left join order_supplies_summary on order_items.product_id = order_supplies_summary.product_id\n \n)\n\nselect * from joined", + "access": "protected", + "original_file_path": "models/marts/order_items.sql", + "group": None, + "patch_path": None, + "build_path": None, + "extra_ctes": [], + "fqn": ["jaffle_shop", "marts", "order_items"], + "language": "sql", + "extra_ctes_injected": True, + "checksum": { + "name": "sha256", + "checksum": "6391e10e8c9765f055e2e3736e0bc3bb7794d4fa95f506ee275229968aab231a", + }, + "path": "marts/order_items.sql", + "unrendered_config": {"materialized": "table"}, + "deprecation_date": None, + "resource_type": "model", + "relation_name": "`dbt-tutorial-347100`.`dbt_beto`.`order_items`", + "compiled_path": "target/compiled/jaffle_shop/models/marts/order_items.sql", + "children": [ + "model.jaffle_shop.customers", + "model.jaffle_shop.orders", + "semantic_model.jaffle_shop.order_item", + ], + "refs": [ + {"name": "stg_order_items", "package": None, "version": None}, + {"name": "stg_orders", "package": None, "version": None}, + {"name": "stg_products", "package": None, "version": None}, + {"name": "stg_supplies", "package": None, "version": None}, + ], + "latest_version": None, + "sources": [], + "alias": "order_items", + "version": None, + "compiled": True, + "created_at": 1702514525.303211, + "compiled_code": "with \n\norder_items as (\n\n select * from `dbt-tutorial-347100`.`dbt_beto`.`stg_order_items`\n\n),\n\n\norders as (\n \n select * from `dbt-tutorial-347100`.`dbt_beto`.`stg_orders`\n),\n\nproducts as (\n\n select * from `dbt-tutorial-347100`.`dbt_beto`.`stg_products`\n\n),\n\nsupplies as (\n\n select * from `dbt-tutorial-347100`.`dbt_beto`.`stg_supplies`\n\n),\n\norder_supplies_summary as (\n\n select\n product_id,\n sum(supply_cost) as supply_cost\n\n from supplies\n\n group by 1\n),\n\njoined as (\n select\n order_items.*,\n products.product_price,\n order_supplies_summary.supply_cost,\n products.is_food_item,\n products.is_drink_item,\n orders.ordered_at\n\n from order_items\n\n left join orders on order_items.order_id = orders.order_id\n \n left join products on order_items.product_id = products.product_id\n \n left join order_supplies_summary on order_items.product_id = order_supplies_summary.product_id\n \n)\n\nselect * from joined", + "constraints": [], + "depends_on": { + "macros": [], + "nodes": [ + "model.jaffle_shop.stg_order_items", + "model.jaffle_shop.stg_orders", + "model.jaffle_shop.stg_products", + "model.jaffle_shop.stg_supplies", + ], + }, }, ] -superset_metrics = { - "model.superset_examples.messages_channels": [ + +superset_metricflow_metrics = { + "model.jaffle_shop.orders": [ { - "description": "", - "expression": "COUNT(*)", - "extra": "{}", - "metric_name": "cnt", - "metric_type": "count", - "verbose_name": "", + "expression": "COUNT(DISTINCT customer_id)", + "metric_name": "customers_with_orders", + "metric_type": "simple", + "verbose_name": "customers_with_orders", + "description": "Distict count of customers placing orders", + }, + { + "expression": "SUM(order_total)", + "metric_name": "order_total", + "metric_type": "simple", + "verbose_name": "order_total", + "description": "Sum of total order amonunt. Includes tax + revenue.", + }, + { + "expression": "SUM(CASE WHEN order_total >= 20 THEN 1 END)", + "metric_name": "large_order", + "metric_type": "simple", + "verbose_name": "large_order", + "description": "Count of orders with order total over 20.", + }, + { + "expression": "SUM(1)", + "metric_name": "orders", + "metric_type": "simple", + "verbose_name": "orders", + "description": "Count of orders.", + }, + { + "expression": "SUM(CASE WHEN is_food_order = TRUE THEN 1 END)", + "metric_name": "food_orders", + "metric_type": "simple", + "verbose_name": "food_orders", + "description": "Count of orders that contain food order items", + }, + { + "expression": "SUM(order_cost)", + "metric_name": "order_cost", + "metric_type": "simple", + "verbose_name": "order_cost", + "description": "Sum of cost for each order item.", + }, + ], + "model.jaffle_shop.order_items": [ + { + "expression": "SUM(product_price)", + "metric_name": "revenue", + "metric_type": "simple", + "verbose_name": "revenue", + "description": "Sum of the product revenue for each order item. Excludes tax.", + }, + { + "expression": "SUM(CASE WHEN is_food_item = 1 THEN product_price ELSE 0 END)", + "metric_name": "food_revenue", + "metric_type": "simple", + "verbose_name": "food_revenue", + "description": "The revenue from food in each order", + }, + { + "expression": "CAST(SUM(CASE WHEN is_food_item = 1 THEN product_price ELSE 0 END) AS DOUBLE) / CAST(NULLIF(SUM(product_price), 0) AS DOUBLE)", + "metric_name": "food_revenue_pct", + "metric_type": "ratio", + "verbose_name": "food_revenue_pct", + "description": "The % of order revenue from food.", + }, + { + "expression": "SUM(product_price)", + "metric_name": "cumulative_revenue", + "metric_type": "cumulative", + "verbose_name": "cumulative_revenue", + "description": "The cumulative revenue for all orders.", }, ], } -dbt_cloud_models = [ - { - "database": "examples_dev", - "description": "", - "meta": {}, - "name": "messages_channels", - "schema": "public", - "unique_id": "model.superset_examples.messages_channels", - }, - { - "database": "some_other_table", - "description": "", - "meta": {}, - "name": "some_other_table", - "schema": "public", - "unique_id": "model.superset_examples.some_other_table", - }, -] - -dbt_cloud_metrics = [ - { - "depends_on": ["model.superset_examples.messages_channels"], - "description": "", - "filters": [], - "label": "", - "meta": {}, - "name": "cnt", - "sql": "*", - "type": "count", - "unique_id": "metric.superset_examples.cnt", - }, - { - "depends_on": ["a", "b"], - "description": "", - "filters": [], - "label": "", - "meta": {}, - "name": "multiple parents", - "sql": "*", - "type": "count", - "unique_id": "c", - }, -] - -dbt_metricflow_metrics = [ - {"name": "a", "type": "Simple", "description": "The simplest metric"}, - {"name": "b", "type": "derived", "description": "Too complex for Superset"}, - {"name": "c", "type": "derived", "description": "Multiple models"}, -] - def test_dbt_core(mocker: MockerFixture, fs: FakeFilesystem) -> None: """ @@ -200,7 +1367,7 @@ def test_dbt_core(mocker: MockerFixture, fs: FakeFilesystem) -> None: manifest = root / "default/target/manifest.json" fs.create_file(manifest, contents=manifest_contents) profiles = root / ".dbt/profiles.yml" - fs.create_file(profiles) + fs.create_file(profiles, contents=profiles_contents) exposures = root / "models/exposures.yml" fs.create_file(exposures) @@ -231,6 +1398,10 @@ def test_dbt_core(mocker: MockerFixture, fs: FakeFilesystem) -> None: str(profiles), "--exposures", str(exposures), + "--project", + "default", + "--target", + "dev", ], catch_exceptions=False, ) @@ -240,7 +1411,7 @@ def test_dbt_core(mocker: MockerFixture, fs: FakeFilesystem) -> None: profiles, "default", "default", - None, + "dev", False, False, "", @@ -264,6 +1435,187 @@ def test_dbt_core(mocker: MockerFixture, fs: FakeFilesystem) -> None: ) +def test_dbt_core_metricflow(mocker: MockerFixture, fs: FakeFilesystem) -> None: + """ + Test the ``dbt-core`` command with Metricflow metrics. + """ + root = Path("/path/to/root") + fs.create_dir(root) + manifest = root / "default/target/manifest.json" + fs.create_file(manifest, contents=manifest_metricflow_contents) + profiles = root / ".dbt/profiles.yml" + fs.create_file(profiles, contents=profiles_contents) + exposures = root / "models/exposures.yml" + fs.create_file(exposures) + + SupersetClient = mocker.patch( + "preset_cli.cli.superset.sync.dbt.command.SupersetClient", + ) + client = SupersetClient() + mocker.patch("preset_cli.cli.superset.main.UsernamePasswordAuth") + sync_database = mocker.patch( + "preset_cli.cli.superset.sync.dbt.command.sync_database", + ) + mocker.patch( + "preset_cli.cli.superset.sync.dbt.command.subprocess.run", + side_effect=[ + mocker.MagicMock( + stdout="""✔ Success 🦄 - query completed after 0.28 seconds +🔎 SQL (remove --explain to see data or add --show-dataflow-plan to see the generated dataflow plan): +SELECT + COUNT(DISTINCT customer_id) AS customers_with_orders +FROM `dbt-tutorial-347100`.`dbt_beto`.`orders` orders_src_3""", + ), + mocker.MagicMock( + stdout="""✔ Success 🦄 - query completed after 0.37 seconds +🔎 SQL (remove --explain to see data or add --show-dataflow-plan to see the generated dataflow plan): +SELECT + COUNT(DISTINCT customers_with_orders) AS new_customer +FROM ( + SELECT + customers_src_0.customer_type AS customer__customer_type + , orders_src_3.customer_id AS customers_with_orders + FROM `dbt-tutorial-347100`.`dbt_beto`.`orders` orders_src_3 + LEFT OUTER JOIN + `dbt-tutorial-347100`.`dbt_beto`.`customers` customers_src_0 + ON + orders_src_3.customer_id = customers_src_0.customer_id +) subq_7 +WHERE customer__customer_type = 'new'""", + ), + mocker.MagicMock( + stdout="""✔ Success 🦄 - query completed after 0.29 seconds +🔎 SQL (remove --explain to see data or add --show-dataflow-plan to see the generated dataflow plan): +SELECT + SUM(order_total) AS order_total +FROM `dbt-tutorial-347100`.`dbt_beto`.`orders` orders_src_3""", + ), + mocker.MagicMock( + stdout="""✔ Success 🦄 - query completed after 0.35 seconds +🔎 SQL (remove --explain to see data or add --show-dataflow-plan to see the generated dataflow plan): +SELECT + SUM(order_count) AS large_order +FROM ( + SELECT + order_total AS order_id__order_total_dim + , 1 AS order_count + FROM `dbt-tutorial-347100`.`dbt_beto`.`orders` orders_src_3 +) subq_2 +WHERE order_id__order_total_dim >= 20""", + ), + mocker.MagicMock( + stdout="""✔ Success 🦄 - query completed after 0.28 seconds +🔎 SQL (remove --explain to see data or add --show-dataflow-plan to see the generated dataflow plan): +SELECT + SUM(1) AS orders +FROM `dbt-tutorial-347100`.`dbt_beto`.`orders` orders_src_3""", + ), + mocker.MagicMock( + stdout="""✔ Success 🦄 - query completed after 0.31 seconds +🔎 SQL (remove --explain to see data or add --show-dataflow-plan to see the generated dataflow plan): +SELECT + SUM(order_count) AS food_orders +FROM ( + SELECT + is_food_order AS order_id__is_food_order + , 1 AS order_count + FROM `dbt-tutorial-347100`.`dbt_beto`.`orders` orders_src_3 +) subq_2 +WHERE order_id__is_food_order = true""", + ), + mocker.MagicMock( + stdout="""✔ Success 🦄 - query completed after 0.24 seconds +🔎 SQL (remove --explain to see data or add --show-dataflow-plan to see the generated dataflow plan): +SELECT + SUM(product_price) AS revenue +FROM `dbt-tutorial-347100`.`dbt_beto`.`order_items` order_item_src_2""", + ), + mocker.MagicMock( + stdout="""✔ Success 🦄 - query completed after 0.28 seconds +🔎 SQL (remove --explain to see data or add --show-dataflow-plan to see the generated dataflow plan): +SELECT + SUM(order_cost) AS order_cost +FROM `dbt-tutorial-347100`.`dbt_beto`.`orders` orders_src_3""", + ), + CalledProcessError(1, cmd="mf", output="Error occurred"), + mocker.MagicMock( + stdout="""✔ Success 🦄 - query completed after 0.26 seconds +🔎 SQL (remove --explain to see data or add --show-dataflow-plan to see the generated dataflow plan): +SELECT + SUM(case when is_food_item = 1 then product_price else 0 end) AS food_revenue +FROM `dbt-tutorial-347100`.`dbt_beto`.`order_items` order_item_src_2""", + ), + mocker.MagicMock( + stdout="""✔ Success 🦄 - query completed after 0.31 seconds +🔎 SQL (remove --explain to see data or add --show-dataflow-plan to see the generated dataflow plan): +SELECT + CAST(SUM(case when is_food_item = 1 then product_price else 0 end) AS FLOAT64) / CAST(NULLIF(SUM(product_price), 0) AS FLOAT64) AS food_revenue_pct +FROM `dbt-tutorial-347100`.`dbt_beto`.`order_items` order_item_src_2""", + ), + CalledProcessError(1, cmd="mf", output="Error occurred"), + mocker.MagicMock( + stdout="""✔ Success 🦄 - query completed after 0.43 seconds +🔎 SQL (remove --explain to see data or add --show-dataflow-plan to see the generated dataflow plan): +SELECT + revenue - cost AS order_gross_profit +FROM ( + SELECT + subq_4.revenue AS revenue + , subq_9.cost AS cost + FROM ( + SELECT + SUM(product_price) AS revenue + FROM `dbt-tutorial-347100`.`dbt_beto`.`order_items` order_item_src_2 + ) subq_4 + CROSS JOIN ( + SELECT + SUM(order_cost) AS cost + FROM `dbt-tutorial-347100`.`dbt_beto`.`orders` orders_src_3 + ) subq_9 +) subq_10""", + ), + mocker.MagicMock( + stdout="""✔ Success 🦄 - query completed after 0.30 seconds +🔎 SQL (remove --explain to see data or add --show-dataflow-plan to see the generated dataflow plan): +SELECT + SUM(product_price) AS cumulative_revenue +FROM `dbt-tutorial-347100`.`dbt_beto`.`order_items` order_item_src_2""", + ), + ], + ) + + runner = CliRunner() + result = runner.invoke( + superset_cli, + [ + "https://superset.example.org/", + "sync", + "dbt-core", + str(manifest), + "--profiles", + str(profiles), + "--exposures", + str(exposures), + "--project", + "default", + "--target", + "dev", + ], + catch_exceptions=False, + ) + assert result.exit_code == 0 + sync_database.assert_called_with( + client, + profiles, + "default", + "default", + "dev", + False, + False, + "", + ) + + def test_dbt_core_preserve_metadata( mocker: MockerFixture, fs: FakeFilesystem, @@ -276,7 +1628,7 @@ def test_dbt_core_preserve_metadata( manifest = root / "default/target/manifest.json" fs.create_file(manifest, contents=manifest_contents) profiles = root / ".dbt/profiles.yml" - fs.create_file(profiles) + fs.create_file(profiles, contents=profiles_contents) exposures = root / "models/exposures.yml" fs.create_file(exposures) @@ -308,6 +1660,10 @@ def test_dbt_core_preserve_metadata( "--exposures", str(exposures), "--preserve-metadata", + "--project", + "default", + "--target", + "dev", ], catch_exceptions=False, ) @@ -317,7 +1673,7 @@ def test_dbt_core_preserve_metadata( profiles, "default", "default", - None, + "dev", False, False, "", @@ -353,7 +1709,7 @@ def test_dbt_core_preserve_columns( manifest = root / "default/target/manifest.json" fs.create_file(manifest, contents=manifest_contents) profiles = root / ".dbt/profiles.yml" - fs.create_file(profiles) + fs.create_file(profiles, contents=profiles_contents) SupersetClient = mocker.patch( "preset_cli.cli.superset.sync.dbt.command.SupersetClient", @@ -378,6 +1734,10 @@ def test_dbt_core_preserve_columns( "--profiles", str(profiles), "--preserve-columns", + "--project", + "default", + "--target", + "dev", ], catch_exceptions=False, ) @@ -387,7 +1747,7 @@ def test_dbt_core_preserve_columns( profiles, "default", "default", - None, + "dev", False, False, "", @@ -417,7 +1777,7 @@ def test_dbt_core_merge_metadata( manifest = root / "default/target/manifest.json" fs.create_file(manifest, contents=manifest_contents) profiles = root / ".dbt/profiles.yml" - fs.create_file(profiles) + fs.create_file(profiles, contents=profiles_contents) exposures = root / "models/exposures.yml" fs.create_file(exposures) @@ -449,6 +1809,10 @@ def test_dbt_core_merge_metadata( "--exposures", str(exposures), "--merge-metadata", + "--project", + "default", + "--target", + "dev", ], catch_exceptions=False, ) @@ -458,7 +1822,7 @@ def test_dbt_core_merge_metadata( profiles, "default", "default", - None, + "dev", False, False, "", @@ -495,7 +1859,7 @@ def test_dbt_core_preserve_and_merge( manifest = root / "default/target/manifest.json" fs.create_file(manifest, contents=manifest_contents) profiles = root / ".dbt/profiles.yml" - fs.create_file(profiles) + fs.create_file(profiles, contents=profiles_contents) exposures = root / "models/exposures.yml" fs.create_file(exposures) @@ -515,6 +1879,10 @@ def test_dbt_core_preserve_and_merge( str(exposures), "--preserve-metadata", "--merge-metadata", + "--project", + "default", + "--target", + "dev", ], catch_exceptions=False, ) @@ -541,7 +1909,7 @@ def test_dbt_core_dbt_project(mocker: MockerFixture, fs: FakeFilesystem) -> None manifest = root / "default/target/manifest.json" fs.create_file(manifest, contents=manifest_contents) profiles = root / ".dbt/profiles.yml" - fs.create_file(profiles) + fs.create_file(profiles, contents=profiles_contents) SupersetClient = mocker.patch( "preset_cli.cli.superset.sync.dbt.command.SupersetClient", @@ -562,6 +1930,8 @@ def test_dbt_core_dbt_project(mocker: MockerFixture, fs: FakeFilesystem) -> None str(dbt_project), "--profiles", str(profiles), + "--target", + "dev", ], catch_exceptions=False, ) @@ -571,7 +1941,7 @@ def test_dbt_core_dbt_project(mocker: MockerFixture, fs: FakeFilesystem) -> None profiles, "my_project", "default", - None, + "dev", False, False, "", @@ -585,7 +1955,7 @@ def test_dbt_core_invalid_argument(mocker: MockerFixture, fs: FakeFilesystem) -> root = Path("/path/to/root") fs.create_dir(root) profiles = root / ".dbt/profiles.yml" - fs.create_file(profiles) + fs.create_file(profiles, contents=profiles_contents) wrong = root / "wrong" fs.create_file(wrong) @@ -622,7 +1992,7 @@ def test_dbt(mocker: MockerFixture, fs: FakeFilesystem) -> None: manifest = root / "default/target/manifest.json" fs.create_file(manifest, contents=manifest_contents) profiles = root / ".dbt/profiles.yml" - fs.create_file(profiles) + fs.create_file(profiles, contents=profiles_contents) exposures = root / "models/exposures.yml" fs.create_file(exposures) @@ -653,6 +2023,10 @@ def test_dbt(mocker: MockerFixture, fs: FakeFilesystem) -> None: str(profiles), "--exposures", str(exposures), + "--project", + "default", + "--target", + "dev", ], catch_exceptions=False, ) @@ -662,7 +2036,7 @@ def test_dbt(mocker: MockerFixture, fs: FakeFilesystem) -> None: profiles, "default", "default", - None, + "dev", False, False, "", @@ -766,7 +2140,7 @@ def test_dbt_core_no_exposures(mocker: MockerFixture, fs: FakeFilesystem) -> Non manifest = root / "default/target/manifest.json" fs.create_file(manifest, contents=manifest_contents) profiles = root / ".dbt/profiles.yml" - fs.create_file(profiles) + fs.create_file(profiles, contents=profiles_contents) mocker.patch("preset_cli.cli.superset.sync.dbt.command.SupersetClient") mocker.patch("preset_cli.cli.superset.main.UsernamePasswordAuth") @@ -786,6 +2160,10 @@ def test_dbt_core_no_exposures(mocker: MockerFixture, fs: FakeFilesystem) -> Non str(manifest), "--profiles", str(profiles), + "--project", + "default", + "--target", + "dev", ], catch_exceptions=False, ) @@ -802,7 +2180,7 @@ def test_dbt_core_default_profile(mocker: MockerFixture, fs: FakeFilesystem) -> manifest = root / "default/target/manifest.json" fs.create_file(manifest, contents=manifest_contents) profiles = root / ".dbt/profiles.yml" - fs.create_file(profiles) + fs.create_file(profiles, contents=profiles_contents) exposures = root / "models/exposures.yml" fs.create_file(exposures) @@ -830,6 +2208,10 @@ def test_dbt_core_default_profile(mocker: MockerFixture, fs: FakeFilesystem) -> str(manifest), "--exposures", str(exposures), + "--project", + "default", + "--target", + "dev", ], catch_exceptions=False, ) @@ -839,7 +2221,7 @@ def test_dbt_core_default_profile(mocker: MockerFixture, fs: FakeFilesystem) -> profiles, "default", "default", - None, + "dev", False, False, "", @@ -855,7 +2237,7 @@ def test_dbt_core_no_database(mocker: MockerFixture, fs: FakeFilesystem) -> None manifest = root / "default/target/manifest.json" fs.create_file(manifest, contents=manifest_contents) profiles = root / ".dbt/profiles.yml" - fs.create_file(profiles) + fs.create_file(profiles, contents=profiles_contents) exposures = root / "models/exposures.yml" fs.create_file(exposures) @@ -878,6 +2260,10 @@ def test_dbt_core_no_database(mocker: MockerFixture, fs: FakeFilesystem) -> None str(profiles), "--exposures", str(exposures), + "--project", + "default", + "--target", + "dev", ], catch_exceptions=False, ) @@ -908,7 +2294,7 @@ def test_dbt_core_disallow_edits_superset( manifest = root / "default/target/manifest.json" fs.create_file(manifest, contents=manifest_contents) profiles = root / ".dbt/profiles.yml" - fs.create_file(profiles) + fs.create_file(profiles, contents=profiles_contents) SupersetClient = mocker.patch( "preset_cli.cli.superset.sync.dbt.command.SupersetClient", @@ -933,6 +2319,8 @@ def test_dbt_core_disallow_edits_superset( "--profiles", str(profiles), "--disallow-edits", + "--target", + "dev", ], catch_exceptions=False, ) @@ -949,7 +2337,7 @@ def test_dbt_core_disallow_edits_superset( profiles, "my_project", "default", - None, + "dev", False, True, "", @@ -1535,7 +2923,7 @@ def test_dbt_core_exposures_only(mocker: MockerFixture, fs: FakeFilesystem) -> N manifest = root / "default/target/manifest.json" fs.create_file(manifest, contents=manifest_contents) profiles = root / ".dbt/profiles.yml" - fs.create_file(profiles) + fs.create_file(profiles, contents=profiles_contents) exposures = root / "models/exposures.yml" fs.create_file(exposures) @@ -1571,6 +2959,10 @@ def test_dbt_core_exposures_only(mocker: MockerFixture, fs: FakeFilesystem) -> N "--exposures", str(exposures), "--exposures-only", + "--project", + "default", + "--target", + "dev", ], catch_exceptions=False, ) diff --git a/tests/cli/superset/sync/dbt/metrics_test.py b/tests/cli/superset/sync/dbt/metrics_test.py index 4ef42073..813b3039 100644 --- a/tests/cli/superset/sync/dbt/metrics_test.py +++ b/tests/cli/superset/sync/dbt/metrics_test.py @@ -104,6 +104,10 @@ def test_get_metric_expression() -> None: get_metric_expression("five", metrics) assert str(excinfo.value) == "Invalid metric five" + with pytest.raises(Exception) as excinfo: + get_metric_expression("six", {"six": {}}) # type: ignore + assert str(excinfo.value) == "Unable to generate metric expression from: {}" + def test_get_metric_expression_new_schema() -> None: """