recce-nightly 1.2.0.20250506__py3-none-any.whl → 1.4.0.20250514__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 (93) hide show
  1. recce/VERSION +1 -1
  2. recce/__init__.py +22 -22
  3. recce/adapter/base.py +11 -14
  4. recce/adapter/dbt_adapter/__init__.py +355 -316
  5. recce/adapter/dbt_adapter/dbt_version.py +3 -0
  6. recce/adapter/sqlmesh_adapter.py +24 -35
  7. recce/apis/check_api.py +39 -28
  8. recce/apis/check_func.py +33 -27
  9. recce/apis/run_api.py +25 -19
  10. recce/apis/run_func.py +29 -23
  11. recce/artifact.py +44 -49
  12. recce/cli.py +484 -285
  13. recce/config.py +42 -33
  14. recce/core.py +52 -44
  15. recce/data/404.html +1 -1
  16. recce/data/_next/static/chunks/{368-7587b306577df275.js → 778-aef312bffb4c0312.js} +15 -15
  17. recce/data/_next/static/chunks/8d700b6a.ed11a130057c7a47.js +1 -0
  18. recce/data/_next/static/chunks/app/layout-c713a2829d3279e4.js +1 -0
  19. recce/data/_next/static/chunks/app/page-7086764277331fcb.js +1 -0
  20. recce/data/_next/static/chunks/{cd9f8d63-cf0d5a7b0f7a92e8.js → cd9f8d63-e020f408095ed77c.js} +3 -3
  21. recce/data/_next/static/chunks/webpack-b787cb1a4f2293de.js +1 -0
  22. recce/data/_next/static/css/88b8abc134cfd59a.css +3 -0
  23. recce/data/index.html +2 -2
  24. recce/data/index.txt +2 -2
  25. recce/diff.py +6 -12
  26. recce/event/__init__.py +74 -72
  27. recce/event/collector.py +27 -20
  28. recce/event/track.py +39 -27
  29. recce/exceptions.py +1 -1
  30. recce/git.py +7 -7
  31. recce/github.py +57 -53
  32. recce/models/__init__.py +1 -1
  33. recce/models/check.py +6 -7
  34. recce/models/run.py +1 -0
  35. recce/models/types.py +27 -27
  36. recce/pull_request.py +26 -24
  37. recce/run.py +148 -111
  38. recce/server.py +105 -88
  39. recce/state.py +209 -177
  40. recce/summary.py +168 -143
  41. recce/tasks/__init__.py +3 -3
  42. recce/tasks/core.py +11 -13
  43. recce/tasks/dataframe.py +19 -17
  44. recce/tasks/histogram.py +69 -34
  45. recce/tasks/lineage.py +2 -2
  46. recce/tasks/profile.py +152 -86
  47. recce/tasks/query.py +139 -87
  48. recce/tasks/rowcount.py +33 -30
  49. recce/tasks/schema.py +14 -14
  50. recce/tasks/top_k.py +35 -35
  51. recce/tasks/valuediff.py +216 -152
  52. recce/util/breaking.py +77 -84
  53. recce/util/cll.py +55 -51
  54. recce/util/io.py +19 -17
  55. recce/util/logger.py +1 -1
  56. recce/util/recce_cloud.py +70 -72
  57. recce/util/singleton.py +4 -4
  58. recce/yaml/__init__.py +7 -10
  59. {recce_nightly-1.2.0.20250506.dist-info → recce_nightly-1.4.0.20250514.dist-info}/METADATA +5 -2
  60. recce_nightly-1.4.0.20250514.dist-info/RECORD +143 -0
  61. {recce_nightly-1.2.0.20250506.dist-info → recce_nightly-1.4.0.20250514.dist-info}/WHEEL +1 -1
  62. tests/adapter/dbt_adapter/conftest.py +1 -0
  63. tests/adapter/dbt_adapter/dbt_test_helper.py +28 -18
  64. tests/adapter/dbt_adapter/test_dbt_adapter.py +0 -15
  65. tests/adapter/dbt_adapter/test_dbt_cll.py +39 -32
  66. tests/adapter/dbt_adapter/test_selector.py +22 -21
  67. tests/tasks/test_histogram.py +58 -66
  68. tests/tasks/test_lineage.py +36 -23
  69. tests/tasks/test_preset_checks.py +45 -31
  70. tests/tasks/test_profile.py +340 -15
  71. tests/tasks/test_query.py +40 -40
  72. tests/tasks/test_row_count.py +65 -46
  73. tests/tasks/test_schema.py +65 -42
  74. tests/tasks/test_top_k.py +22 -18
  75. tests/tasks/test_valuediff.py +43 -32
  76. tests/test_cli.py +71 -58
  77. tests/test_config.py +7 -9
  78. tests/test_core.py +5 -3
  79. tests/test_dbt.py +7 -7
  80. tests/test_pull_request.py +1 -1
  81. tests/test_server.py +19 -13
  82. tests/test_state.py +40 -27
  83. tests/test_summary.py +18 -14
  84. recce/data/_next/static/chunks/8d700b6a-f0b1f6b9e0d97ce2.js +0 -1
  85. recce/data/_next/static/chunks/app/layout-9102e22cb73f74d6.js +0 -1
  86. recce/data/_next/static/chunks/app/page-cee661090afbd6aa.js +0 -1
  87. recce/data/_next/static/chunks/webpack-567d72f0bc0820d5.js +0 -1
  88. recce_nightly-1.2.0.20250506.dist-info/RECORD +0 -142
  89. /recce/data/_next/static/{Kcbs3GEIyH2LxgLYat0es → E_HPXsXdrqHg2YEHmU3mK}/_buildManifest.js +0 -0
  90. /recce/data/_next/static/{Kcbs3GEIyH2LxgLYat0es → E_HPXsXdrqHg2YEHmU3mK}/_ssgManifest.js +0 -0
  91. {recce_nightly-1.2.0.20250506.dist-info → recce_nightly-1.4.0.20250514.dist-info}/entry_points.txt +0 -0
  92. {recce_nightly-1.2.0.20250506.dist-info → recce_nightly-1.4.0.20250514.dist-info}/licenses/LICENSE +0 -0
  93. {recce_nightly-1.2.0.20250506.dist-info → recce_nightly-1.4.0.20250514.dist-info}/top_level.txt +0 -0
recce/artifact.py CHANGED
@@ -9,9 +9,9 @@ from urllib.parse import urlencode
9
9
  import requests
10
10
  from rich.console import Console
11
11
 
12
- from recce.git import hosting_repo, commit_hash_from_branch, current_branch
12
+ from recce.git import commit_hash_from_branch, current_branch, hosting_repo
13
13
  from recce.state import s3_sse_c_headers
14
- from recce.util.recce_cloud import RecceCloud, PresignedUrlMethod
14
+ from recce.util.recce_cloud import PresignedUrlMethod, RecceCloud
15
15
 
16
16
 
17
17
  def verify_artifacts_path(target_path: str) -> bool:
@@ -30,10 +30,7 @@ def verify_artifacts_path(target_path: str) -> bool:
30
30
  if not os.path.isdir(target_path):
31
31
  return False
32
32
 
33
- required_artifacts_files = [
34
- 'manifest.json',
35
- 'catalog.json'
36
- ]
33
+ required_artifacts_files = ["manifest.json", "catalog.json"]
37
34
 
38
35
  if all(f in os.listdir(target_path) for f in required_artifacts_files):
39
36
  # Check if the required files are present in the target path
@@ -43,35 +40,35 @@ def verify_artifacts_path(target_path: str) -> bool:
43
40
 
44
41
 
45
42
  def parse_dbt_version(file_path: str) -> str:
46
- with open(file_path, 'r') as f:
43
+ with open(file_path, "r") as f:
47
44
  data = json.load(f)
48
45
 
49
- dbt_version = data.get('metadata', {}).get('dbt_version', None)
46
+ dbt_version = data.get("metadata", {}).get("dbt_version", None)
50
47
  return dbt_version
51
48
 
52
49
 
53
50
  def archive_artifacts(target_path: str) -> (str, str):
54
51
  if verify_artifacts_path(target_path) is False:
55
- raise Exception(f'Invalid target path: {target_path}')
52
+ raise Exception(f"Invalid target path: {target_path}")
56
53
 
57
- manifest_path = os.path.join(target_path, 'manifest.json')
58
- catalog_path = os.path.join(target_path, 'catalog.json')
54
+ manifest_path = os.path.join(target_path, "manifest.json")
55
+ catalog_path = os.path.join(target_path, "catalog.json")
59
56
 
60
57
  dbt_version = parse_dbt_version(manifest_path)
61
58
  if dbt_version is None:
62
- raise Exception('Failed to parse dbt version from manifest.json')
59
+ raise Exception("Failed to parse dbt version from manifest.json")
63
60
 
64
61
  # prepare the temporary artifacts path
65
62
  tmp_dir = tempfile.mkdtemp()
66
- artifacts_tar_path = os.path.join(tmp_dir, 'dbt_artifacts.tar')
67
- artifacts_tar_gz_path = artifacts_tar_path + '.gz'
63
+ artifacts_tar_path = os.path.join(tmp_dir, "dbt_artifacts.tar")
64
+ artifacts_tar_gz_path = artifacts_tar_path + ".gz"
68
65
 
69
- with tarfile.open(artifacts_tar_path, 'w') as tar:
70
- tar.add(manifest_path, arcname='manifest.json')
71
- tar.add(catalog_path, arcname='catalog.json')
66
+ with tarfile.open(artifacts_tar_path, "w") as tar:
67
+ tar.add(manifest_path, arcname="manifest.json")
68
+ tar.add(catalog_path, arcname="catalog.json")
72
69
 
73
70
  # Compress the tar file
74
- with open(artifacts_tar_path, 'rb') as f_in, gzip.open(artifacts_tar_gz_path, 'wb') as f_out:
71
+ with open(artifacts_tar_path, "rb") as f_in, gzip.open(artifacts_tar_gz_path, "wb") as f_out:
75
72
  f_out.writelines(f_in)
76
73
 
77
74
  # Clean up the temporary directory
@@ -100,36 +97,33 @@ def upload_dbt_artifacts(target_path: str, branch: str, token: str, password: st
100
97
  compress_file_path, dbt_version = archive_artifacts(target_path)
101
98
  repo = hosting_repo()
102
99
  sha = commit_hash_from_branch(branch)
103
- metadata = {
104
- 'commit': sha,
105
- 'dbt_version': dbt_version
106
- }
100
+ metadata = {"commit": sha, "dbt_version": dbt_version}
107
101
 
108
102
  # Get the presigned URL for uploading the artifacts
109
103
  presigned_url = RecceCloud(token).get_presigned_url(
110
104
  method=PresignedUrlMethod.UPLOAD,
111
105
  repository=repo,
112
- artifact_name='dbt_artifacts.tar.gz',
106
+ artifact_name="dbt_artifacts.tar.gz",
113
107
  branch=branch,
114
- metadata=metadata
108
+ metadata=metadata,
115
109
  )
116
110
 
117
111
  if debug:
118
- console.rule('Debug information', style='blue')
119
- console.print(f'Branch: {branch}')
120
- console.print(f'Commit hash: {sha}')
121
- console.print(f'GitHub repository: {repo}')
122
- console.print(f'Artifact path: {compress_file_path}')
123
- console.print(f'DBT version: {dbt_version}')
124
- console.print(f'Presigned URL: {presigned_url}')
112
+ console.rule("Debug information", style="blue")
113
+ console.print(f"Branch: {branch}")
114
+ console.print(f"Commit hash: {sha}")
115
+ console.print(f"GitHub repository: {repo}")
116
+ console.print(f"Artifact path: {compress_file_path}")
117
+ console.print(f"DBT version: {dbt_version}")
118
+ console.print(f"Presigned URL: {presigned_url}")
125
119
  console.print(f'Uploading the dbt artifacts from path "{target_path}" to branch "{branch}"')
126
120
 
127
121
  # Upload the compressed artifacts
128
122
 
129
123
  headers = s3_sse_c_headers(password)
130
124
  if metadata:
131
- headers['x-amz-tagging'] = urlencode(metadata)
132
- response = requests.put(presigned_url, data=open(compress_file_path, 'rb').read(), headers=headers)
125
+ headers["x-amz-tagging"] = urlencode(metadata)
126
+ response = requests.put(presigned_url, data=open(compress_file_path, "rb").read(), headers=headers)
133
127
  if response.status_code != 200:
134
128
  raise Exception({response.text})
135
129
 
@@ -143,9 +137,9 @@ def upload_dbt_artifacts(target_path: str, branch: str, token: str, password: st
143
137
  pass
144
138
 
145
139
 
146
- def download_dbt_artifacts(target_path: str, branch: str, token: str, password: str,
147
- force: bool = False,
148
- debug: bool = False):
140
+ def download_dbt_artifacts(
141
+ target_path: str, branch: str, token: str, password: str, force: bool = False, debug: bool = False
142
+ ):
149
143
  console = Console()
150
144
  repo = hosting_repo()
151
145
  sha = None
@@ -153,19 +147,19 @@ def download_dbt_artifacts(target_path: str, branch: str, token: str, password:
153
147
 
154
148
  presigned_url, tags = RecceCloud(token).get_download_presigned_url_with_tags(
155
149
  repository=repo,
156
- artifact_name='dbt_artifacts.tar.gz',
150
+ artifact_name="dbt_artifacts.tar.gz",
157
151
  branch=branch,
158
152
  )
159
153
  if tags:
160
- sha = tags.get('commit')
161
- dbt_version = tags.get('dbt_version')
154
+ sha = tags.get("commit")
155
+ dbt_version = tags.get("dbt_version")
162
156
 
163
157
  if debug:
164
- console.rule('Debug information', style='blue')
165
- console.print(f'Git Branch: {branch}')
166
- console.print(f'Git Commit: {sha}')
167
- console.print(f'GitHub repository: {repo}')
168
- console.print(f'DBT version: {dbt_version}')
158
+ console.rule("Debug information", style="blue")
159
+ console.print(f"Git Branch: {branch}")
160
+ console.print(f"Git Commit: {sha}")
161
+ console.print(f"GitHub repository: {repo}")
162
+ console.print(f"DBT version: {dbt_version}")
169
163
  console.print(f'Downloading from branch: "{branch}" and extracting to "{target_path}"')
170
164
 
171
165
  headers = s3_sse_c_headers(password)
@@ -177,16 +171,17 @@ def download_dbt_artifacts(target_path: str, branch: str, token: str, password:
177
171
  if os.path.exists(target_path):
178
172
  if not force:
179
173
  raise Exception(
180
- f'Path {target_path} already exists. Please provide a new path or use \'--force\' option to overwrite the existing folder.')
181
- console.print(f'[[yellow]Warning[/yellow]] Overwrite existing path: {target_path}')
174
+ f"Path {target_path} already exists. Please provide a new path or use '--force' option to overwrite the existing folder."
175
+ )
176
+ console.print(f"[[yellow]Warning[/yellow]] Overwrite existing path: {target_path}")
182
177
  shutil.rmtree(target_path)
183
178
  os.mkdir(target_path)
184
179
 
185
- tar_gz_file = os.path.join(target_path, 'dbt_artifacts.tar.gz')
186
- with open(tar_gz_file, 'wb') as f:
180
+ tar_gz_file = os.path.join(target_path, "dbt_artifacts.tar.gz")
181
+ with open(tar_gz_file, "wb") as f:
187
182
  f.write(response.content)
188
183
 
189
- with tarfile.open(tar_gz_file, 'r') as tar:
184
+ with tarfile.open(tar_gz_file, "r") as tar:
190
185
  tar.extractall(path=target_path)
191
186
 
192
187
  # Clean up the compressed artifacts