recce-nightly 0.55.0.20250223__tar.gz → 0.55.0.20250225__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 (144) hide show
  1. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/PKG-INFO +1 -1
  2. recce_nightly-0.55.0.20250225/recce/VERSION +1 -0
  3. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/adapter/dbt_adapter/__init__.py +101 -31
  4. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/404.html +1 -1
  5. recce_nightly-0.55.0.20250223/recce/data/_next/static/chunks/app/page-a82caa413d353ee4.js → recce_nightly-0.55.0.20250225/recce/data/_next/static/chunks/app/page-3b958dd422cce983.js +1 -1
  6. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/index.html +2 -2
  7. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/index.txt +2 -2
  8. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/run.py +2 -2
  9. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/util/cll.py +88 -71
  10. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce_nightly.egg-info/PKG-INFO +1 -1
  11. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce_nightly.egg-info/SOURCES.txt +3 -3
  12. recce_nightly-0.55.0.20250225/tests/test_dbt.py +197 -0
  13. recce_nightly-0.55.0.20250223/recce/VERSION +0 -1
  14. recce_nightly-0.55.0.20250223/tests/test_dbt.py +0 -24
  15. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/LICENSE +0 -0
  16. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/README.md +0 -0
  17. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/__init__.py +0 -0
  18. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/adapter/__init__.py +0 -0
  19. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/adapter/base.py +0 -0
  20. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/adapter/dbt_adapter/dbt_version.py +0 -0
  21. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/adapter/sqlmesh_adapter.py +0 -0
  22. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/apis/__init__.py +0 -0
  23. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/apis/check_api.py +0 -0
  24. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/apis/check_func.py +0 -0
  25. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/apis/run_api.py +0 -0
  26. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/apis/run_func.py +0 -0
  27. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/artifact.py +0 -0
  28. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/cli.py +0 -0
  29. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/config.py +0 -0
  30. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/core.py +0 -0
  31. {recce_nightly-0.55.0.20250223/recce/data/_next/static/y5Kkvpkew9hSMhPxh_mxN → recce_nightly-0.55.0.20250225/recce/data/_next/static/07p7nCPCfqFS16N0mBJkg}/_buildManifest.js +0 -0
  32. {recce_nightly-0.55.0.20250223/recce/data/_next/static/y5Kkvpkew9hSMhPxh_mxN → recce_nightly-0.55.0.20250225/recce/data/_next/static/07p7nCPCfqFS16N0mBJkg}/_ssgManifest.js +0 -0
  33. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/157e448a-49151cad1ec51175.js +0 -0
  34. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/29e3cc0d-490dbff344996865.js +0 -0
  35. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/312-3e9b49b718b98737.js +0 -0
  36. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/323-9565a741f1447d32.js +0 -0
  37. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/36e1c10d-3bcdd9bb8564108c.js +0 -0
  38. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/3998a672-e71829c331c77ccb.js +0 -0
  39. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/450c323b-79414be6f43ef15c.js +0 -0
  40. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/47d8844f-ccb4e71fbabd12f3.js +0 -0
  41. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/6dc81886-03da5372308c376d.js +0 -0
  42. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/7a8a3e83-f7fe5f14c56108bf.js +0 -0
  43. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/7f27ae6c-c484e79185298424.js +0 -0
  44. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/868e7b5c-36d94ba5a58a2e6a.js +0 -0
  45. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/9746af58-daab848e55b5faf7.js +0 -0
  46. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/a30376cd-ea4617387c84b12e.js +0 -0
  47. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/app/_not-found/page-c2ee18b5ec3e3d57.js +0 -0
  48. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/app/layout-5b30ab0207459cb8.js +0 -0
  49. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/b3b1872b-97ea0be5bd9b42bc.js +0 -0
  50. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/b63b1b3f-13deddaaba264453.js +0 -0
  51. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/c132bf7d-740a7144e614cb2d.js +0 -0
  52. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/ce84277d-ced9559f73764a27.js +0 -0
  53. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/cf0511cf-88e5bf54e88504a3.js +0 -0
  54. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/fee69bc6-2cf346c884a74e9d.js +0 -0
  55. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/framework-ded83d71b51ce901.js +0 -0
  56. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/main-45628b9d5f140527.js +0 -0
  57. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/main-app-19c0918a6bb54549.js +0 -0
  58. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/pages/_app-ff7f75fed61fbef3.js +0 -0
  59. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/pages/_error-5e587f051118d074.js +0 -0
  60. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -0
  61. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/chunks/webpack-300961f547f48fe7.js +0 -0
  62. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/css/1d7428fe54fca42f.css +0 -0
  63. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/media/montserrat-cyrillic-800-normal.5c8b3804.woff +0 -0
  64. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/media/montserrat-cyrillic-800-normal.c03acce9.woff2 +0 -0
  65. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.83d3554a.woff2 +0 -0
  66. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.8a4a9645.woff +0 -0
  67. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/media/montserrat-latin-800-normal.388abfc2.woff2 +0 -0
  68. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/media/montserrat-latin-800-normal.e7b55ea8.woff +0 -0
  69. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/media/montserrat-latin-ext-800-normal.40cba3c6.woff +0 -0
  70. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/media/montserrat-latin-ext-800-normal.85728e97.woff2 +0 -0
  71. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/media/montserrat-vietnamese-800-normal.0bd05041.woff +0 -0
  72. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/_next/static/media/montserrat-vietnamese-800-normal.dfbbc7ba.woff2 +0 -0
  73. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/favicon.ico +0 -0
  74. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/imgs/feedback/thumbs-down.png +0 -0
  75. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/imgs/feedback/thumbs-up.png +0 -0
  76. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/data/logo/recce-logo-white.png +0 -0
  77. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/diff.py +0 -0
  78. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/event/CONFIG +0 -0
  79. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/event/SENTRY_DNS +0 -0
  80. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/event/__init__.py +0 -0
  81. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/event/collector.py +0 -0
  82. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/event/track.py +0 -0
  83. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/exceptions.py +0 -0
  84. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/git.py +0 -0
  85. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/github.py +0 -0
  86. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/models/__init__.py +0 -0
  87. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/models/check.py +0 -0
  88. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/models/run.py +0 -0
  89. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/models/types.py +0 -0
  90. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/pull_request.py +0 -0
  91. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/server.py +0 -0
  92. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/state.py +0 -0
  93. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/summary.py +0 -0
  94. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/tasks/__init__.py +0 -0
  95. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/tasks/core.py +0 -0
  96. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/tasks/dataframe.py +0 -0
  97. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/tasks/histogram.py +0 -0
  98. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/tasks/lineage.py +0 -0
  99. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/tasks/profile.py +0 -0
  100. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/tasks/query.py +0 -0
  101. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/tasks/rowcount.py +0 -0
  102. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/tasks/schema.py +0 -0
  103. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/tasks/top_k.py +0 -0
  104. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/tasks/valuediff.py +0 -0
  105. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/util/__init__.py +0 -0
  106. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/util/breaking.py +0 -0
  107. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/util/cache.py +0 -0
  108. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/util/io.py +0 -0
  109. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/util/logger.py +0 -0
  110. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/util/pydantic_model.py +0 -0
  111. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/util/recce_cloud.py +0 -0
  112. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/util/singleton.py +0 -0
  113. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce/yaml/__init__.py +0 -0
  114. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce_nightly.egg-info/dependency_links.txt +0 -0
  115. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce_nightly.egg-info/entry_points.txt +0 -0
  116. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce_nightly.egg-info/requires.txt +0 -0
  117. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/recce_nightly.egg-info/top_level.txt +0 -0
  118. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/setup.cfg +0 -0
  119. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/setup.py +0 -0
  120. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/__init__.py +0 -0
  121. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/adapter/__init__.py +0 -0
  122. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/adapter/dbt_adapter/__init__.py +0 -0
  123. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/adapter/dbt_adapter/conftest.py +0 -0
  124. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/adapter/dbt_adapter/dbt_test_helper.py +0 -0
  125. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/adapter/dbt_adapter/test_dbt_adapter.py +0 -0
  126. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/adapter/dbt_adapter/test_selector.py +0 -0
  127. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/tasks/__init__.py +0 -0
  128. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/tasks/conftest.py +0 -0
  129. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/tasks/test_histogram.py +0 -0
  130. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/tasks/test_lineage.py +0 -0
  131. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/tasks/test_preset_checks.py +0 -0
  132. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/tasks/test_profile.py +0 -0
  133. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/tasks/test_query.py +0 -0
  134. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/tasks/test_row_count.py +0 -0
  135. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/tasks/test_schema.py +0 -0
  136. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/tasks/test_top_k.py +0 -0
  137. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/tasks/test_valuediff.py +0 -0
  138. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/test_cli.py +0 -0
  139. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/test_config.py +0 -0
  140. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/test_core.py +0 -0
  141. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/test_pull_request.py +0 -0
  142. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/test_server.py +0 -0
  143. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/test_state.py +0 -0
  144. {recce_nightly-0.55.0.20250223 → recce_nightly-0.55.0.20250225}/tests/test_summary.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: recce-nightly
3
- Version: 0.55.0.20250223
3
+ Version: 0.55.0.20250225
4
4
  Summary: Environment diff tool for dbt
5
5
  Home-page: https://github.com/InfuseAI/recce
6
6
  Author: InfuseAI Dev Team
@@ -0,0 +1 @@
1
+ 0.55.0.20250225
@@ -10,6 +10,7 @@ from pathlib import Path
10
10
  from typing import Callable, Dict, List, Optional, Tuple, Iterator, Any, Set, Union, Literal, Type
11
11
 
12
12
  from recce.util.cll import cll
13
+ from recce.exceptions import RecceException
13
14
 
14
15
  try:
15
16
  import agate
@@ -470,6 +471,14 @@ class DbtAdapter(BaseAdapter):
470
471
  os.path.join(project_root, target_base_path, 'catalog.json'),
471
472
  ]
472
473
 
474
+ def is_python_model(self, node_id: str, base: Optional[bool] = False):
475
+ manifest = self.curr_manifest if base is False else self.base_manifest
476
+ model = manifest.nodes.get(node_id)
477
+ if hasattr(model, 'language'):
478
+ return model.language == 'python'
479
+
480
+ return False
481
+
473
482
  def find_node_by_name(self, node_name, base=False) -> Optional[ManifestNode]:
474
483
 
475
484
  manifest = self.curr_manifest if base is False else self.base_manifest
@@ -545,6 +554,36 @@ class DbtAdapter(BaseAdapter):
545
554
 
546
555
  return self.adapter.execute(sql, auto_begin=auto_begin, fetch=fetch, limit=limit)
547
556
 
557
+ def build_parent_map(self, nodes: Dict, base: Optional[bool] = False) -> Dict[str, List[str]]:
558
+ manifest = self.curr_manifest if base is False else self.base_manifest
559
+ manifest_dict = manifest.to_dict()
560
+
561
+ node_ids = nodes.keys()
562
+ parent_map = {}
563
+ for k, parents in manifest_dict['parent_map'].items():
564
+ if k not in node_ids:
565
+ continue
566
+ parent_map[k] = [parent for parent in parents if parent in node_ids]
567
+
568
+ return parent_map
569
+
570
+ @lru_cache(maxsize=2)
571
+ def build_table_map(self, base: Optional[bool] = False) -> Dict[str, str]:
572
+ manifest = self.curr_manifest if base is False else self.base_manifest
573
+ manifest_dict = manifest.to_dict()
574
+
575
+ table_map = {}
576
+ for node in manifest_dict['nodes'].values():
577
+ resource_type = node['resource_type']
578
+ if resource_type not in ['model', 'seed', 'exposure', 'snapshot']:
579
+ continue
580
+ table_map[node['unique_id']] = node.get('alias')
581
+
582
+ for source in manifest_dict['sources'].values():
583
+ table_map[source['unique_id']] = source.get('identifier')
584
+
585
+ return table_map
586
+
548
587
  def get_lineage(self, base: Optional[bool] = False):
549
588
  manifest = self.curr_manifest if base is False else self.base_manifest
550
589
  catalog = self.curr_catalog if base is False else self.base_catalog
@@ -618,8 +657,8 @@ class DbtAdapter(BaseAdapter):
618
657
  if catalog is not None and unique_id in catalog.nodes:
619
658
  columns = {}
620
659
  primary_key = None
621
- for col_name, col in catalog.nodes[unique_id].columns.items():
622
- col = dict(name=col_name, type=col.type)
660
+ for col_name, col_metadata in catalog.nodes[unique_id].columns.items():
661
+ col = dict(name=col_name, type=col_metadata.type)
623
662
  if col_name in cols_not_null:
624
663
  col['not_null'] = True
625
664
  if col_name in cols_unique:
@@ -643,7 +682,13 @@ class DbtAdapter(BaseAdapter):
643
682
  }
644
683
 
645
684
  if catalog is not None and unique_id in catalog.sources:
646
- nodes[unique_id]['columns'] = catalog.sources[unique_id].columns
685
+ nodes[unique_id]['columns'] = {
686
+ col_name: {
687
+ 'name': col_name,
688
+ 'type': col_metadata.type
689
+ }
690
+ for col_name, col_metadata in catalog.sources[unique_id].columns.items()
691
+ }
647
692
 
648
693
  for exposure in manifest_dict['exposures'].values():
649
694
  nodes[exposure['unique_id']] = {
@@ -672,45 +717,70 @@ class DbtAdapter(BaseAdapter):
672
717
  'config': semantic_models['config'],
673
718
  }
674
719
 
675
- nodeIds = nodes.keys()
676
- parent_map = {}
677
- for k, parents in manifest_dict['parent_map'].items():
678
- if k not in nodeIds:
679
- continue
680
- parent_map[k] = [parent for parent in parents if parent in nodeIds]
720
+ parent_map = self.build_parent_map(nodes, base)
721
+ table_map = {}
681
722
 
682
723
  # Handle column-level lineage, only enable if env var is set to true
683
724
  if os.getenv('RECCE_CLL_ENABLED') == 'true':
684
- for node in nodes.values():
685
- if node.get('resource_type') != 'model':
686
- continue
687
-
688
- if node.get('raw_code') is None:
689
- continue
690
-
691
- compiled_sql = self.generate_sql(node.get('raw_code'), base=base)
692
- schema = {}
693
- for parent_id in parent_map[node.get('id')]:
694
- parent_node = nodes.get(parent_id)
695
- if parent_node is None:
696
- continue
697
- columns = parent_node.get('columns') or {}
698
- schema[parent_node['name']] = {
699
- name: column.get('type') for name, column in columns.items()
700
- }
701
- column_lineage = cll(compiled_sql, schema=schema)
702
- for name, column in node['columns'].items():
703
- if name in column_lineage:
704
- column['depends_on'] = column_lineage[name].depends_on
705
- column['transformation_type'] = column_lineage[name].type
725
+ if base is False:
726
+ table_map = self.build_table_map(base)
727
+ self.append_column_lineage(nodes, parent_map, base)
706
728
 
707
729
  return dict(
708
730
  parent_map=parent_map,
709
731
  nodes=nodes,
732
+ table_map=table_map,
710
733
  manifest_metadata=manifest_metadata,
711
734
  catalog_metadata=catalog_metadata,
712
735
  )
713
736
 
737
+ def append_column_lineage(self, nodes: Dict, parent_map: Dict, base: Optional[bool] = False):
738
+ def _apply_all_columns(node, trans_type, depends_on):
739
+ for col in node.get('columns', {}).values():
740
+ col['transformation_type'] = trans_type
741
+ col['depends_on'] = depends_on
742
+
743
+ for node in nodes.values():
744
+ resource_type = node.get('resource_type')
745
+ if resource_type not in {'model', 'seed', 'source', 'snapshot'}:
746
+ continue
747
+
748
+ if resource_type == 'source' or resource_type == 'seed':
749
+ _apply_all_columns(node, 'source', [])
750
+ continue
751
+
752
+ if node.get('raw_code') is None or self.is_python_model(node.get('id'), base=base):
753
+ _apply_all_columns(node, 'unknown', [])
754
+ continue
755
+
756
+ if not node.get('columns', {}):
757
+ # no catalog
758
+ continue
759
+
760
+ compiled_sql = self.generate_sql(node.get('raw_code'), base=base)
761
+
762
+ schema = {}
763
+ for parent_id in parent_map[node.get('id')]:
764
+ parent_node = nodes.get(parent_id)
765
+ if parent_node is None:
766
+ continue
767
+ columns = parent_node.get('columns') or {}
768
+ schema[parent_node['name']] = {
769
+ name: column.get('type') for name, column in columns.items()
770
+ }
771
+
772
+ try:
773
+ column_lineage = cll(compiled_sql, schema=schema)
774
+ except RecceException as exception:
775
+ print(exception)
776
+ _apply_all_columns(node, 'unknown', [])
777
+ continue
778
+
779
+ for name, column in node.get('columns', {}).items():
780
+ if name in column_lineage:
781
+ column['depends_on'] = column_lineage[name].depends_on
782
+ column['transformation_type'] = column_lineage[name].type
783
+
714
784
  @lru_cache(maxsize=1)
715
785
  def _get_lineage_diff_cached(self, cache_key) -> LineageDiff:
716
786
  base = self.get_lineage(base=True)
@@ -1 +1 @@
1
- <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-300961f547f48fe7.js"/><script src="/_next/static/chunks/157e448a-49151cad1ec51175.js" async=""></script><script src="/_next/static/chunks/312-3e9b49b718b98737.js" async=""></script><script src="/_next/static/chunks/main-app-19c0918a6bb54549.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>recce</title><meta name="description" content="Recce: Data validation toolkit for comprehensive PR review"/><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><script src="/_next/static/chunks/webpack-300961f547f48fe7.js" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:I[16892,[],\"\"]\n3:I[60299,[],\"\"]\n4:I[43276,[],\"\"]\na:I[28103,[],\"\"]\n5:{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"}\n6:{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"}\n7:{\"display\":\"inline-block\"}\n8:{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0}\nb:[]\n"])</script><script>self.__next_f.push([1,"0:[\"$\",\"$L1\",null,{\"buildId\":\"y5Kkvpkew9hSMhPxh_mxN\",\"assetPrefix\":\"\",\"urlParts\":[\"\",\"_not-found\"],\"initialTree\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{},[[\"$L2\",[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null],null],null]},[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\",\"/_not-found\",\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"notFoundStyles\":\"$undefined\"}]],null]},[[null,[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"suppressHydrationWarning\":true,\"children\":[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$5\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$6\",\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":\"$7\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$8\",\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[]}]}]}]],null],null],\"couldBeIntercepted\":false,\"initialHead\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],\"$L9\"],\"globalErrorComponent\":\"$a\",\"missingSlots\":\"$Wb\"}]\n"])</script><script>self.__next_f.push([1,"9:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"recce\"}],[\"$\",\"meta\",\"3\",{\"name\":\"description\",\"content\":\"Recce: Data validation toolkit for comprehensive PR review\"}]]\n2:null\n"])</script></body></html>
1
+ <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-300961f547f48fe7.js"/><script src="/_next/static/chunks/157e448a-49151cad1ec51175.js" async=""></script><script src="/_next/static/chunks/312-3e9b49b718b98737.js" async=""></script><script src="/_next/static/chunks/main-app-19c0918a6bb54549.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>recce</title><meta name="description" content="Recce: Data validation toolkit for comprehensive PR review"/><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><script src="/_next/static/chunks/webpack-300961f547f48fe7.js" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:I[16892,[],\"\"]\n3:I[60299,[],\"\"]\n4:I[43276,[],\"\"]\na:I[28103,[],\"\"]\n5:{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"}\n6:{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"}\n7:{\"display\":\"inline-block\"}\n8:{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0}\nb:[]\n"])</script><script>self.__next_f.push([1,"0:[\"$\",\"$L1\",null,{\"buildId\":\"07p7nCPCfqFS16N0mBJkg\",\"assetPrefix\":\"\",\"urlParts\":[\"\",\"_not-found\"],\"initialTree\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{},[[\"$L2\",[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null],null],null]},[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\",\"/_not-found\",\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"notFoundStyles\":\"$undefined\"}]],null]},[[null,[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"suppressHydrationWarning\":true,\"children\":[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$5\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$6\",\"children\":\"404\"}],[\"$\",\"div\",null,{\"style\":\"$7\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$8\",\"children\":\"This page could not be found.\"}]}]]}]}]],\"notFoundStyles\":[]}]}]}]],null],null],\"couldBeIntercepted\":false,\"initialHead\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],\"$L9\"],\"globalErrorComponent\":\"$a\",\"missingSlots\":\"$Wb\"}]\n"])</script><script>self.__next_f.push([1,"9:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"recce\"}],[\"$\",\"meta\",\"3\",{\"name\":\"description\",\"content\":\"Recce: Data validation toolkit for comprehensive PR review\"}]]\n2:null\n"])</script></body></html>