recce-nightly 0.62.0.20250417__py3-none-any.whl → 1.30.0.20251221__py3-none-any.whl

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.

Potentially problematic release.


This version of recce-nightly might be problematic. Click here for more details.

Files changed (245) hide show
  1. recce/VERSION +1 -1
  2. recce/__init__.py +27 -22
  3. recce/adapter/base.py +11 -14
  4. recce/adapter/dbt_adapter/__init__.py +845 -461
  5. recce/adapter/dbt_adapter/dbt_version.py +3 -0
  6. recce/adapter/sqlmesh_adapter.py +24 -35
  7. recce/apis/check_api.py +59 -42
  8. recce/apis/check_events_api.py +353 -0
  9. recce/apis/check_func.py +41 -35
  10. recce/apis/run_api.py +25 -19
  11. recce/apis/run_func.py +64 -25
  12. recce/artifact.py +119 -51
  13. recce/cli.py +1301 -324
  14. recce/config.py +43 -34
  15. recce/connect_to_cloud.py +138 -0
  16. recce/core.py +55 -47
  17. recce/data/404/index.html +2 -0
  18. recce/data/404.html +2 -1
  19. recce/data/__next.@lineage.!KHNsb3Qp.__PAGE__.txt +7 -0
  20. recce/data/__next.@lineage.!KHNsb3Qp.txt +4 -0
  21. recce/data/__next.__PAGE__.txt +6 -0
  22. recce/data/__next._full.txt +32 -0
  23. recce/data/__next._head.txt +8 -0
  24. recce/data/__next._index.txt +14 -0
  25. recce/data/__next._tree.txt +8 -0
  26. recce/data/_next/static/chunks/025a7e3e3f9f40ae.js +1 -0
  27. recce/data/_next/static/chunks/0ce56d67ef5779ca.js +4 -0
  28. recce/data/_next/static/chunks/1a6a78780155dac7.js +48 -0
  29. recce/data/_next/static/chunks/1de8485918b9182a.css +2 -0
  30. recce/data/_next/static/chunks/1e4b1b50d1e34993.js +1 -0
  31. recce/data/_next/static/chunks/206d5d181e4c738e.js +1 -0
  32. recce/data/_next/static/chunks/2c357efc34c5b859.js +25 -0
  33. recce/data/_next/static/chunks/2e9d95d2d48c479c.js +1 -0
  34. recce/data/_next/static/chunks/2f016dc4a3edad2e.js +2 -0
  35. recce/data/_next/static/chunks/313251962d698f7c.js +1 -0
  36. recce/data/_next/static/chunks/3a9f021f38eb5574.css +1 -0
  37. recce/data/_next/static/chunks/40079da8d2b8f651.js +1 -0
  38. recce/data/_next/static/chunks/4599182bffb64661.js +38 -0
  39. recce/data/_next/static/chunks/4e62f6e184173580.js +1 -0
  40. recce/data/_next/static/chunks/5c4dfb0d09eaa401.js +1 -0
  41. recce/data/_next/static/chunks/69e4f06ccfdfc3ac.js +1 -0
  42. recce/data/_next/static/chunks/6b206cb4707d6bee.js +1 -0
  43. recce/data/_next/static/chunks/6d8557f062aa4386.css +1 -0
  44. recce/data/_next/static/chunks/7fbe3650bd83b6b5.js +1 -0
  45. recce/data/_next/static/chunks/83fa823a825674f6.js +1 -0
  46. recce/data/_next/static/chunks/848a6c9b5f55f7ed.js +1 -0
  47. recce/data/_next/static/chunks/859462b0858aef88.css +2 -0
  48. recce/data/_next/static/chunks/923964f18c87d0f1.css +1 -0
  49. recce/data/_next/static/chunks/939390f911895d7c.js +48 -0
  50. recce/data/_next/static/chunks/99a9817237a07f43.js +1 -0
  51. recce/data/_next/static/chunks/9fed8b4b2b924054.js +5 -0
  52. recce/data/_next/static/chunks/b6949f6c5892110c.js +1 -0
  53. recce/data/_next/static/chunks/b851a1d3f8149828.js +1 -0
  54. recce/data/_next/static/chunks/c734f9ad957de0b4.js +1 -0
  55. recce/data/_next/static/chunks/cdde321b0ec75717.js +2 -0
  56. recce/data/_next/static/chunks/d0f91117d77ff844.css +1 -0
  57. recce/data/_next/static/chunks/d6c8667911c2500f.js +1 -0
  58. recce/data/_next/static/chunks/da8dab68c02752cf.js +74 -0
  59. recce/data/_next/static/chunks/dc074049c9d12d97.js +109 -0
  60. recce/data/_next/static/chunks/ee7f1a8227342421.js +1 -0
  61. recce/data/_next/static/chunks/fa2f4e56c2fccc73.js +1 -0
  62. recce/data/_next/static/chunks/turbopack-1fad664f62979b93.js +3 -0
  63. recce/data/_next/static/media/favicon.a8d38d84.ico +0 -0
  64. recce/data/_next/static/media/montserrat-cyrillic-800-normal.d80d830d.woff2 +0 -0
  65. recce/data/_next/static/media/montserrat-cyrillic-800-normal.f9d58125.woff +0 -0
  66. recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.076c2a93.woff2 +0 -0
  67. recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.a4fa76b5.woff +0 -0
  68. recce/data/_next/static/media/montserrat-latin-800-normal.cde454cc.woff2 +0 -0
  69. recce/data/_next/static/media/montserrat-latin-800-normal.d5761935.woff +0 -0
  70. recce/data/_next/static/media/montserrat-latin-ext-800-normal.40ec0659.woff2 +0 -0
  71. recce/data/_next/static/media/montserrat-latin-ext-800-normal.b671449b.woff +0 -0
  72. recce/data/_next/static/media/montserrat-vietnamese-800-normal.9f7b8541.woff +0 -0
  73. recce/data/_next/static/media/montserrat-vietnamese-800-normal.f9eb854e.woff2 +0 -0
  74. recce/data/_next/static/nX-Uz0AH6Tc6hIQUFGqaB/_buildManifest.js +11 -0
  75. recce/data/_next/static/nX-Uz0AH6Tc6hIQUFGqaB/_clientMiddlewareManifest.json +1 -0
  76. recce/data/_not-found/__next._full.txt +24 -0
  77. recce/data/_not-found/__next._head.txt +8 -0
  78. recce/data/_not-found/__next._index.txt +13 -0
  79. recce/data/_not-found/__next._not-found.__PAGE__.txt +5 -0
  80. recce/data/_not-found/__next._not-found.txt +4 -0
  81. recce/data/_not-found/__next._tree.txt +6 -0
  82. recce/data/_not-found/index.html +2 -0
  83. recce/data/_not-found/index.txt +24 -0
  84. recce/data/auth_callback.html +68 -0
  85. recce/data/checks/__next.@lineage.__DEFAULT__.txt +7 -0
  86. recce/data/checks/__next._full.txt +39 -0
  87. recce/data/checks/__next._head.txt +8 -0
  88. recce/data/checks/__next._index.txt +14 -0
  89. recce/data/checks/__next._tree.txt +8 -0
  90. recce/data/checks/__next.checks.__PAGE__.txt +10 -0
  91. recce/data/checks/__next.checks.txt +4 -0
  92. recce/data/checks/index.html +2 -0
  93. recce/data/checks/index.txt +39 -0
  94. recce/data/imgs/reload-image.svg +4 -0
  95. recce/data/index.html +2 -27
  96. recce/data/index.txt +32 -7
  97. recce/data/lineage/__next.@lineage.__DEFAULT__.txt +7 -0
  98. recce/data/lineage/__next._full.txt +39 -0
  99. recce/data/lineage/__next._head.txt +8 -0
  100. recce/data/lineage/__next._index.txt +14 -0
  101. recce/data/lineage/__next._tree.txt +8 -0
  102. recce/data/lineage/__next.lineage.__PAGE__.txt +10 -0
  103. recce/data/lineage/__next.lineage.txt +4 -0
  104. recce/data/lineage/index.html +2 -0
  105. recce/data/lineage/index.txt +39 -0
  106. recce/data/query/__next.@lineage.__DEFAULT__.txt +7 -0
  107. recce/data/query/__next._full.txt +37 -0
  108. recce/data/query/__next._head.txt +8 -0
  109. recce/data/query/__next._index.txt +14 -0
  110. recce/data/query/__next._tree.txt +8 -0
  111. recce/data/query/__next.query.__PAGE__.txt +9 -0
  112. recce/data/query/__next.query.txt +4 -0
  113. recce/data/query/index.html +2 -0
  114. recce/data/query/index.txt +37 -0
  115. recce/diff.py +6 -12
  116. recce/event/CONFIG.bak +1 -0
  117. recce/event/__init__.py +86 -74
  118. recce/event/collector.py +33 -22
  119. recce/event/track.py +49 -27
  120. recce/exceptions.py +1 -1
  121. recce/git.py +7 -7
  122. recce/github.py +57 -53
  123. recce/mcp_server.py +725 -0
  124. recce/models/__init__.py +4 -1
  125. recce/models/check.py +438 -21
  126. recce/models/run.py +1 -0
  127. recce/models/types.py +134 -28
  128. recce/pull_request.py +27 -25
  129. recce/run.py +179 -122
  130. recce/server.py +394 -104
  131. recce/state/__init__.py +31 -0
  132. recce/state/cloud.py +644 -0
  133. recce/state/const.py +26 -0
  134. recce/state/local.py +56 -0
  135. recce/state/state.py +119 -0
  136. recce/state/state_loader.py +174 -0
  137. recce/summary.py +196 -149
  138. recce/tasks/__init__.py +19 -3
  139. recce/tasks/core.py +11 -13
  140. recce/tasks/dataframe.py +82 -18
  141. recce/tasks/histogram.py +69 -34
  142. recce/tasks/lineage.py +2 -2
  143. recce/tasks/profile.py +152 -86
  144. recce/tasks/query.py +180 -89
  145. recce/tasks/rowcount.py +37 -31
  146. recce/tasks/schema.py +18 -15
  147. recce/tasks/top_k.py +35 -35
  148. recce/tasks/utils.py +147 -0
  149. recce/tasks/valuediff.py +247 -155
  150. recce/util/__init__.py +3 -0
  151. recce/util/api_token.py +80 -0
  152. recce/util/breaking.py +105 -100
  153. recce/util/cll.py +274 -219
  154. recce/util/cloud/__init__.py +15 -0
  155. recce/util/cloud/base.py +115 -0
  156. recce/util/cloud/check_events.py +190 -0
  157. recce/util/cloud/checks.py +242 -0
  158. recce/util/io.py +22 -17
  159. recce/util/lineage.py +65 -16
  160. recce/util/logger.py +1 -1
  161. recce/util/onboarding_state.py +45 -0
  162. recce/util/perf_tracking.py +85 -0
  163. recce/util/recce_cloud.py +347 -72
  164. recce/util/singleton.py +4 -4
  165. recce/util/startup_perf.py +121 -0
  166. recce/yaml/__init__.py +7 -10
  167. recce_nightly-1.30.0.20251221.dist-info/METADATA +195 -0
  168. recce_nightly-1.30.0.20251221.dist-info/RECORD +183 -0
  169. {recce_nightly-0.62.0.20250417.dist-info → recce_nightly-1.30.0.20251221.dist-info}/WHEEL +1 -2
  170. recce/data/_next/static/chunks/1f229bf6-d9fe92e56db8d93b.js +0 -1
  171. recce/data/_next/static/chunks/29e3cc0d-8c150e37dff9631b.js +0 -1
  172. recce/data/_next/static/chunks/36e1c10d-bb0210cbd6573a8d.js +0 -1
  173. recce/data/_next/static/chunks/3998a672-eaad84bdd88cc73e.js +0 -1
  174. recce/data/_next/static/chunks/450c323b-1bb5db526e54435a.js +0 -1
  175. recce/data/_next/static/chunks/47d8844f-79a1b53c66a7d7ec.js +0 -1
  176. recce/data/_next/static/chunks/500-e51c92a025a51234.js +0 -65
  177. recce/data/_next/static/chunks/6dc81886-c94b9b91bc2c3caf.js +0 -1
  178. recce/data/_next/static/chunks/700-3b65fc3666820d00.js +0 -2
  179. recce/data/_next/static/chunks/7a8a3e83-d7fa409d97b38b2b.js +0 -1
  180. recce/data/_next/static/chunks/7f27ae6c-413f6b869a04183a.js +0 -1
  181. recce/data/_next/static/chunks/9746af58-d74bef4d03eea6ab.js +0 -1
  182. recce/data/_next/static/chunks/a30376cd-7d806e1602f2dc3a.js +0 -1
  183. recce/data/_next/static/chunks/app/_not-found/page-8a886fa0855c3105.js +0 -1
  184. recce/data/_next/static/chunks/app/layout-9102e22cb73f74d6.js +0 -1
  185. recce/data/_next/static/chunks/app/page-9adc25782272ed2e.js +0 -1
  186. recce/data/_next/static/chunks/b63b1b3f-7395c74e11a14e95.js +0 -1
  187. recce/data/_next/static/chunks/c132bf7d-8102037f9ccf372a.js +0 -1
  188. recce/data/_next/static/chunks/c1ceaa8b-a1e442154d23515e.js +0 -1
  189. recce/data/_next/static/chunks/cd9f8d63-cf0d5a7b0f7a92e8.js +0 -54
  190. recce/data/_next/static/chunks/ce84277d-f42c2c58049cea2d.js +0 -1
  191. recce/data/_next/static/chunks/e24bf851-0f8cbc99656833e7.js +0 -1
  192. recce/data/_next/static/chunks/fee69bc6-f17d36c080742e74.js +0 -1
  193. recce/data/_next/static/chunks/framework-ded83d71b51ce901.js +0 -1
  194. recce/data/_next/static/chunks/main-a0859f1f36d0aa6c.js +0 -1
  195. recce/data/_next/static/chunks/main-app-0225a2255968e566.js +0 -1
  196. recce/data/_next/static/chunks/pages/_app-d5672bf3d8b6371b.js +0 -1
  197. recce/data/_next/static/chunks/pages/_error-ed75be3f25588548.js +0 -1
  198. recce/data/_next/static/chunks/webpack-567d72f0bc0820d5.js +0 -1
  199. recce/data/_next/static/css/c9ecb46a4b21c126.css +0 -14
  200. recce/data/_next/static/media/montserrat-cyrillic-800-normal.22628180.woff2 +0 -0
  201. recce/data/_next/static/media/montserrat-cyrillic-800-normal.31d693bb.woff +0 -0
  202. recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.7e2c1e62.woff +0 -0
  203. recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.94a63aea.woff2 +0 -0
  204. recce/data/_next/static/media/montserrat-latin-800-normal.6f8fa298.woff2 +0 -0
  205. recce/data/_next/static/media/montserrat-latin-800-normal.97e20d5e.woff +0 -0
  206. recce/data/_next/static/media/montserrat-latin-ext-800-normal.013b84f9.woff2 +0 -0
  207. recce/data/_next/static/media/montserrat-latin-ext-800-normal.aff52ab0.woff +0 -0
  208. recce/data/_next/static/media/montserrat-vietnamese-800-normal.5f21869b.woff +0 -0
  209. recce/data/_next/static/media/montserrat-vietnamese-800-normal.c0035377.woff2 +0 -0
  210. recce/data/_next/static/qiyFlux77VkhxiceAJe_F/_buildManifest.js +0 -1
  211. recce/state.py +0 -753
  212. recce_nightly-0.62.0.20250417.dist-info/METADATA +0 -311
  213. recce_nightly-0.62.0.20250417.dist-info/RECORD +0 -139
  214. recce_nightly-0.62.0.20250417.dist-info/top_level.txt +0 -2
  215. tests/__init__.py +0 -0
  216. tests/adapter/__init__.py +0 -0
  217. tests/adapter/dbt_adapter/__init__.py +0 -0
  218. tests/adapter/dbt_adapter/conftest.py +0 -13
  219. tests/adapter/dbt_adapter/dbt_test_helper.py +0 -283
  220. tests/adapter/dbt_adapter/test_dbt_adapter.py +0 -40
  221. tests/adapter/dbt_adapter/test_dbt_cll.py +0 -102
  222. tests/adapter/dbt_adapter/test_selector.py +0 -177
  223. tests/tasks/__init__.py +0 -0
  224. tests/tasks/conftest.py +0 -4
  225. tests/tasks/test_histogram.py +0 -137
  226. tests/tasks/test_lineage.py +0 -42
  227. tests/tasks/test_preset_checks.py +0 -50
  228. tests/tasks/test_profile.py +0 -73
  229. tests/tasks/test_query.py +0 -151
  230. tests/tasks/test_row_count.py +0 -116
  231. tests/tasks/test_schema.py +0 -99
  232. tests/tasks/test_top_k.py +0 -73
  233. tests/tasks/test_valuediff.py +0 -74
  234. tests/test_cli.py +0 -122
  235. tests/test_config.py +0 -45
  236. tests/test_core.py +0 -27
  237. tests/test_dbt.py +0 -36
  238. tests/test_pull_request.py +0 -130
  239. tests/test_server.py +0 -98
  240. tests/test_state.py +0 -123
  241. tests/test_summary.py +0 -57
  242. /recce/data/_next/static/chunks/{polyfills-42372ed130431b0a.js → a6dad97d9634a72d.js} +0 -0
  243. /recce/data/_next/static/{qiyFlux77VkhxiceAJe_F → nX-Uz0AH6Tc6hIQUFGqaB}/_ssgManifest.js +0 -0
  244. {recce_nightly-0.62.0.20250417.dist-info → recce_nightly-1.30.0.20251221.dist-info}/entry_points.txt +0 -0
  245. {recce_nightly-0.62.0.20250417.dist-info → recce_nightly-1.30.0.20251221.dist-info}/licenses/LICENSE +0 -0
recce/models/types.py CHANGED
@@ -1,26 +1,28 @@
1
1
  import uuid
2
2
  from datetime import datetime, timezone
3
3
  from enum import Enum
4
- from typing import Optional, Literal
4
+ from typing import Dict, List, Literal, Optional, Set
5
5
 
6
- from pydantic import BaseModel, UUID4, Field
6
+ from pydantic import UUID4, BaseModel, Field
7
+
8
+ from recce.util.pydantic_model import pydantic_model_dump
7
9
 
8
10
 
9
11
  class RunType(Enum):
10
- SIMPLE = 'simple'
12
+ SIMPLE = "simple"
11
13
  QUERY = "query"
12
- QUERY_BASE = 'query_base'
13
- QUERY_DIFF = 'query_diff'
14
- VALUE_DIFF = 'value_diff'
15
- VALUE_DIFF_DETAIL = 'value_diff_detail'
16
- SCHEMA_DIFF = 'schema_diff'
17
- PROFILE = 'profile'
18
- PROFILE_DIFF = 'profile_diff'
19
- ROW_COUNT = 'row_count'
20
- ROW_COUNT_DIFF = 'row_count_diff'
21
- LINEAGE_DIFF = 'lineage_diff'
22
- TOP_K_DIFF = 'top_k_diff'
23
- HISTOGRAM_DIFF = 'histogram_diff'
14
+ QUERY_BASE = "query_base"
15
+ QUERY_DIFF = "query_diff"
16
+ VALUE_DIFF = "value_diff"
17
+ VALUE_DIFF_DETAIL = "value_diff_detail"
18
+ SCHEMA_DIFF = "schema_diff"
19
+ PROFILE = "profile"
20
+ PROFILE_DIFF = "profile_diff"
21
+ ROW_COUNT = "row_count"
22
+ ROW_COUNT_DIFF = "row_count_diff"
23
+ LINEAGE_DIFF = "lineage_diff"
24
+ TOP_K_DIFF = "top_k_diff"
25
+ HISTOGRAM_DIFF = "histogram_diff"
24
26
 
25
27
  def __str__(self):
26
28
  return self.value
@@ -32,12 +34,10 @@ class RunProgress(BaseModel):
32
34
 
33
35
 
34
36
  class RunStatus(Enum):
35
- FINISHED = 'finished'
36
- FAILED = 'failed'
37
- CANCELLED = 'cancelled'
38
- RUNNING = 'running'
39
- # This is a special status only in v0.36.0. Replaced by FINISHED. To be removed in the future.
40
- SUCCESSFUL = 'successful'
37
+ FINISHED = "finished"
38
+ FAILED = "failed"
39
+ CANCELLED = "cancelled"
40
+ RUNNING = "running"
41
41
 
42
42
 
43
43
  class Run(BaseModel):
@@ -52,6 +52,39 @@ class Run(BaseModel):
52
52
  run_id: UUID4 = Field(default_factory=uuid.uuid4)
53
53
  run_at: str = Field(default_factory=lambda: datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"))
54
54
 
55
+ def __init__(self, **data):
56
+ type = data.get("type")
57
+
58
+ if "result" in data and data["result"] is not None:
59
+ result = data.get("result")
60
+
61
+ if type in [RunType.QUERY.value, RunType.QUERY_BASE.value]:
62
+ from recce.tasks.query import QueryResult
63
+
64
+ data["result"] = pydantic_model_dump(QueryResult(**result))
65
+ elif type == RunType.QUERY_DIFF.value:
66
+ from recce.tasks.query import QueryDiffResult
67
+
68
+ data["result"] = pydantic_model_dump(QueryDiffResult(**result))
69
+ elif type == RunType.PROFILE.value:
70
+ from recce.tasks.profile import ProfileResult
71
+
72
+ data["result"] = pydantic_model_dump(ProfileResult(**result))
73
+ elif type == RunType.PROFILE_DIFF.value:
74
+ from recce.tasks.profile import ProfileDiffResult
75
+
76
+ data["result"] = pydantic_model_dump(ProfileDiffResult(**result))
77
+ elif type == RunType.VALUE_DIFF.value:
78
+ from recce.tasks.valuediff import ValueDiffResult
79
+
80
+ data["result"] = pydantic_model_dump(ValueDiffResult(**result))
81
+ elif type == RunType.VALUE_DIFF_DETAIL.value:
82
+ from recce.tasks.valuediff import ValueDiffDetailResult
83
+
84
+ data["result"] = pydantic_model_dump(ValueDiffDetailResult(**result))
85
+
86
+ super().__init__(**data)
87
+
55
88
 
56
89
  class Check(BaseModel):
57
90
  name: str
@@ -60,8 +93,11 @@ class Check(BaseModel):
60
93
  params: Optional[dict] = {}
61
94
  view_options: Optional[dict] = {}
62
95
  check_id: UUID4 = Field(default_factory=uuid.uuid4)
96
+ session_id: Optional[UUID4] = Field(default=None)
63
97
  is_checked: bool = False
64
98
  is_preset: bool = False
99
+ created_by: Optional[str] = None
100
+ updated_by: Optional[str] = None
65
101
  created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc).replace(microsecond=0))
66
102
  updated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc).replace(microsecond=0))
67
103
 
@@ -84,15 +120,15 @@ class Check(BaseModel):
84
120
 
85
121
 
86
122
  ChangeStatus = Literal[
87
- 'added',
88
- 'removed',
89
- 'modified',
123
+ "added",
124
+ "removed",
125
+ "modified",
90
126
  ]
91
127
  ChangeCategory = Literal[
92
- 'breaking',
93
- 'non_breaking',
94
- 'partial_breaking',
95
- 'unknown',
128
+ "breaking",
129
+ "non_breaking",
130
+ "partial_breaking",
131
+ "unknown",
96
132
  ]
97
133
 
98
134
 
@@ -110,3 +146,73 @@ class LineageDiff(BaseModel):
110
146
  base: dict
111
147
  current: dict
112
148
  diff: dict[str, NodeDiff]
149
+
150
+
151
+ # Column Level Linage
152
+ class CllColumnDep(BaseModel):
153
+ node: str
154
+ column: str
155
+
156
+
157
+ class CllColumn(BaseModel):
158
+ id: Optional[str] = None
159
+ table_id: Optional[str] = None
160
+ name: Optional[str] = None
161
+
162
+ # data type
163
+ type: Optional[str] = None
164
+
165
+ # transformation type
166
+ transformation_type: Literal["source", "passthrough", "renamed", "derived", "unknown"] = "unknown"
167
+
168
+ # change analysis
169
+ change_status: Optional[ChangeStatus] = None
170
+
171
+ # column-to-column dependencies
172
+ depends_on: List[CllColumnDep] = Field(default_factory=list)
173
+
174
+
175
+ class CllNode(BaseModel):
176
+ id: str
177
+ name: str
178
+ package_name: str
179
+ resource_type: str
180
+ raw_code: Optional[str] = None
181
+ source_name: Optional[str] = None
182
+
183
+ # change analysis
184
+ change_status: Optional[ChangeStatus] = None
185
+ change_category: Optional[ChangeCategory] = None
186
+
187
+ # Column to column dependencies
188
+ columns: Dict[str, CllColumn] = Field(default_factory=dict)
189
+
190
+ # If the node is impacted. Only used if option 'change_analysis' is set
191
+ impacted: Optional[bool] = None
192
+
193
+ @classmethod
194
+ def build_cll_node(cls, manifest, resource_key, node_id) -> Optional["CllNode"]:
195
+ resources = getattr(manifest, resource_key)
196
+ if node_id not in resources:
197
+ return None
198
+ n = resources[node_id]
199
+ if resource_key == "nodes" and n.resource_type not in ["model", "seed", "snapshot"]:
200
+ return None
201
+ cll_node = CllNode(
202
+ id=n.unique_id,
203
+ name=n.name,
204
+ package_name=n.package_name,
205
+ resource_type=n.resource_type,
206
+ )
207
+ if resource_key == "sources":
208
+ cll_node.source_name = n.source_name
209
+ elif resource_key == "nodes":
210
+ cll_node.raw_code = n.raw_code
211
+ return cll_node
212
+
213
+
214
+ class CllData(BaseModel):
215
+ nodes: Dict[str, CllNode] = Field(default_factory=dict)
216
+ columns: Dict[str, CllColumn] = Field(default_factory=dict)
217
+ parent_map: Dict[str, Set[str]] = Field(default_factory=dict)
218
+ child_map: Dict[str, Set[str]] = Field(default_factory=dict)
recce/pull_request.py CHANGED
@@ -28,14 +28,14 @@ def fetch_pr_metadata(**kwargs):
28
28
  # fetch from github action event path
29
29
  metadata = fetch_pr_metadata_from_event_path()
30
30
  if metadata is not None:
31
- pr_info.id = metadata.get('github_pr_id')
32
- pr_info.url = metadata.get('github_pr_url')
33
- pr_info.title = metadata.get('github_pr_title')
34
- pr_info.repository = metadata.get('github_repository')
31
+ pr_info.id = metadata.get("github_pr_id")
32
+ pr_info.url = metadata.get("github_pr_url")
33
+ pr_info.title = metadata.get("github_pr_title")
34
+ pr_info.repository = metadata.get("github_repository")
35
35
  else:
36
36
  repo = hosting_repo()
37
- pr, message = recce_pr_information(github_token=kwargs.get('github_token'))
38
- if kwargs.get('cloud') and message:
37
+ pr, message = recce_pr_information(github_token=kwargs.get("github_token"))
38
+ if kwargs.get("cloud") and message:
39
39
  print(message)
40
40
 
41
41
  if pr:
@@ -47,14 +47,14 @@ def fetch_pr_metadata(**kwargs):
47
47
  pr_info.branch = pr.head.ref
48
48
 
49
49
  # fetch from cli arguments
50
- if pr_info.url is None and 'github_pull_request_url' in kwargs:
51
- pr_info.url = kwargs.get('github_pull_request_url')
50
+ if pr_info.url is None and "github_pull_request_url" in kwargs:
51
+ pr_info.url = kwargs.get("github_pull_request_url")
52
52
 
53
53
  if pr_info.branch is None:
54
- pr_info.branch = kwargs.get('git_current_branch')
54
+ pr_info.branch = kwargs.get("git_current_branch")
55
55
 
56
56
  if pr_info.base_branch is None:
57
- pr_info.base_branch = kwargs.get('git_base_branch')
57
+ pr_info.base_branch = kwargs.get("git_base_branch")
58
58
 
59
59
  # fetch from env
60
60
  if pr_info.url is None:
@@ -65,17 +65,17 @@ def fetch_pr_metadata(**kwargs):
65
65
 
66
66
  def fetch_pr_metadata_from_event_path() -> Optional[dict]:
67
67
  """
68
- If recce run is running in a GitHub Action, this function will return the pull request metadata.
68
+ If recce run is running in a GitHub Action, this function will return the pull request metadata.
69
69
 
70
- Example:
71
- {
72
- "github_pr_id": 1,
73
- "github_pr_url": "https://github.com/xyz/abc/pull/1,
74
- "github_pr_title": "Update README.md",
75
- "github_repository": "xyz/abc"
76
- }
70
+ Example:
71
+ {
72
+ "github_pr_id": 1,
73
+ "github_pr_url": "https://github.com/xyz/abc/pull/1,
74
+ "github_pr_title": "Update README.md",
75
+ "github_repository": "xyz/abc"
76
+ }
77
77
 
78
- :return: dict
78
+ :return: dict
79
79
  """
80
80
 
81
81
  # get the event json from the path in GITHUB_EVENT_PATH
@@ -83,7 +83,7 @@ def fetch_pr_metadata_from_event_path() -> Optional[dict]:
83
83
  github_repository = os.getenv("GITHUB_REPOSITORY")
84
84
  if event_path:
85
85
  try:
86
- with open(event_path, "r") as event_file:
86
+ with open(event_path, "r", encoding="utf-8") as event_file:
87
87
  event_data = json.load(event_file)
88
88
 
89
89
  pr_id = event_data["number"]
@@ -92,10 +92,12 @@ def fetch_pr_metadata_from_event_path() -> Optional[dict]:
92
92
  pr_url = pull_request_data["_links"]["html"]["href"]
93
93
  pr_api = pull_request_data["_links"]["self"]["href"]
94
94
  pr_title = _fetch_pr_title(pr_api)
95
- return dict(github_pr_id=pr_id,
96
- github_pr_url=pr_url,
97
- github_pr_title=pr_title,
98
- github_repository=github_repository)
95
+ return dict(
96
+ github_pr_id=pr_id,
97
+ github_pr_url=pr_url,
98
+ github_pr_title=pr_title,
99
+ github_repository=github_repository,
100
+ )
99
101
  else:
100
102
  print("Not a pull request event, skip.")
101
103
  except Exception as e:
@@ -115,7 +117,7 @@ def _fetch_pr_title(endpoint) -> Optional[str]:
115
117
 
116
118
  if response.status_code == 200:
117
119
  pull_request_data = response.json()
118
- return pull_request_data.get('title')
120
+ return pull_request_data.get("title")
119
121
  except Exception as e:
120
122
  print("Cannot fetch PR title: ", e)
121
123