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.
Files changed (195) hide show
  1. {model2data-1.13.0/model2data.egg-info → model2data-1.14.0}/PKG-INFO +7 -3
  2. {model2data-1.13.0 → model2data-1.14.0}/README.md +6 -2
  3. {model2data-1.13.0 → model2data-1.14.0}/README_PYPI.md +6 -2
  4. {model2data-1.13.0 → model2data-1.14.0}/model2data/cli.py +56 -7
  5. {model2data-1.13.0 → model2data-1.14.0}/model2data/guide/tune.md +4 -2
  6. {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/__init__.py +5 -0
  7. model2data-1.14.0/model2data/metrics/lightdash.py +597 -0
  8. {model2data-1.13.0 → model2data-1.14.0}/model2data/spec/PUBLISHING.md +0 -2
  9. {model2data-1.13.0 → model2data-1.14.0}/model2data/spec/metrics/README.md +3 -2
  10. {model2data-1.13.0 → model2data-1.14.0/model2data.egg-info}/PKG-INFO +7 -3
  11. {model2data-1.13.0 → model2data-1.14.0}/model2data.egg-info/SOURCES.txt +2 -0
  12. {model2data-1.13.0 → model2data-1.14.0}/pyproject.toml +1 -1
  13. {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_cli.py +57 -0
  14. {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_dbt.py +69 -0
  15. model2data-1.14.0/tests/test_metrics_lightdash.py +645 -0
  16. {model2data-1.13.0 → model2data-1.14.0}/LICENSE +0 -0
  17. {model2data-1.13.0 → model2data-1.14.0}/model2data/__init__.py +0 -0
  18. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/__init__.py +0 -0
  19. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/LICENSE +0 -0
  20. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/VENDORED.md +0 -0
  21. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/__init__.py +0 -0
  22. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/__init__.py +0 -0
  23. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/base.py +0 -0
  24. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/column.py +0 -0
  25. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/enum.py +0 -0
  26. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/expression.py +0 -0
  27. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/index.py +0 -0
  28. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/note.py +0 -0
  29. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/project.py +0 -0
  30. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/reference.py +0 -0
  31. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/sticky_note.py +0 -0
  32. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/table.py +0 -0
  33. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/_classes/table_group.py +0 -0
  34. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/classes/__init__.py +0 -0
  35. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/constants.py +0 -0
  36. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/database.py +0 -0
  37. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/__init__.py +0 -0
  38. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/column.py +0 -0
  39. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/common.py +0 -0
  40. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/enum.py +0 -0
  41. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/generic.py +0 -0
  42. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/index.py +0 -0
  43. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/project.py +0 -0
  44. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/records.py +0 -0
  45. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/reference.py +0 -0
  46. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/sticky_note.py +0 -0
  47. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/table.py +0 -0
  48. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/table_group.py +0 -0
  49. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/definitions/table_partial.py +0 -0
  50. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/exceptions.py +0 -0
  51. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/parser/__init__.py +0 -0
  52. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/parser/blueprints.py +0 -0
  53. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/parser/parser.py +0 -0
  54. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/__init__.py +0 -0
  55. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/base.py +0 -0
  56. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/__init__.py +0 -0
  57. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/__init__.py +0 -0
  58. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/column.py +0 -0
  59. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/enum.py +0 -0
  60. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/expression.py +0 -0
  61. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/index.py +0 -0
  62. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/note.py +0 -0
  63. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/project.py +0 -0
  64. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/reference.py +0 -0
  65. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/renderer.py +0 -0
  66. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/sticky_note.py +0 -0
  67. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/table.py +0 -0
  68. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/table_group.py +0 -0
  69. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/dbml/default/utils.py +0 -0
  70. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/__init__.py +0 -0
  71. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/__init__.py +0 -0
  72. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/column.py +0 -0
  73. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/enum.py +0 -0
  74. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/expression.py +0 -0
  75. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/index.py +0 -0
  76. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/note.py +0 -0
  77. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/reference.py +0 -0
  78. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/renderer.py +0 -0
  79. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/table.py +0 -0
  80. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/renderer/sql/default/utils.py +0 -0
  81. {model2data-1.13.0 → model2data-1.14.0}/model2data/_vendor/pydbml/tools.py +0 -0
  82. {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/__init__.py +0 -0
  83. {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/hint_tests.py +0 -0
  84. {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/naming.py +0 -0
  85. {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/project.py +0 -0
  86. {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/templates/dbt_project.yml.jinja +0 -0
  87. {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/templates/hint_macros/model2data_hint_tests.sql +0 -0
  88. {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/templates/hint_macros/model2data_when_tests.sql +0 -0
  89. {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/templates/history_macros/model2data_history_tests.sql +0 -0
  90. {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/templates/macros/generate_schema_name.sql +0 -0
  91. {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/templates/profiles.yml.jinja +0 -0
  92. {model2data-1.13.0 → model2data-1.14.0}/model2data/dbt/tests.py +0 -0
  93. {model2data-1.13.0 → model2data-1.14.0}/model2data/defects/__init__.py +0 -0
  94. {model2data-1.13.0 → model2data-1.14.0}/model2data/defects/apply.py +0 -0
  95. {model2data-1.13.0 → model2data-1.14.0}/model2data/defects/checks.py +0 -0
  96. {model2data-1.13.0 → model2data-1.14.0}/model2data/defects/presets.py +0 -0
  97. {model2data-1.13.0 → model2data-1.14.0}/model2data/defects/report.py +0 -0
  98. {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/__init__.py +0 -0
  99. {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/core.py +0 -0
  100. {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/days.py +0 -0
  101. {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/faker.py +0 -0
  102. {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/hints.py +0 -0
  103. {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/history.py +0 -0
  104. {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/kinds.py +0 -0
  105. {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/options.py +0 -0
  106. {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/relationships.py +0 -0
  107. {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/timeline.py +0 -0
  108. {model2data-1.13.0 → model2data-1.14.0}/model2data/generate/when.py +0 -0
  109. {model2data-1.13.0 → model2data-1.14.0}/model2data/guide/setup.md +0 -0
  110. {model2data-1.13.0 → model2data-1.14.0}/model2data/guide/triage.md +0 -0
  111. {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/check.py +0 -0
  112. {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/columns.py +0 -0
  113. {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/dbt.py +0 -0
  114. {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/expression.py +0 -0
  115. {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/graph.py +0 -0
  116. {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/infer.py +0 -0
  117. {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/ossie.py +0 -0
  118. {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/reader.py +0 -0
  119. {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/semantic.py +0 -0
  120. {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/sql.py +0 -0
  121. {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/types.py +0 -0
  122. {model2data-1.13.0 → model2data-1.14.0}/model2data/metrics/values.py +0 -0
  123. {model2data-1.13.0 → model2data-1.14.0}/model2data/model/__init__.py +0 -0
  124. {model2data-1.13.0 → model2data-1.14.0}/model2data/model/_yaml.py +0 -0
  125. {model2data-1.13.0 → model2data-1.14.0}/model2data/model/dbml.py +0 -0
  126. {model2data-1.13.0 → model2data-1.14.0}/model2data/model/document.py +0 -0
  127. {model2data-1.13.0 → model2data-1.14.0}/model2data/model/dump.py +0 -0
  128. {model2data-1.13.0 → model2data-1.14.0}/model2data/model/engine.py +0 -0
  129. {model2data-1.13.0 → model2data-1.14.0}/model2data/model/errors.py +0 -0
  130. {model2data-1.13.0 → model2data-1.14.0}/model2data/model/reader.py +0 -0
  131. {model2data-1.13.0 → model2data-1.14.0}/model2data/model/types.py +0 -0
  132. {model2data-1.13.0 → model2data-1.14.0}/model2data/model/validate.py +0 -0
  133. {model2data-1.13.0 → model2data-1.14.0}/model2data/output.py +0 -0
  134. {model2data-1.13.0 → model2data-1.14.0}/model2data/parse/__init__.py +0 -0
  135. {model2data-1.13.0 → model2data-1.14.0}/model2data/parse/dbml.py +0 -0
  136. {model2data-1.13.0 → model2data-1.14.0}/model2data/spec/README.md +0 -0
  137. {model2data-1.13.0 → model2data-1.14.0}/model2data/spec/examples/coffee_webshop.metrics.yml +0 -0
  138. {model2data-1.13.0 → model2data-1.14.0}/model2data/spec/examples/coffee_webshop.model2data.yml +0 -0
  139. {model2data-1.13.0 → model2data-1.14.0}/model2data/spec/metrics/metrics.schema.json +0 -0
  140. {model2data-1.13.0 → model2data-1.14.0}/model2data/spec/model.schema.json +0 -0
  141. {model2data-1.13.0 → model2data-1.14.0}/model2data/utils.py +0 -0
  142. {model2data-1.13.0 → model2data-1.14.0}/model2data.egg-info/dependency_links.txt +0 -0
  143. {model2data-1.13.0 → model2data-1.14.0}/model2data.egg-info/entry_points.txt +0 -0
  144. {model2data-1.13.0 → model2data-1.14.0}/model2data.egg-info/requires.txt +0 -0
  145. {model2data-1.13.0 → model2data-1.14.0}/model2data.egg-info/top_level.txt +0 -0
  146. {model2data-1.13.0 → model2data-1.14.0}/setup.cfg +0 -0
  147. {model2data-1.13.0 → model2data-1.14.0}/tests/test_as_of_anchor.py +0 -0
  148. {model2data-1.13.0 → model2data-1.14.0}/tests/test_cli.py +0 -0
  149. {model2data-1.13.0 → model2data-1.14.0}/tests/test_cli_model.py +0 -0
  150. {model2data-1.13.0 → model2data-1.14.0}/tests/test_column_time_hints.py +0 -0
  151. {model2data-1.13.0 → model2data-1.14.0}/tests/test_coverage_gaps.py +0 -0
  152. {model2data-1.13.0 → model2data-1.14.0}/tests/test_days.py +0 -0
  153. {model2data-1.13.0 → model2data-1.14.0}/tests/test_dbml_parser.py +0 -0
  154. {model2data-1.13.0 → model2data-1.14.0}/tests/test_dbml_parser_fuzz.py +0 -0
  155. {model2data-1.13.0 → model2data-1.14.0}/tests/test_dbt_integration.py +0 -0
  156. {model2data-1.13.0 → model2data-1.14.0}/tests/test_dbt_naming.py +0 -0
  157. {model2data-1.13.0 → model2data-1.14.0}/tests/test_dbt_project.py +0 -0
  158. {model2data-1.13.0 → model2data-1.14.0}/tests/test_dbt_tests.py +0 -0
  159. {model2data-1.13.0 → model2data-1.14.0}/tests/test_defects.py +0 -0
  160. {model2data-1.13.0 → model2data-1.14.0}/tests/test_defects_dbt.py +0 -0
  161. {model2data-1.13.0 → model2data-1.14.0}/tests/test_defects_replay.py +0 -0
  162. {model2data-1.13.0 → model2data-1.14.0}/tests/test_defects_report.py +0 -0
  163. {model2data-1.13.0 → model2data-1.14.0}/tests/test_defects_review.py +0 -0
  164. {model2data-1.13.0 → model2data-1.14.0}/tests/test_determinism.py +0 -0
  165. {model2data-1.13.0 → model2data-1.14.0}/tests/test_distributions.py +0 -0
  166. {model2data-1.13.0 → model2data-1.14.0}/tests/test_examples_model.py +0 -0
  167. {model2data-1.13.0 → model2data-1.14.0}/tests/test_faker_name_inference.py +0 -0
  168. {model2data-1.13.0 → model2data-1.14.0}/tests/test_fast_paths.py +0 -0
  169. {model2data-1.13.0 → model2data-1.14.0}/tests/test_generation.py +0 -0
  170. {model2data-1.13.0 → model2data-1.14.0}/tests/test_guide.py +0 -0
  171. {model2data-1.13.0 → model2data-1.14.0}/tests/test_hint_tests.py +0 -0
  172. {model2data-1.13.0 → model2data-1.14.0}/tests/test_history.py +0 -0
  173. {model2data-1.13.0 → model2data-1.14.0}/tests/test_issue_lines.py +0 -0
  174. {model2data-1.13.0 → model2data-1.14.0}/tests/test_lone_country.py +0 -0
  175. {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_expression.py +0 -0
  176. {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_ossie.py +0 -0
  177. {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_reader.py +0 -0
  178. {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_semantic.py +0 -0
  179. {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_spec.py +0 -0
  180. {model2data-1.13.0 → model2data-1.14.0}/tests/test_metrics_values.py +0 -0
  181. {model2data-1.13.0 → model2data-1.14.0}/tests/test_model.py +0 -0
  182. {model2data-1.13.0 → model2data-1.14.0}/tests/test_model_dbml.py +0 -0
  183. {model2data-1.13.0 → model2data-1.14.0}/tests/test_model_edges.py +0 -0
  184. {model2data-1.13.0 → model2data-1.14.0}/tests/test_model_messages.py +0 -0
  185. {model2data-1.13.0 → model2data-1.14.0}/tests/test_model_vocabulary.py +0 -0
  186. {model2data-1.13.0 → model2data-1.14.0}/tests/test_options.py +0 -0
  187. {model2data-1.13.0 → model2data-1.14.0}/tests/test_release_stress.py +0 -0
  188. {model2data-1.13.0 → model2data-1.14.0}/tests/test_reproducibility.py +0 -0
  189. {model2data-1.13.0 → model2data-1.14.0}/tests/test_row_identity.py +0 -0
  190. {model2data-1.13.0 → model2data-1.14.0}/tests/test_shaping.py +0 -0
  191. {model2data-1.13.0 → model2data-1.14.0}/tests/test_spec_alignment.py +0 -0
  192. {model2data-1.13.0 → model2data-1.14.0}/tests/test_spec_schema.py +0 -0
  193. {model2data-1.13.0 → model2data-1.14.0}/tests/test_table_seeds.py +0 -0
  194. {model2data-1.13.0 → model2data-1.14.0}/tests/test_timeline.py +0 -0
  195. {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.13.0
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("ossie", "--to", help="The format: 'ossie' (Apache Ossie 0.1.1, YAML)."),
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
- if export.lossiness:
1175
- typer.echo("ℹ️ Not expressible in Ossie 0.1.1 itself, carried in custom_extensions:")
1176
- for loss in export.lossiness:
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
  ]