recce-nightly 0.51.0.20250116__tar.gz → 0.51.0.20250120__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 (143) hide show
  1. {recce_nightly-0.51.0.20250116/recce_nightly.egg-info → recce_nightly-0.51.0.20250120}/PKG-INFO +2 -1
  2. recce_nightly-0.51.0.20250120/recce/VERSION +1 -0
  3. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/adapter/base.py +32 -0
  4. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/adapter/dbt_adapter/__init__.py +67 -0
  5. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/core.py +4 -0
  6. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/404.html +1 -1
  7. recce_nightly-0.51.0.20250116/recce/data/_next/static/chunks/984-b74b3e767a855fd0.js → recce_nightly-0.51.0.20250120/recce/data/_next/static/chunks/323-9565a741f1447d32.js +16 -16
  8. recce_nightly-0.51.0.20250120/recce/data/_next/static/chunks/app/page-0acda55e62045118.js +1 -0
  9. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/index.html +2 -2
  10. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/index.txt +2 -2
  11. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/models/types.py +18 -2
  12. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/server.py +3 -4
  13. recce_nightly-0.51.0.20250120/recce/util/breaking.py +63 -0
  14. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120/recce_nightly.egg-info}/PKG-INFO +2 -1
  15. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce_nightly.egg-info/SOURCES.txt +6 -4
  16. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce_nightly.egg-info/requires.txt +1 -0
  17. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/setup.py +1 -0
  18. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/adapter/dbt_adapter/dbt_test_helper.py +10 -0
  19. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/adapter/dbt_adapter/test_selector.py +2 -2
  20. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/tasks/test_row_count.py +3 -2
  21. recce_nightly-0.51.0.20250120/tests/test_core.py +27 -0
  22. recce_nightly-0.51.0.20250116/recce/VERSION +0 -1
  23. recce_nightly-0.51.0.20250116/recce/data/_next/static/chunks/app/page-f50ed88c73315106.js +0 -1
  24. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/LICENSE +0 -0
  25. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/README.md +0 -0
  26. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/__init__.py +0 -0
  27. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/adapter/__init__.py +0 -0
  28. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/adapter/dbt_adapter/dbt_version.py +0 -0
  29. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/adapter/sqlmesh_adapter.py +0 -0
  30. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/apis/__init__.py +0 -0
  31. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/apis/check_api.py +0 -0
  32. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/apis/check_func.py +0 -0
  33. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/apis/run_api.py +0 -0
  34. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/apis/run_func.py +0 -0
  35. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/artifact.py +0 -0
  36. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/cli.py +0 -0
  37. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/config.py +0 -0
  38. {recce_nightly-0.51.0.20250116/recce/data/_next/static/6ANkv4M7ypHedA7qwoJqp → recce_nightly-0.51.0.20250120/recce/data/_next/static/R7dmZds4xWYx3fGG1bDQE}/_buildManifest.js +0 -0
  39. {recce_nightly-0.51.0.20250116/recce/data/_next/static/6ANkv4M7ypHedA7qwoJqp → recce_nightly-0.51.0.20250120/recce/data/_next/static/R7dmZds4xWYx3fGG1bDQE}/_ssgManifest.js +0 -0
  40. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/157e448a-49151cad1ec51175.js +0 -0
  41. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/29e3cc0d-490dbff344996865.js +0 -0
  42. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/312-3e9b49b718b98737.js +0 -0
  43. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/36e1c10d-3bcdd9bb8564108c.js +0 -0
  44. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/3998a672-e71829c331c77ccb.js +0 -0
  45. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/450c323b-79414be6f43ef15c.js +0 -0
  46. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/47d8844f-ccb4e71fbabd12f3.js +0 -0
  47. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/6dc81886-03da5372308c376d.js +0 -0
  48. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/7a8a3e83-f7fe5f14c56108bf.js +0 -0
  49. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/7f27ae6c-c484e79185298424.js +0 -0
  50. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/868e7b5c-36d94ba5a58a2e6a.js +0 -0
  51. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/9746af58-daab848e55b5faf7.js +0 -0
  52. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/a30376cd-ea4617387c84b12e.js +0 -0
  53. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/app/_not-found/page-c2ee18b5ec3e3d57.js +0 -0
  54. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/app/layout-5b30ab0207459cb8.js +0 -0
  55. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/b3b1872b-97ea0be5bd9b42bc.js +0 -0
  56. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/b63b1b3f-13deddaaba264453.js +0 -0
  57. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/c132bf7d-740a7144e614cb2d.js +0 -0
  58. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/ce84277d-ced9559f73764a27.js +0 -0
  59. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/cf0511cf-88e5bf54e88504a3.js +0 -0
  60. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/fee69bc6-2cf346c884a74e9d.js +0 -0
  61. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/framework-ded83d71b51ce901.js +0 -0
  62. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/main-45628b9d5f140527.js +0 -0
  63. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/main-app-19c0918a6bb54549.js +0 -0
  64. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/pages/_app-ff7f75fed61fbef3.js +0 -0
  65. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/pages/_error-5e587f051118d074.js +0 -0
  66. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -0
  67. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/chunks/webpack-300961f547f48fe7.js +0 -0
  68. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/css/1d7428fe54fca42f.css +0 -0
  69. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/media/montserrat-cyrillic-800-normal.5c8b3804.woff +0 -0
  70. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/media/montserrat-cyrillic-800-normal.c03acce9.woff2 +0 -0
  71. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.83d3554a.woff2 +0 -0
  72. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.8a4a9645.woff +0 -0
  73. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/media/montserrat-latin-800-normal.388abfc2.woff2 +0 -0
  74. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/media/montserrat-latin-800-normal.e7b55ea8.woff +0 -0
  75. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/media/montserrat-latin-ext-800-normal.40cba3c6.woff +0 -0
  76. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/media/montserrat-latin-ext-800-normal.85728e97.woff2 +0 -0
  77. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/media/montserrat-vietnamese-800-normal.0bd05041.woff +0 -0
  78. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/_next/static/media/montserrat-vietnamese-800-normal.dfbbc7ba.woff2 +0 -0
  79. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/favicon.ico +0 -0
  80. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/imgs/feedback/thumbs-down.png +0 -0
  81. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/imgs/feedback/thumbs-up.png +0 -0
  82. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/data/logo/recce-logo-white.png +0 -0
  83. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/diff.py +0 -0
  84. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/event/CONFIG +0 -0
  85. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/event/SENTRY_DNS +0 -0
  86. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/event/__init__.py +0 -0
  87. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/event/collector.py +0 -0
  88. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/event/track.py +0 -0
  89. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/exceptions.py +0 -0
  90. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/git.py +0 -0
  91. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/github.py +0 -0
  92. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/models/__init__.py +0 -0
  93. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/models/check.py +0 -0
  94. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/models/run.py +0 -0
  95. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/pull_request.py +0 -0
  96. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/run.py +0 -0
  97. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/state.py +0 -0
  98. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/summary.py +0 -0
  99. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/tasks/__init__.py +0 -0
  100. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/tasks/core.py +0 -0
  101. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/tasks/dataframe.py +0 -0
  102. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/tasks/histogram.py +0 -0
  103. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/tasks/lineage.py +0 -0
  104. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/tasks/profile.py +0 -0
  105. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/tasks/query.py +0 -0
  106. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/tasks/rowcount.py +0 -0
  107. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/tasks/schema.py +0 -0
  108. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/tasks/top_k.py +0 -0
  109. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/tasks/valuediff.py +0 -0
  110. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/util/__init__.py +0 -0
  111. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/util/cache.py +0 -0
  112. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/util/io.py +0 -0
  113. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/util/logger.py +0 -0
  114. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/util/pydantic_model.py +0 -0
  115. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/util/recce_cloud.py +0 -0
  116. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/util/singleton.py +0 -0
  117. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce/yaml/__init__.py +0 -0
  118. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce_nightly.egg-info/dependency_links.txt +0 -0
  119. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce_nightly.egg-info/entry_points.txt +0 -0
  120. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/recce_nightly.egg-info/top_level.txt +0 -0
  121. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/setup.cfg +0 -0
  122. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/__init__.py +0 -0
  123. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/adapter/__init__.py +0 -0
  124. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/adapter/dbt_adapter/__init__.py +0 -0
  125. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/adapter/dbt_adapter/conftest.py +0 -0
  126. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/adapter/dbt_adapter/test_dbt_adapter.py +0 -0
  127. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/tasks/__init__.py +0 -0
  128. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/tasks/conftest.py +0 -0
  129. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/tasks/test_histogram.py +0 -0
  130. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/tasks/test_lineage.py +0 -0
  131. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/tasks/test_preset_checks.py +0 -0
  132. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/tasks/test_profile.py +0 -0
  133. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/tasks/test_query.py +0 -0
  134. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/tasks/test_schema.py +0 -0
  135. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/tasks/test_top_k.py +0 -0
  136. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/tasks/test_valuediff.py +0 -0
  137. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/test_cli.py +0 -0
  138. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/test_config.py +0 -0
  139. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/test_dbt.py +0 -0
  140. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/test_pull_request.py +0 -0
  141. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/test_server.py +0 -0
  142. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/test_state.py +0 -0
  143. {recce_nightly-0.51.0.20250116 → recce_nightly-0.51.0.20250120}/tests/test_summary.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: recce-nightly
3
- Version: 0.51.0.20250116
3
+ Version: 0.51.0.20250120
4
4
  Summary: Environment diff tool for dbt
5
5
  Home-page: https://github.com/InfuseAI/recce
6
6
  Author: InfuseAI Dev Team
@@ -36,6 +36,7 @@ Requires-Dist: python-dateutil
36
36
  Requires-Dist: python-multipart
37
37
  Requires-Dist: GitPython
38
38
  Requires-Dist: PyGithub
39
+ Requires-Dist: sqlglot
39
40
  Provides-Extra: dev
40
41
  Requires-Dist: pytest>=4.6; extra == "dev"
41
42
  Requires-Dist: pytest-flake8; extra == "dev"
@@ -0,0 +1 @@
1
+ 0.51.0.20250120
@@ -2,6 +2,7 @@ import logging
2
2
  from abc import ABC, abstractmethod
3
3
  from typing import Optional, Callable, Set, Literal
4
4
 
5
+ from recce.models.types import LineageDiff, NodeDiff
5
6
  from recce.state import ArtifactsRoot
6
7
 
7
8
  # from dbt.contracts.graph.nodes import ManifestNode
@@ -19,6 +20,37 @@ class BaseAdapter(ABC):
19
20
  def get_lineage(self, base: Optional[bool] = False):
20
21
  raise NotImplementedError()
21
22
 
23
+ def get_lineage_diff(self) -> LineageDiff:
24
+ base = self.get_lineage(base=True)
25
+ current = self.get_lineage(base=False)
26
+ keys = {
27
+ *base.get('nodes', {}).keys(),
28
+ *current.get('nodes', {}).keys()
29
+ }
30
+
31
+ # for each node, compare the base and current lineage
32
+ diff = {}
33
+ for key in keys:
34
+ base_node = base.get('nodes', {}).get(key)
35
+ curr_node = current.get('nodes', {}).get(key)
36
+ if base_node and curr_node:
37
+ base_checksum = base_node.get('checksum', {}).get('checksum')
38
+ curr_checksum = curr_node.get('checksum', {}).get('checksum')
39
+
40
+ if base_checksum is not None and base_checksum == curr_checksum:
41
+ continue
42
+
43
+ diff[key] = NodeDiff(change_status='modified', change_category='breaking')
44
+ elif base_node:
45
+ diff[key] = NodeDiff(chnage_status='removed')
46
+ elif curr_node:
47
+ diff[key] = NodeDiff(change_status='added')
48
+ return LineageDiff(
49
+ base=base,
50
+ current=current,
51
+ diff=diff,
52
+ )
53
+
22
54
  @abstractmethod
23
55
  def select_nodes(
24
56
  self,
@@ -5,6 +5,7 @@ import uuid
5
5
  from contextlib import contextmanager
6
6
  from dataclasses import dataclass, fields
7
7
  from errno import ENOENT
8
+ from functools import lru_cache
8
9
  from pathlib import Path
9
10
  from typing import Callable, Dict, List, Optional, Tuple, Iterator, Any, Set, Union, Literal, Type
10
11
 
@@ -18,6 +19,7 @@ from recce.adapter.base import BaseAdapter
18
19
  from recce.state import ArtifactsRoot
19
20
  from .dbt_version import DbtVersion
20
21
  from ...models import RunType
22
+ from ...models.types import LineageDiff, NodeDiff
21
23
  from ...tasks import Task, QueryTask, QueryBaseTask, QueryDiffTask, ValueDiffTask, ValueDiffDetailTask, ProfileDiffTask, \
22
24
  RowCountDiffTask, TopKDiffTask, HistogramDiffTask
23
25
 
@@ -537,6 +539,23 @@ class DbtAdapter(BaseAdapter):
537
539
  def get_lineage(self, base: Optional[bool] = False):
538
540
  manifest = self.curr_manifest if base is False else self.base_manifest
539
541
  catalog = self.curr_catalog if base is False else self.base_catalog
542
+ cache_key = hash((id(manifest), id(catalog)))
543
+ return self.get_lineage_cached(base, cache_key)
544
+
545
+ def get_lineage_diff(self) -> LineageDiff:
546
+ cache_key = hash((
547
+ id(self.base_manifest),
548
+ id(self.base_catalog),
549
+ id(self.curr_manifest),
550
+ id(self.curr_catalog),
551
+ ))
552
+ return self._get_lineage_diff_cached(cache_key)
553
+
554
+ @lru_cache(maxsize=2)
555
+ def get_lineage_cached(self, base: Optional[bool] = False, cache_key=0):
556
+ manifest = self.curr_manifest if base is False else self.base_manifest
557
+ catalog = self.curr_catalog if base is False else self.base_catalog
558
+
540
559
  manifest_metadata = manifest.metadata if manifest is not None else None
541
560
  catalog_metadata = catalog.metadata if catalog is not None else None
542
561
 
@@ -658,6 +677,48 @@ class DbtAdapter(BaseAdapter):
658
677
  catalog_metadata=catalog_metadata,
659
678
  )
660
679
 
680
+ @lru_cache(maxsize=1)
681
+ def _get_lineage_diff_cached(self, cache_key) -> LineageDiff:
682
+ base = self.get_lineage(base=True)
683
+ current = self.get_lineage(base=False)
684
+ keys = {
685
+ *base.get('nodes', {}).keys(),
686
+ *current.get('nodes', {}).keys()
687
+ }
688
+
689
+ # for each node, compare the base and current lineage
690
+ diff = {}
691
+ for key in keys:
692
+ base_node = base.get('nodes', {}).get(key)
693
+ curr_node = current.get('nodes', {}).get(key)
694
+ if base_node and curr_node:
695
+ base_checksum = base_node.get('checksum', {}).get('checksum')
696
+ curr_checksum = curr_node.get('checksum', {}).get('checksum')
697
+ if base_checksum is None or curr_checksum is None or base_checksum == curr_checksum:
698
+ continue
699
+
700
+ change_category = 'breaking'
701
+ if curr_node.get('resource_type') == 'model':
702
+ try:
703
+ from recce.util.breaking import is_breaking_change
704
+ base_sql = self.generate_sql(base_node.get('raw_code'))
705
+ curr_sql = self.generate_sql(curr_node.get('raw_code'))
706
+ if not is_breaking_change(base_sql, curr_sql):
707
+ change_category = 'non-breaking'
708
+ except Exception:
709
+ pass
710
+
711
+ diff[key] = NodeDiff(change_status='modified', change_category=change_category)
712
+ elif base_node:
713
+ diff[key] = NodeDiff(chnage_status='removed')
714
+ elif curr_node:
715
+ diff[key] = NodeDiff(change_status='added')
716
+ return LineageDiff(
717
+ base=base,
718
+ current=current,
719
+ diff=diff,
720
+ )
721
+
661
722
  def get_manifests_by_id(self, unique_id: str):
662
723
  curr_manifest = self.get_manifest(base=False)
663
724
  base_manifest = self.get_manifest(base=True)
@@ -916,3 +977,9 @@ class DbtAdapter(BaseAdapter):
916
977
 
917
978
  def cancel(self, connection: Connection):
918
979
  self.adapter.connections.cancel(connection)
980
+
981
+ def __hash__(self):
982
+ return id(self)
983
+
984
+ def __eq__(self, other):
985
+ return self.__hash__() == other.__hash__()
@@ -7,6 +7,7 @@ from typing import Callable, Dict, Optional, List, Tuple
7
7
 
8
8
  from recce.adapter.base import BaseAdapter
9
9
  from recce.models import Check, Run
10
+ from recce.models.types import LineageDiff
10
11
  from recce.state import RecceState, RecceStateMetadata, GitRepoInfo, PullRequestInfo, RecceStateLoader
11
12
  from recce.util.recce_cloud import set_recce_cloud_onboarding_state
12
13
 
@@ -67,6 +68,9 @@ class RecceContext:
67
68
  def get_lineage(self, base: Optional[bool] = False):
68
69
  return self.adapter.get_lineage(base=base)
69
70
 
71
+ def get_lineage_diff(self) -> LineageDiff:
72
+ return self.adapter.get_lineage_diff()
73
+
70
74
  def build_name_to_unique_id_index(self) -> Dict[str, str]:
71
75
  name_to_unique_id = {}
72
76
  curr = self.get_lineage(base=False)
@@ -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\":\"6ANkv4M7ypHedA7qwoJqp\",\"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\":\"R7dmZds4xWYx3fGG1bDQE\",\"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>