model2data 1.13.0__tar.gz → 1.14.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {model2data-1.13.0/model2data.egg-info → model2data-1.14.0}/PKG-INFO +7 -3
- {model2data-1.13.0 → model2data-1.14.0}/README.md +6 -2
- {model2data-1.13.0 → model2data-1.14.0}/README_PYPI.md +6 -2
- {model2data-1.13.0 → model2data-1.14.0}/model2data/cli.py +56 -7
- {model2data-1.13.0 → model2data-1.14.0}/model2data/guide/tune.md +4 -2
- {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/__init__.py +5 -0
- model2data-1.14.0/model2data/metrics/lightdash.py +597 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/spec/PUBLISHING.md +0 -2
- {model2data-1.13.0 → model2data-1.14.0}/model2data/spec/metrics/README.md +3 -2
- {model2data-1.13.0 → model2data-1.14.0/model2data.egg-info}/PKG-INFO +7 -3
- {model2data-1.13.0 → model2data-1.14.0}/model2data.egg-info/SOURCES.txt +2 -0
- {model2data-1.13.0 → model2data-1.14.0}/pyproject.toml +1 -1
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_cli.py +57 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_dbt.py +69 -0
- model2data-1.14.0/tests/test_metrics_lightdash.py +645 -0
- {model2data-1.13.0 → model2data-1.14.0}/LICENSE +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/LICENSE +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/VENDORED.md +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/base.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/column.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/enum.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/expression.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/index.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/note.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/project.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/reference.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/sticky_note.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/table.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/table_group.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/classes/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/constants.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/database.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/column.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/common.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/enum.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/generic.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/index.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/project.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/records.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/reference.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/sticky_note.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/table.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/table_group.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/table_partial.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/exceptions.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/parser/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/parser/blueprints.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/parser/parser.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/base.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/column.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/enum.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/expression.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/index.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/note.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/project.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/reference.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/renderer.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/sticky_note.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/table.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/table_group.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/utils.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/column.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/enum.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/expression.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/index.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/note.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/reference.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/renderer.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/table.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/utils.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/tools.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/hint_tests.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/naming.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/project.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/templates/dbt_project.yml.jinja +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/templates/hint_macros/model2data_hint_tests.sql +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/templates/hint_macros/model2data_when_tests.sql +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/templates/history_macros/model2data_history_tests.sql +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/templates/macros/generate_schema_name.sql +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/templates/profiles.yml.jinja +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/tests.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/defects/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/defects/apply.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/defects/checks.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/defects/presets.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/defects/report.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/core.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/days.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/faker.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/hints.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/history.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/kinds.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/options.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/relationships.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/timeline.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/when.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/guide/setup.md +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/guide/triage.md +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/check.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/columns.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/dbt.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/expression.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/graph.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/infer.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/ossie.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/reader.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/semantic.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/sql.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/types.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/values.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/model/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/model/_yaml.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/model/dbml.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/model/document.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/model/dump.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/model/engine.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/model/errors.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/model/reader.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/model/types.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/model/validate.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/output.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/parse/__init__.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/parse/dbml.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/spec/README.md +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/spec/examples/coffee_webshop.metrics.yml +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/spec/examples/coffee_webshop.model2data.yml +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/spec/metrics/metrics.schema.json +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/spec/model.schema.json +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data/utils.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data.egg-info/dependency_links.txt +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data.egg-info/entry_points.txt +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data.egg-info/requires.txt +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/model2data.egg-info/top_level.txt +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/setup.cfg +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_as_of_anchor.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_cli.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_cli_model.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_column_time_hints.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_coverage_gaps.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_days.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_dbml_parser.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_dbml_parser_fuzz.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_dbt_integration.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_dbt_naming.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_dbt_project.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_dbt_tests.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_defects.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_defects_dbt.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_defects_replay.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_defects_report.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_defects_review.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_determinism.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_distributions.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_examples_model.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_faker_name_inference.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_fast_paths.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_generation.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_guide.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_hint_tests.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_history.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_issue_lines.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_lone_country.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_expression.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_ossie.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_reader.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_semantic.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_spec.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_values.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_model.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_model_dbml.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_model_edges.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_model_messages.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_model_vocabulary.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_options.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_release_stress.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_reproducibility.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_row_identity.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_shaping.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_spec_alignment.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_spec_schema.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_table_seeds.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_timeline.py +0 -0
- {model2data-1.13.0 → model2data-1.14.0}/tests/test_when.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: model2data
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.14.0
|
|
4
4
|
Summary: Turn a data model into realistic synthetic data, a runnable dbt project and metrics with known values
|
|
5
5
|
Author: JB Analytica
|
|
6
6
|
License-Expression: MIT
|
|
@@ -131,6 +131,9 @@ orphans, nulls, invalid values, messy text, late-arriving rows. Every run with d
|
|
|
131
131
|
orders, average order value. The run writes each metric's value over the generated data to
|
|
132
132
|
`metric_values.json`, overall and per month, a dbt test per metric that must reproduce it on the
|
|
133
133
|
warehouse, and an [Apache Ossie](https://github.com/apache/ossie) semantic model under `osi/`.
|
|
134
|
+
New in 1.14.0: `--lightdash` writes the same metrics into the staging models' YAML as
|
|
135
|
+
[Lightdash](https://www.lightdash.com/) reads them, filters, joins and ratios included, so the
|
|
136
|
+
dashboard's revenue can be checked against the number the run already knows.
|
|
134
137
|
→ [Metrics with known values](https://github.com/JB-Analytica/model2data/blob/main/docs/metrics.md)
|
|
135
138
|
|
|
136
139
|
**Validate in CI.** `model2data validate` checks models and metrics files and prints GitHub
|
|
@@ -272,7 +275,7 @@ definition goes in; nothing but synthetic data comes out.
|
|
|
272
275
|
`accepted_values` fail for the right reason.
|
|
273
276
|
- **A team defining metrics once.** Write revenue in one metrics file, check every number the
|
|
274
277
|
semantic layer or dashboard shows against `metric_values.json`, let `dbt build` prove the SQL,
|
|
275
|
-
and hand the definitions on as Apache Ossie.
|
|
278
|
+
and hand the definitions on as Apache Ossie or straight to Lightdash.
|
|
276
279
|
|
|
277
280
|
## How it works
|
|
278
281
|
|
|
@@ -298,7 +301,8 @@ model (.model2data.yml or DBML) + metrics file (optional)
|
|
|
298
301
|
model's hints, table and column `description:` fields from the model, and a profile for
|
|
299
302
|
DuckDB (zero-config, file-based) or Postgres.
|
|
300
303
|
4. **Compute metrics.** With `--metrics`, computes each metric over the generated data and writes
|
|
301
|
-
its known value, a dbt test that checks it, and the Apache Ossie file
|
|
304
|
+
its known value, a dbt test that checks it, and the Apache Ossie file; with `--lightdash`,
|
|
305
|
+
Lightdash metrics and dimensions in the staging models' YAML.
|
|
302
306
|
|
|
303
307
|
---
|
|
304
308
|
|
|
@@ -84,6 +84,9 @@ orphans, nulls, invalid values, messy text, late-arriving rows. Every run with d
|
|
|
84
84
|
orders, average order value. The run writes each metric's value over the generated data to
|
|
85
85
|
`metric_values.json`, overall and per month, a dbt test per metric that must reproduce it on the
|
|
86
86
|
warehouse, and an [Apache Ossie](https://github.com/apache/ossie) semantic model under `osi/`.
|
|
87
|
+
New in 1.14.0: `--lightdash` writes the same metrics into the staging models' YAML as
|
|
88
|
+
[Lightdash](https://www.lightdash.com/) reads them, filters, joins and ratios included, so the
|
|
89
|
+
dashboard's revenue can be checked against the number the run already knows.
|
|
87
90
|
→ [Metrics with known values](docs/metrics.md)
|
|
88
91
|
|
|
89
92
|
**Validate in CI.** `model2data validate` checks models and metrics files and prints GitHub
|
|
@@ -225,7 +228,7 @@ definition goes in; nothing but synthetic data comes out.
|
|
|
225
228
|
`accepted_values` fail for the right reason.
|
|
226
229
|
- **A team defining metrics once.** Write revenue in one metrics file, check every number the
|
|
227
230
|
semantic layer or dashboard shows against `metric_values.json`, let `dbt build` prove the SQL,
|
|
228
|
-
and hand the definitions on as Apache Ossie.
|
|
231
|
+
and hand the definitions on as Apache Ossie or straight to Lightdash.
|
|
229
232
|
|
|
230
233
|
## How it works
|
|
231
234
|
|
|
@@ -281,7 +284,8 @@ flowchart LR
|
|
|
281
284
|
model's hints, table and column `description:` fields from the model, and a profile for
|
|
282
285
|
DuckDB (zero-config, file-based) or Postgres.
|
|
283
286
|
4. **Compute metrics.** With `--metrics`, computes each metric over the generated data and writes
|
|
284
|
-
its known value, a dbt test that checks it, and the Apache Ossie file
|
|
287
|
+
its known value, a dbt test that checks it, and the Apache Ossie file; with `--lightdash`,
|
|
288
|
+
Lightdash metrics and dimensions in the staging models' YAML.
|
|
285
289
|
|
|
286
290
|
---
|
|
287
291
|
|
|
@@ -84,6 +84,9 @@ orphans, nulls, invalid values, messy text, late-arriving rows. Every run with d
|
|
|
84
84
|
orders, average order value. The run writes each metric's value over the generated data to
|
|
85
85
|
`metric_values.json`, overall and per month, a dbt test per metric that must reproduce it on the
|
|
86
86
|
warehouse, and an [Apache Ossie](https://github.com/apache/ossie) semantic model under `osi/`.
|
|
87
|
+
New in 1.14.0: `--lightdash` writes the same metrics into the staging models' YAML as
|
|
88
|
+
[Lightdash](https://www.lightdash.com/) reads them, filters, joins and ratios included, so the
|
|
89
|
+
dashboard's revenue can be checked against the number the run already knows.
|
|
87
90
|
→ [Metrics with known values](https://github.com/JB-Analytica/model2data/blob/main/docs/metrics.md)
|
|
88
91
|
|
|
89
92
|
**Validate in CI.** `model2data validate` checks models and metrics files and prints GitHub
|
|
@@ -225,7 +228,7 @@ definition goes in; nothing but synthetic data comes out.
|
|
|
225
228
|
`accepted_values` fail for the right reason.
|
|
226
229
|
- **A team defining metrics once.** Write revenue in one metrics file, check every number the
|
|
227
230
|
semantic layer or dashboard shows against `metric_values.json`, let `dbt build` prove the SQL,
|
|
228
|
-
and hand the definitions on as Apache Ossie.
|
|
231
|
+
and hand the definitions on as Apache Ossie or straight to Lightdash.
|
|
229
232
|
|
|
230
233
|
## How it works
|
|
231
234
|
|
|
@@ -251,7 +254,8 @@ model (.model2data.yml or DBML) + metrics file (optional)
|
|
|
251
254
|
model's hints, table and column `description:` fields from the model, and a profile for
|
|
252
255
|
DuckDB (zero-config, file-based) or Postgres.
|
|
253
256
|
4. **Compute metrics.** With `--metrics`, computes each metric over the generated data and writes
|
|
254
|
-
its known value, a dbt test that checks it, and the Apache Ossie file
|
|
257
|
+
its known value, a dbt test that checks it, and the Apache Ossie file; with `--lightdash`,
|
|
258
|
+
Lightdash metrics and dimensions in the staging models' YAML.
|
|
255
259
|
|
|
256
260
|
---
|
|
257
261
|
|
|
@@ -50,13 +50,16 @@ from model2data.metrics import (
|
|
|
50
50
|
SPEC_VERSION as METRICS_SPEC_VERSION,
|
|
51
51
|
)
|
|
52
52
|
from model2data.metrics import (
|
|
53
|
+
LightdashExport,
|
|
53
54
|
Metrics,
|
|
54
55
|
MetricsError,
|
|
55
56
|
is_metrics_file,
|
|
56
57
|
known_values,
|
|
57
58
|
metrics_stem,
|
|
58
59
|
sibling_model,
|
|
60
|
+
to_lightdash,
|
|
59
61
|
to_ossie,
|
|
62
|
+
write_lightdash,
|
|
60
63
|
write_metric_tests,
|
|
61
64
|
)
|
|
62
65
|
from model2data.metrics import load as load_metrics
|
|
@@ -471,6 +474,16 @@ def main(
|
|
|
471
474
|
"without it. Not picked up from beside the model: pass it."
|
|
472
475
|
),
|
|
473
476
|
),
|
|
477
|
+
lightdash: bool = typer.Option(
|
|
478
|
+
False,
|
|
479
|
+
"--lightdash",
|
|
480
|
+
help=(
|
|
481
|
+
"Add Lightdash metrics and dimensions to the staging models' YAML\n"
|
|
482
|
+
"(models/staging/stg_*.yml, under config.meta): the --metrics file's metrics,\n"
|
|
483
|
+
"or without one the metrics the model implies. Without it those files are\n"
|
|
484
|
+
"unchanged."
|
|
485
|
+
),
|
|
486
|
+
),
|
|
474
487
|
):
|
|
475
488
|
"""
|
|
476
489
|
Generate synthetic data and a dbt project from a model.
|
|
@@ -726,6 +739,13 @@ def main(
|
|
|
726
739
|
# Metrics: only added files, computed from what the seeds hold
|
|
727
740
|
# -------------------------
|
|
728
741
|
metrics_count: Optional[int] = None
|
|
742
|
+
lightdash_export = None
|
|
743
|
+
if _given(lightdash):
|
|
744
|
+
typer.echo("🔦 Adding Lightdash metrics and dimensions to the staging models...")
|
|
745
|
+
lightdash_export = to_lightdash(
|
|
746
|
+
resolve_metrics(model, metrics_doc, model_name=_model_stem(file))
|
|
747
|
+
)
|
|
748
|
+
write_lightdash(dest, lightdash_export)
|
|
729
749
|
if metrics_doc is not None and metrics_file is not None:
|
|
730
750
|
typer.echo("📏 Computing each metric's known value and its dbt test...")
|
|
731
751
|
semantic = resolve_metrics(model, metrics_doc, model_name=_model_stem(file))
|
|
@@ -797,6 +817,13 @@ def main(
|
|
|
797
817
|
f"osi/{project_name}.yml, data-tests/metrics/)"
|
|
798
818
|
)
|
|
799
819
|
|
|
820
|
+
if lightdash_export is not None:
|
|
821
|
+
typer.echo(
|
|
822
|
+
f" Lightdash: {len(lightdash_export.metrics)} metrics "
|
|
823
|
+
"(models/staging/stg_*.yml, config.meta)"
|
|
824
|
+
)
|
|
825
|
+
_print_losses("Not expressible in Lightdash, left out", lightdash_export.lossiness)
|
|
826
|
+
|
|
800
827
|
if report is not None:
|
|
801
828
|
_print_defects(report)
|
|
802
829
|
|
|
@@ -1074,7 +1101,14 @@ metrics_app = typer.Typer(
|
|
|
1074
1101
|
)
|
|
1075
1102
|
app.add_typer(metrics_app, name="metrics")
|
|
1076
1103
|
|
|
1077
|
-
_METRICS_EXPORTS = ("ossie",)
|
|
1104
|
+
_METRICS_EXPORTS = ("ossie", "lightdash")
|
|
1105
|
+
|
|
1106
|
+
|
|
1107
|
+
def _print_losses(heading: str, losses: list) -> None:
|
|
1108
|
+
if losses:
|
|
1109
|
+
typer.echo(f"ℹ️ {heading}:")
|
|
1110
|
+
for loss in losses:
|
|
1111
|
+
typer.echo(f" - {loss}")
|
|
1078
1112
|
|
|
1079
1113
|
|
|
1080
1114
|
def _metrics_inputs(file: Path, metrics_file: Optional[Path]) -> Any:
|
|
@@ -1138,7 +1172,14 @@ def metrics_list_command(
|
|
|
1138
1172
|
def metrics_export_command(
|
|
1139
1173
|
file: Path = _MODEL_OPTION,
|
|
1140
1174
|
metrics_file: Optional[Path] = _METRICS_OPTION,
|
|
1141
|
-
to: str = typer.Option(
|
|
1175
|
+
to: str = typer.Option(
|
|
1176
|
+
"ossie",
|
|
1177
|
+
"--to",
|
|
1178
|
+
help=(
|
|
1179
|
+
"The format: 'ossie' (Apache Ossie 0.1.1, YAML) or 'lightdash' (dbt model "
|
|
1180
|
+
"properties with Lightdash's config.meta, YAML)."
|
|
1181
|
+
),
|
|
1182
|
+
),
|
|
1142
1183
|
output: Optional[Path] = typer.Option( # noqa: B008
|
|
1143
1184
|
None,
|
|
1144
1185
|
"--output",
|
|
@@ -1153,6 +1194,11 @@ def metrics_export_command(
|
|
|
1153
1194
|
Ossie datasets read the staging models of the dbt project `generate` writes
|
|
1154
1195
|
(staging.stg_<table>). What Ossie 0.1.1 cannot say is listed at the top of the file,
|
|
1155
1196
|
and carried in custom_extensions.
|
|
1197
|
+
|
|
1198
|
+
Lightdash's file describes those staging models (stg_<table>) as a dbt properties
|
|
1199
|
+
file. dbt reads a model's properties from one file only, so in a project `generate`
|
|
1200
|
+
wrote, use `generate --lightdash` instead: it merges the same meta into the staging
|
|
1201
|
+
models' own YAML. What Lightdash cannot say is listed at the top of the file.
|
|
1156
1202
|
"""
|
|
1157
1203
|
to = (_given(to) or "ossie").lower()
|
|
1158
1204
|
if to not in _METRICS_EXPORTS:
|
|
@@ -1160,7 +1206,7 @@ def metrics_export_command(
|
|
|
1160
1206
|
f"Choose one of: {', '.join(_METRICS_EXPORTS)}.", param_hint="--to"
|
|
1161
1207
|
)
|
|
1162
1208
|
semantic = _metrics_inputs(file, _given(metrics_file))
|
|
1163
|
-
export = to_ossie(semantic)
|
|
1209
|
+
export = to_ossie(semantic) if to == "ossie" else to_lightdash(semantic)
|
|
1164
1210
|
text = export.to_yaml()
|
|
1165
1211
|
output = _given(output)
|
|
1166
1212
|
if output is None:
|
|
@@ -1170,8 +1216,11 @@ def metrics_export_command(
|
|
|
1170
1216
|
typer.echo(f"❌ {output} already exists. Use --force to overwrite it.")
|
|
1171
1217
|
raise typer.Exit(1)
|
|
1172
1218
|
output.write_text(text, encoding="utf-8")
|
|
1219
|
+
if isinstance(export, LightdashExport):
|
|
1220
|
+
typer.echo(f"✅ Wrote {output} (Lightdash, dbt YAML, {len(export.metrics)} metrics)")
|
|
1221
|
+
_print_losses("Not expressible in Lightdash, left out", export.lossiness)
|
|
1222
|
+
return
|
|
1173
1223
|
typer.echo(f"✅ Wrote {output} (Apache Ossie 0.1.1, {len(semantic.metrics)} metrics)")
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
typer.echo(f" - {loss}")
|
|
1224
|
+
_print_losses(
|
|
1225
|
+
"Not expressible in Ossie 0.1.1 itself, carried in custom_extensions", export.lossiness
|
|
1226
|
+
)
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
| `model2data validate M...` | check models against spec 0.4.0, and `*.metrics.yml` files against the metrics spec and their model (`--model M`, else the model beside it with the same stem) | 0 conforms (warnings allowed), 1 any error |
|
|
9
9
|
| `model2data convert M` | print M as `.model2data.yml`; `-o FILE` writes it, `--force` overwrites | 0 ok, 1 unreadable model or output exists |
|
|
10
10
|
| `model2data metrics list -f M [--metrics F]` | every metric: the file's, then the inferred ones | 0, 1 on a model or metrics error |
|
|
11
|
-
| `model2data metrics export -f M [--metrics F] --to ossie` | the model and its metrics as Apache Ossie 0.1.1; `-o FILE` writes it, `--force` overwrites | 0, 1 on an error or an existing output, 2 on another `--to` |
|
|
11
|
+
| `model2data metrics export -f M [--metrics F] --to ossie\|lightdash` | the model and its metrics as Apache Ossie 0.1.1, or as Lightdash meta in one dbt properties file for the staging models; `-o FILE` writes it, `--force` overwrites | 0, 1 on an error or an existing output, 2 on another `--to` |
|
|
12
12
|
| `model2data guide [TOPIC]` | this page; topics `setup`, `triage`, `tune` | 0 |
|
|
13
13
|
|
|
14
14
|
`generate` exits 0 on success; 1 on a model error, an existing `dbt_<name>/` without
|
|
@@ -142,7 +142,9 @@ Only tables with `incremental` change after the first day.
|
|
|
142
142
|
With `--metrics FILE`, and nothing else changed: `metric_values.json` (each metric's known
|
|
143
143
|
value over the seeds, overall and by month), `data-tests/metrics/metric_<name>.sql` (a dbt
|
|
144
144
|
test per metric that fails unless the warehouse gets that value) and `osi/<name>.yml`
|
|
145
|
-
(Apache Ossie 0.1.1).
|
|
145
|
+
(Apache Ossie 0.1.1). With `--lightdash` (with or without `--metrics`), the staging models'
|
|
146
|
+
`stg_<table>.yml` also carry Lightdash metrics, dimensions and joins under `config.meta`; what
|
|
147
|
+
Lightdash cannot say is listed in the summary.
|
|
146
148
|
|
|
147
149
|
## Metrics file
|
|
148
150
|
|
|
@@ -12,6 +12,7 @@ generator never reads it: a model generates the same data with or without one.
|
|
|
12
12
|
>>> values = metrics.known_values(semantic, frames) # over a run's generated tables
|
|
13
13
|
>>> export = metrics.to_ossie(semantic) # Apache Ossie 0.1.1
|
|
14
14
|
>>> export.to_yaml(), export.lossiness
|
|
15
|
+
>>> metrics.to_lightdash(semantic).to_yaml() # Lightdash meta, dbt YAML
|
|
15
16
|
|
|
16
17
|
`resolve(model)` with no metrics file gives the metrics the model implies on
|
|
17
18
|
its own: one per `measure` column, and a row count per fact.
|
|
@@ -23,6 +24,7 @@ from model2data.metrics.expression import ExpressionError
|
|
|
23
24
|
from model2data.metrics.expression import parse as parse_expression
|
|
24
25
|
from model2data.metrics.graph import Graph, Join
|
|
25
26
|
from model2data.metrics.infer import inferred_metrics
|
|
27
|
+
from model2data.metrics.lightdash import LightdashExport, to_lightdash, write_lightdash
|
|
26
28
|
from model2data.metrics.ossie import OSSIE_VERSION, Loss, OssieExport, to_ossie
|
|
27
29
|
from model2data.metrics.reader import (
|
|
28
30
|
MetricsError,
|
|
@@ -71,6 +73,7 @@ __all__ = [
|
|
|
71
73
|
"Join",
|
|
72
74
|
"KnownValue",
|
|
73
75
|
"KnownValues",
|
|
76
|
+
"LightdashExport",
|
|
74
77
|
"Loss",
|
|
75
78
|
"Measure",
|
|
76
79
|
"Metric",
|
|
@@ -94,7 +97,9 @@ __all__ = [
|
|
|
94
97
|
"parse_expression",
|
|
95
98
|
"resolve",
|
|
96
99
|
"sibling_model",
|
|
100
|
+
"to_lightdash",
|
|
97
101
|
"to_ossie",
|
|
98
102
|
"validate",
|
|
103
|
+
"write_lightdash",
|
|
99
104
|
"write_metric_tests",
|
|
100
105
|
]
|