recce-nightly 1.3.0.20250507__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.
- recce/VERSION +1 -1
- recce/__init__.py +22 -22
- recce/adapter/base.py +11 -14
- recce/adapter/dbt_adapter/__init__.py +355 -316
- recce/adapter/dbt_adapter/dbt_version.py +3 -0
- recce/adapter/sqlmesh_adapter.py +24 -35
- recce/apis/check_api.py +39 -28
- recce/apis/check_func.py +33 -27
- recce/apis/run_api.py +25 -19
- recce/apis/run_func.py +29 -23
- recce/artifact.py +44 -49
- recce/cli.py +484 -285
- recce/config.py +42 -33
- recce/core.py +52 -44
- recce/data/404.html +1 -1
- recce/data/_next/static/chunks/{368-7587b306577df275.js → 778-aef312bffb4c0312.js} +15 -15
- recce/data/_next/static/chunks/8d700b6a.ed11a130057c7a47.js +1 -0
- recce/data/_next/static/chunks/app/layout-c713a2829d3279e4.js +1 -0
- recce/data/_next/static/chunks/app/page-7086764277331fcb.js +1 -0
- recce/data/_next/static/chunks/{cd9f8d63-cf0d5a7b0f7a92e8.js → cd9f8d63-e020f408095ed77c.js} +3 -3
- recce/data/_next/static/chunks/webpack-b787cb1a4f2293de.js +1 -0
- recce/data/_next/static/css/88b8abc134cfd59a.css +3 -0
- recce/data/index.html +2 -2
- recce/data/index.txt +2 -2
- recce/diff.py +6 -12
- recce/event/__init__.py +74 -72
- recce/event/collector.py +27 -20
- recce/event/track.py +39 -27
- recce/exceptions.py +1 -1
- recce/git.py +7 -7
- recce/github.py +57 -53
- recce/models/__init__.py +1 -1
- recce/models/check.py +6 -7
- recce/models/run.py +1 -0
- recce/models/types.py +27 -27
- recce/pull_request.py +26 -24
- recce/run.py +148 -111
- recce/server.py +103 -89
- recce/state.py +209 -177
- recce/summary.py +168 -143
- recce/tasks/__init__.py +3 -3
- recce/tasks/core.py +11 -13
- recce/tasks/dataframe.py +19 -17
- recce/tasks/histogram.py +69 -34
- recce/tasks/lineage.py +2 -2
- recce/tasks/profile.py +147 -86
- recce/tasks/query.py +139 -87
- recce/tasks/rowcount.py +33 -30
- recce/tasks/schema.py +14 -14
- recce/tasks/top_k.py +35 -35
- recce/tasks/valuediff.py +216 -152
- recce/util/breaking.py +77 -84
- recce/util/cll.py +55 -51
- recce/util/io.py +19 -17
- recce/util/logger.py +1 -1
- recce/util/recce_cloud.py +70 -72
- recce/util/singleton.py +4 -4
- recce/yaml/__init__.py +7 -10
- {recce_nightly-1.3.0.20250507.dist-info → recce_nightly-1.4.0.20250514.dist-info}/METADATA +5 -2
- recce_nightly-1.4.0.20250514.dist-info/RECORD +143 -0
- {recce_nightly-1.3.0.20250507.dist-info → recce_nightly-1.4.0.20250514.dist-info}/WHEEL +1 -1
- tests/adapter/dbt_adapter/conftest.py +1 -0
- tests/adapter/dbt_adapter/dbt_test_helper.py +28 -18
- tests/adapter/dbt_adapter/test_dbt_adapter.py +0 -15
- tests/adapter/dbt_adapter/test_dbt_cll.py +39 -32
- tests/adapter/dbt_adapter/test_selector.py +22 -21
- tests/tasks/test_histogram.py +58 -66
- tests/tasks/test_lineage.py +36 -23
- tests/tasks/test_preset_checks.py +45 -31
- tests/tasks/test_profile.py +340 -15
- tests/tasks/test_query.py +40 -40
- tests/tasks/test_row_count.py +65 -46
- tests/tasks/test_schema.py +65 -42
- tests/tasks/test_top_k.py +22 -18
- tests/tasks/test_valuediff.py +43 -32
- tests/test_cli.py +71 -58
- tests/test_config.py +7 -9
- tests/test_core.py +5 -3
- tests/test_dbt.py +7 -7
- tests/test_pull_request.py +1 -1
- tests/test_server.py +19 -13
- tests/test_state.py +40 -27
- tests/test_summary.py +18 -14
- recce/data/_next/static/chunks/8d700b6a-f0b1f6b9e0d97ce2.js +0 -1
- recce/data/_next/static/chunks/app/layout-9102e22cb73f74d6.js +0 -1
- recce/data/_next/static/chunks/app/page-92f13c8fad9fae3d.js +0 -1
- recce/data/_next/static/chunks/webpack-567d72f0bc0820d5.js +0 -1
- recce_nightly-1.3.0.20250507.dist-info/RECORD +0 -142
- /recce/data/_next/static/{K5iKlCYhdcpq8Ea6ck9J_ → E_HPXsXdrqHg2YEHmU3mK}/_buildManifest.js +0 -0
- /recce/data/_next/static/{K5iKlCYhdcpq8Ea6ck9J_ → E_HPXsXdrqHg2YEHmU3mK}/_ssgManifest.js +0 -0
- {recce_nightly-1.3.0.20250507.dist-info → recce_nightly-1.4.0.20250514.dist-info}/entry_points.txt +0 -0
- {recce_nightly-1.3.0.20250507.dist-info → recce_nightly-1.4.0.20250514.dist-info}/licenses/LICENSE +0 -0
- {recce_nightly-1.3.0.20250507.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
|
|
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
|
|
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,
|
|
43
|
+
with open(file_path, "r") as f:
|
|
47
44
|
data = json.load(f)
|
|
48
45
|
|
|
49
|
-
dbt_version = data.get(
|
|
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
|
|
52
|
+
raise Exception(f"Invalid target path: {target_path}")
|
|
56
53
|
|
|
57
|
-
manifest_path = os.path.join(target_path,
|
|
58
|
-
catalog_path = os.path.join(target_path,
|
|
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(
|
|
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,
|
|
67
|
-
artifacts_tar_gz_path = artifacts_tar_path +
|
|
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,
|
|
70
|
-
tar.add(manifest_path, arcname=
|
|
71
|
-
tar.add(catalog_path, arcname=
|
|
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,
|
|
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=
|
|
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(
|
|
119
|
-
console.print(f
|
|
120
|
-
console.print(f
|
|
121
|
-
console.print(f
|
|
122
|
-
console.print(f
|
|
123
|
-
console.print(f
|
|
124
|
-
console.print(f
|
|
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[
|
|
132
|
-
response = requests.put(presigned_url, data=open(compress_file_path,
|
|
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(
|
|
147
|
-
|
|
148
|
-
|
|
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=
|
|
150
|
+
artifact_name="dbt_artifacts.tar.gz",
|
|
157
151
|
branch=branch,
|
|
158
152
|
)
|
|
159
153
|
if tags:
|
|
160
|
-
sha = tags.get(
|
|
161
|
-
dbt_version = tags.get(
|
|
154
|
+
sha = tags.get("commit")
|
|
155
|
+
dbt_version = tags.get("dbt_version")
|
|
162
156
|
|
|
163
157
|
if debug:
|
|
164
|
-
console.rule(
|
|
165
|
-
console.print(f
|
|
166
|
-
console.print(f
|
|
167
|
-
console.print(f
|
|
168
|
-
console.print(f
|
|
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
|
|
181
|
-
|
|
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,
|
|
186
|
-
with open(tar_gz_file,
|
|
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,
|
|
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
|