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/util/io.py CHANGED
@@ -1,14 +1,14 @@
1
1
  import gzip
2
2
  import os
3
3
  import tempfile
4
- from abc import ABCMeta, abstractmethod, ABC
4
+ from abc import ABC, ABCMeta, abstractmethod
5
5
  from enum import Enum
6
6
 
7
7
 
8
8
  class SupportedFileTypes(Enum):
9
- FILE = 'file'
10
- GZIP = 'gzip'
11
- ZIP = 'zip'
9
+ FILE = "file"
10
+ GZIP = "gzip"
11
+ ZIP = "zip"
12
12
 
13
13
 
14
14
  def file_io_factory(file_type: SupportedFileTypes):
@@ -19,7 +19,7 @@ def file_io_factory(file_type: SupportedFileTypes):
19
19
  elif file_type == SupportedFileTypes.ZIP:
20
20
  return ZipFileIO
21
21
  else:
22
- raise ValueError(f'Unsupported file type: {file_type}')
22
+ raise ValueError(f"Unsupported file type: {file_type}")
23
23
 
24
24
 
25
25
  class AbstractFileIO(metaclass=ABCMeta):
@@ -37,24 +37,24 @@ class AbstractFileIO(metaclass=ABCMeta):
37
37
  class FileIO(AbstractFileIO, ABC):
38
38
  @staticmethod
39
39
  def write(path: str, data: str, **kwargs):
40
- with open(path, 'w') as f:
40
+ with open(path, "w") as f:
41
41
  f.write(data)
42
42
 
43
43
  @staticmethod
44
44
  def read(path: str, **kwargs) -> str:
45
- with open(path, 'r') as f:
45
+ with open(path, "r") as f:
46
46
  return f.read()
47
47
 
48
48
 
49
49
  class GzipFileIO(AbstractFileIO, ABC):
50
50
  @staticmethod
51
51
  def write(path: str, data: str, **kwargs):
52
- with gzip.open(path, 'wt') as f:
52
+ with gzip.open(path, "wt") as f:
53
53
  f.write(data)
54
54
 
55
55
  @staticmethod
56
56
  def read(path: str, **kwargs) -> str:
57
- with gzip.open(path, 'rt') as f:
57
+ with gzip.open(path, "rt") as f:
58
58
  return f.read()
59
59
 
60
60
  @staticmethod
@@ -69,17 +69,18 @@ class ZipFileIO(AbstractFileIO, ABC):
69
69
  try:
70
70
  import pyminizip
71
71
  except ImportError:
72
- raise ImportError('pyminizip is not installed. Please install it using `pip install pyminizip`')
72
+ raise ImportError("pyminizip is not installed. Please install it using `pip install pyminizip`")
73
73
 
74
74
  @staticmethod
75
75
  def read(path: str, **kwargs) -> str:
76
76
  ZipFileIO._is_pyminizip_installed()
77
77
  import pyminizip
78
+
78
79
  cwd = os.getcwd()
79
- password = kwargs.get('password')
80
- zip_dir_name = kwargs.get('zip_dir_name')
80
+ password = kwargs.get("password")
81
+ zip_dir_name = kwargs.get("zip_dir_name")
81
82
  if zip_dir_name is None:
82
- raise ValueError('zip_dir_name is required for zipping')
83
+ raise ValueError("zip_dir_name is required for zipping")
83
84
 
84
85
  try:
85
86
  with tempfile.TemporaryDirectory() as tmp_dir:
@@ -88,7 +89,7 @@ class ZipFileIO(AbstractFileIO, ABC):
88
89
  content = FileIO.read(tmp_file)
89
90
  except Exception as e:
90
91
  error_msg = str(e)
91
- if '-3' in error_msg:
92
+ if "-3" in error_msg:
92
93
  raise Exception("Invalid password to uncompress state file.")
93
94
  raise Exception(f"Failed to uncompress state file: {error_msg}")
94
95
  finally:
@@ -100,11 +101,12 @@ class ZipFileIO(AbstractFileIO, ABC):
100
101
  def write(path: str, data: str, **kwargs):
101
102
  ZipFileIO._is_pyminizip_installed()
102
103
  import pyminizip
104
+
103
105
  cwd = os.getcwd()
104
- password = kwargs.get('password')
105
- zip_dir_name = kwargs.get('zip_dir_name')
106
+ password = kwargs.get("password")
107
+ zip_dir_name = kwargs.get("zip_dir_name")
106
108
  if zip_dir_name is None:
107
- raise ValueError('zip_dir_name is required for zipping')
109
+ raise ValueError("zip_dir_name is required for zipping")
108
110
 
109
111
  try:
110
112
  with tempfile.TemporaryDirectory() as tmp_dir:
recce/util/logger.py CHANGED
@@ -16,7 +16,7 @@ class CustomFormatter(logging.Formatter):
16
16
  logging.INFO: green + format + reset,
17
17
  logging.WARNING: yellow + format + reset,
18
18
  logging.ERROR: red + format + reset,
19
- logging.CRITICAL: bold_red + format + reset
19
+ logging.CRITICAL: bold_red + format + reset,
20
20
  }
21
21
 
22
22
  def format(self, record):
recce/util/recce_cloud.py CHANGED
@@ -1,20 +1,20 @@
1
1
  import json
2
2
  import logging
3
3
  import os
4
- from typing import Dict, IO
4
+ from typing import IO, Dict
5
5
 
6
6
  import requests
7
7
 
8
8
  from recce.pull_request import PullRequestInfo
9
9
 
10
- RECCE_CLOUD_API_HOST = os.environ.get('RECCE_CLOUD_API_HOST', 'https://cloud.datarecce.io')
10
+ RECCE_CLOUD_API_HOST = os.environ.get("RECCE_CLOUD_API_HOST", "https://cloud.datarecce.io")
11
11
 
12
- logger = logging.getLogger('uvicorn')
12
+ logger = logging.getLogger("uvicorn")
13
13
 
14
14
 
15
15
  class PresignedUrlMethod:
16
- UPLOAD = 'upload'
17
- DOWNLOAD = 'download'
16
+ UPLOAD = "upload"
17
+ DOWNLOAD = "download"
18
18
 
19
19
 
20
20
  class RecceCloudException(Exception):
@@ -23,7 +23,7 @@ class RecceCloudException(Exception):
23
23
  self.status_code = status_code
24
24
 
25
25
  try:
26
- reason = json.loads(reason).get('detail', '')
26
+ reason = json.loads(reason).get("detail", "")
27
27
  except json.JSONDecodeError:
28
28
  pass
29
29
  self.reason = reason
@@ -32,134 +32,132 @@ class RecceCloudException(Exception):
32
32
  class RecceCloud:
33
33
  def __init__(self, token: str):
34
34
  self.token = token
35
- self.base_url = f'{RECCE_CLOUD_API_HOST}/api/v1'
35
+ self.base_url = f"{RECCE_CLOUD_API_HOST}/api/v1"
36
36
 
37
37
  def _request(self, method, url, **kwargs):
38
- headers = {
39
- 'Authorization': f'Bearer {self.token}'
40
- }
38
+ headers = {"Authorization": f"Bearer {self.token}"}
41
39
  return requests.request(method, url, headers=headers, **kwargs)
42
40
 
43
- def get_presigned_url(self,
44
- method: PresignedUrlMethod,
45
- repository: str,
46
- artifact_name: str,
47
- metadata: dict = None,
48
- pr_id: int = None,
49
- branch: str = None) -> str:
41
+ def get_presigned_url(
42
+ self,
43
+ method: PresignedUrlMethod,
44
+ repository: str,
45
+ artifact_name: str,
46
+ metadata: dict = None,
47
+ pr_id: int = None,
48
+ branch: str = None,
49
+ ) -> str:
50
50
  response = self._fetch_presigned_url(method, repository, artifact_name, metadata, pr_id, branch)
51
- return response.get('presigned_url')
51
+ return response.get("presigned_url")
52
52
 
53
- def get_download_presigned_url_with_tags(self,
54
- repository: str,
55
- artifact_name: str,
56
- branch: str = None) -> (str, dict):
53
+ def get_download_presigned_url_with_tags(
54
+ self, repository: str, artifact_name: str, branch: str = None
55
+ ) -> (str, dict):
57
56
  response = self._fetch_presigned_url(PresignedUrlMethod.DOWNLOAD, repository, artifact_name, branch=branch)
58
- return response.get('presigned_url'), response.get('tags', {})
59
-
60
- def _fetch_presigned_url(self,
61
- method: PresignedUrlMethod,
62
- repository: str,
63
- artifact_name: str,
64
- metadata: dict = None,
65
- pr_id: int = None,
66
- branch: str = None) -> str:
57
+ return response.get("presigned_url"), response.get("tags", {})
58
+
59
+ def _fetch_presigned_url(
60
+ self,
61
+ method: PresignedUrlMethod,
62
+ repository: str,
63
+ artifact_name: str,
64
+ metadata: dict = None,
65
+ pr_id: int = None,
66
+ branch: str = None,
67
+ ) -> str:
67
68
  if pr_id is not None:
68
- api_url = f'{self.base_url}/{repository}/pulls/{pr_id}/artifacts/{method}?artifact_name={artifact_name}&enable_ssec=true'
69
+ api_url = f"{self.base_url}/{repository}/pulls/{pr_id}/artifacts/{method}?artifact_name={artifact_name}&enable_ssec=true"
69
70
  elif branch is not None:
70
- api_url = f'{self.base_url}/{repository}/commits/{branch}/artifacts/{method}?artifact_name={artifact_name}&enable_ssec=true'
71
+ api_url = f"{self.base_url}/{repository}/commits/{branch}/artifacts/{method}?artifact_name={artifact_name}&enable_ssec=true"
71
72
  else:
72
- raise ValueError('Either pr_id or sha must be provided.')
73
- response = self._request('POST', api_url, json=metadata)
73
+ raise ValueError("Either pr_id or sha must be provided.")
74
+ response = self._request("POST", api_url, json=metadata)
74
75
  if response.status_code != 200:
75
76
  raise RecceCloudException(
76
- message='Failed to {method} artifact {preposition} Recce Cloud.'.format(
77
- method=method,
78
- preposition='from' if method == PresignedUrlMethod.DOWNLOAD else 'to'
77
+ message="Failed to {method} artifact {preposition} Recce Cloud.".format(
78
+ method=method, preposition="from" if method == PresignedUrlMethod.DOWNLOAD else "to"
79
79
  ),
80
80
  reason=response.text,
81
- status_code=response.status_code
81
+ status_code=response.status_code,
82
82
  )
83
83
  return response.json()
84
84
 
85
85
  def get_artifact_metadata(self, pr_info: PullRequestInfo) -> dict:
86
- api_url = f'{self.base_url}/{pr_info.repository}/pulls/{pr_info.id}/metadata'
87
- response = self._request('GET', api_url)
86
+ api_url = f"{self.base_url}/{pr_info.repository}/pulls/{pr_info.id}/metadata"
87
+ response = self._request("GET", api_url)
88
88
  if response.status_code == 204:
89
89
  return None
90
90
  if response.status_code != 200:
91
91
  raise RecceCloudException(
92
- message='Failed to get artifact metadata from Recce Cloud.',
92
+ message="Failed to get artifact metadata from Recce Cloud.",
93
93
  reason=response.text,
94
- status_code=response.status_code
94
+ status_code=response.status_code,
95
95
  )
96
96
  return response.json()
97
97
 
98
98
  def purge_artifacts(self, pr_info: PullRequestInfo):
99
- api_url = f'{self.base_url}/{pr_info.repository}/pulls/{pr_info.id}/artifacts'
100
- response = self._request('DELETE', api_url)
99
+ api_url = f"{self.base_url}/{pr_info.repository}/pulls/{pr_info.id}/artifacts"
100
+ response = self._request("DELETE", api_url)
101
101
  if response.status_code != 204:
102
102
  raise RecceCloudException(
103
- message='Failed to purge artifacts from Recce Cloud.',
103
+ message="Failed to purge artifacts from Recce Cloud.",
104
104
  reason=response.text,
105
- status_code=response.status_code
105
+ status_code=response.status_code,
106
106
  )
107
107
 
108
108
  def check_artifacts_exists(self, pr_info: PullRequestInfo) -> bool:
109
- api_url = f'{self.base_url}/{pr_info.repository}/pulls/{pr_info.id}/metadata'
110
- response = self._request('GET', api_url)
109
+ api_url = f"{self.base_url}/{pr_info.repository}/pulls/{pr_info.id}/metadata"
110
+ response = self._request("GET", api_url)
111
111
  if response.status_code == 200:
112
112
  return True
113
113
  elif response.status_code == 204:
114
114
  return False
115
115
  else:
116
116
  raise RecceCloudException(
117
- message='Failed to check if artifacts exist in Recce Cloud.',
117
+ message="Failed to check if artifacts exist in Recce Cloud.",
118
118
  reason=response.text,
119
- status_code=response.status_code
119
+ status_code=response.status_code,
120
120
  )
121
121
 
122
122
  def share_state(self, file_name: str, file_io: IO):
123
- api_url = f'{self.base_url}/recce-state/upload'
124
- files = {'file': (file_name, file_io, 'application/json')}
125
- response = self._request('POST', api_url, files=files)
123
+ api_url = f"{self.base_url}/recce-state/upload"
124
+ files = {"file": (file_name, file_io, "application/json")}
125
+ response = self._request("POST", api_url, files=files)
126
126
  if response.status_code == 403:
127
- return {'status': 'error', 'message': response.json().get('detail')}
127
+ return {"status": "error", "message": response.json().get("detail")}
128
128
  if response.status_code != 200:
129
129
  raise RecceCloudException(
130
- message='Failed to share Recce state.',
131
- reason=response.text,
132
- status_code=response.status_code
130
+ message="Failed to share Recce state.", reason=response.text, status_code=response.status_code
133
131
  )
134
132
  return response.json()
135
133
 
136
134
  def update_github_pull_request_check(self, pr_info: PullRequestInfo, metadata: dict = None):
137
- api_url = f'{self.base_url}/{pr_info.repository}/pulls/{pr_info.id}/github/checks'
135
+ api_url = f"{self.base_url}/{pr_info.repository}/pulls/{pr_info.id}/github/checks"
138
136
  try:
139
- self._request('POST', api_url, json=metadata)
137
+ self._request("POST", api_url, json=metadata)
140
138
  except Exception as e:
141
139
  # We don't care the response of this request, so we don't need to raise any exception.
142
- logger.debug(f'Failed to update the GitHub PR check. Reason: {str(e)}')
140
+ logger.debug(f"Failed to update the GitHub PR check. Reason: {str(e)}")
143
141
 
144
142
  def get_user_info(self) -> Dict:
145
- api_url = f'{self.base_url}/users'
146
- response = self._request('GET', api_url)
143
+ api_url = f"{self.base_url}/users"
144
+ response = self._request("GET", api_url)
147
145
  if response.status_code != 200:
148
146
  raise RecceCloudException(
149
- message='Failed to get user info from Recce Cloud.',
147
+ message="Failed to get user info from Recce Cloud.",
150
148
  reason=response.text,
151
- status_code=response.status_code
149
+ status_code=response.status_code,
152
150
  )
153
- return response.json().get('user')
151
+ return response.json().get("user")
154
152
 
155
153
  def set_onboarding_state(self, state: str):
156
- api_url = f'{self.base_url}/users/onboarding-state'
157
- response = self._request('PUT', api_url, json={'state': state})
154
+ api_url = f"{self.base_url}/users/onboarding-state"
155
+ response = self._request("PUT", api_url, json={"state": state})
158
156
  if response.status_code != 200:
159
157
  raise RecceCloudException(
160
- message='Failed to update onboarding state in Recce Cloud.',
158
+ message="Failed to update onboarding state in Recce Cloud.",
161
159
  reason=response.text,
162
- status_code=response.status_code
160
+ status_code=response.status_code,
163
161
  )
164
162
 
165
163
 
@@ -168,10 +166,10 @@ def get_recce_cloud_onboarding_state(token: str) -> str:
168
166
  recce_cloud = RecceCloud(token)
169
167
  user_info = recce_cloud.get_user_info()
170
168
  if user_info:
171
- return user_info.get('onboarding_state')
169
+ return user_info.get("onboarding_state")
172
170
  except Exception as e:
173
171
  logger.debug(str(e))
174
- return 'undefined'
172
+ return "undefined"
175
173
 
176
174
 
177
175
  def set_recce_cloud_onboarding_state(token: str, new_state: str):
recce/util/singleton.py CHANGED
@@ -1,9 +1,9 @@
1
1
  class SingletonMeta(type):
2
2
  """
3
- The Singleton class can be implemented in different ways in Python. Some
4
- possible methods include: base class, decorator, metaclass. We will use the
5
- metaclass because it is best suited for this purpose.
6
- """
3
+ The Singleton class can be implemented in different ways in Python. Some
4
+ possible methods include: base class, decorator, metaclass. We will use the
5
+ metaclass because it is best suited for this purpose.
6
+ """
7
7
 
8
8
  _instances = {}
9
9
 
recce/yaml/__init__.py CHANGED
@@ -1,10 +1,11 @@
1
1
  from typing import Any, Callable
2
2
 
3
3
  from ruamel import yaml
4
- from ruamel.yaml import CommentedMap as _cm, CommentedSeq as _cs
4
+ from ruamel.yaml import CommentedMap as _cm
5
+ from ruamel.yaml import CommentedSeq as _cs
5
6
 
6
7
  _yaml = yaml.YAML()
7
- _safe_yaml = yaml.YAML(typ='safe')
8
+ _safe_yaml = yaml.YAML(typ="safe")
8
9
 
9
10
  CommentedMap = _cm
10
11
  CommentedSeq = _cs
@@ -27,15 +28,13 @@ def safe_load(stream, version=None) -> Any:
27
28
  return _safe_yaml.load(stream)
28
29
 
29
30
 
30
- def dump(
31
- data, stream: Any = None, *, transform: Any = None
32
- ) -> Any:
31
+ def dump(data, stream: Any = None, *, transform: Any = None) -> Any:
33
32
  return _yaml.dump(data, stream, transform=transform)
34
33
 
35
34
 
36
35
  def safe_load_yaml(file_path):
37
36
  try:
38
- with open(file_path, 'r') as f:
37
+ with open(file_path, "r") as f:
39
38
  payload = safe_load(f)
40
39
  except yaml.YAMLError as e:
41
40
  print(e)
@@ -46,7 +45,7 @@ def safe_load_yaml(file_path):
46
45
 
47
46
 
48
47
  def round_trip_load_yaml(file_path):
49
- with open(file_path, 'r') as f:
48
+ with open(file_path, "r") as f:
50
49
  try:
51
50
  payload = load(f)
52
51
  except yaml.YAMLError as e:
@@ -55,7 +54,5 @@ def round_trip_load_yaml(file_path):
55
54
  return payload
56
55
 
57
56
 
58
- def round_trip_dump(
59
- data: Any,
60
- stream=None):
57
+ def round_trip_dump(data: Any, stream=None):
61
58
  return yaml.round_trip_dump(data, stream)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: recce-nightly
3
- Version: 1.2.0.20250506
3
+ Version: 1.4.0.20250514
4
4
  Summary: Environment diff tool for dbt
5
5
  Home-page: https://github.com/InfuseAI/recce
6
6
  Author: InfuseAI Dev Team
@@ -40,7 +40,10 @@ Requires-Dist: sqlglot
40
40
  Provides-Extra: dev
41
41
  Requires-Dist: pytest>=4.6; extra == "dev"
42
42
  Requires-Dist: pytest-flake8; extra == "dev"
43
- Requires-Dist: flake8==3.9.2; extra == "dev"
43
+ Requires-Dist: black>=25.1.0; extra == "dev"
44
+ Requires-Dist: isort>=6.0.1; extra == "dev"
45
+ Requires-Dist: flake8>=7.2.0; extra == "dev"
46
+ Requires-Dist: pre-commit>=4.2.0; extra == "dev"
44
47
  Requires-Dist: pytest-mypy; extra == "dev"
45
48
  Requires-Dist: pytest-cov; extra == "dev"
46
49
  Requires-Dist: twine; extra == "dev"
@@ -0,0 +1,143 @@
1
+ recce/VERSION,sha256=9ZTNVW7MlcEiwz3qySDm_h-tOLFOykEntdSn8SASwaU,15
2
+ recce/__init__.py,sha256=yNb0QT-yoStex0VZALNJvUwtPLommoVCStcow31guqo,2392
3
+ recce/artifact.py,sha256=tKQAHSrLRjiR3ppOI4sym8SxYiiLTuD3DPMYh4DWQdA,6506
4
+ recce/cli.py,sha256=OqIUMkQSm1XgpGawm_j1XURAMK9ijlBQrWTuakPP6S0,35388
5
+ recce/config.py,sha256=fs22mpFj8CFIxftGbhFAV5xIsPLX2xNTwWSer3UYn5k,4658
6
+ recce/core.py,sha256=C7RooEojAi5PIlbJuvB0Cj8F0HVktyn8bNRZE-TuzHQ,10726
7
+ recce/diff.py,sha256=L2_bzQ3__PO-0aeir8PHF8FvSOUmQ8WcDXgML1-mHdY,748
8
+ recce/exceptions.py,sha256=SclQ678GrHGjw7p_ZFJ3vZaL_yMU5xABeIAm2u_W2bk,592
9
+ recce/git.py,sha256=8Eg-6NzL-KjA3rT-ibbAyaCwGlzV0JqH3yGikrJNMDA,2344
10
+ recce/github.py,sha256=PEpM6ZRiinsPbXSWj4aJCKbZrN1jUXzpzAfJq_CGah4,7420
11
+ recce/pull_request.py,sha256=aW0B1NE2LUKTam1S4TQ7smXB9KLE1DV8GnyBqNXA6j8,3832
12
+ recce/run.py,sha256=LAjbWUF8loZ9cL25d_maQELwROHHmfaFn7iqFRy5O1o,13567
13
+ recce/server.py,sha256=X7WDMlujxfzc8yk-GWuSyVIWee9kUEcjplGP1vD0r1w,20301
14
+ recce/state.py,sha256=VPzKyEdmyBeZ45BQArB587QN5C3Sfr7O5Oh_JRBcKrc,30616
15
+ recce/summary.py,sha256=Mbxvxr9KazR5o9icqhhjiGHsoAiWxQU4PdN7HytBJ1c,19154
16
+ recce/adapter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ recce/adapter/base.py,sha256=T_JNeLHgiHSaegw-DbrvHOaYjMyZcjj2Qtg5cWh_fco,3548
18
+ recce/adapter/sqlmesh_adapter.py,sha256=IU3N-F6ToDoO7_bV5vsG8pmTuDcbFtewTIuCxedTaRM,5046
19
+ recce/adapter/dbt_adapter/__init__.py,sha256=21FBwx6ovGO-oOxLcsZWVejlD35NT_r2v3vtApnWfTU,54384
20
+ recce/adapter/dbt_adapter/dbt_version.py,sha256=M7aedZIWslXnJsryK8Ki4OL_t2oAKxy4uE2pRwfWIkk,1228
21
+ recce/apis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ recce/apis/check_api.py,sha256=KMCXSMl1qqzx2jQgRqCrD4j_cY3EHBbM3H2-t-6saAU,6227
23
+ recce/apis/check_func.py,sha256=gktbCcyk3WGvWRJJ-wDnwv7NrIny2nTHWLl1-kdiVRo,4183
24
+ recce/apis/run_api.py,sha256=eOaxOxXDkH59uqGCd4blld7edavUx7JU_DCd2WAYrL8,3416
25
+ recce/apis/run_func.py,sha256=6wC8TDU-h7TLr2VZH7HNsWaUVlQ9HBN5N_dwqfi4lMY,7440
26
+ recce/data/404.html,sha256=-lVLhRLEsURSnKitVilsjDgmfn7nl9b5sf93tyLmBYw,6554
27
+ recce/data/favicon.ico,sha256=B2mBumUOnzvUrXrqNkrc5QfdDXjzEXRcWkWur0fJ6sM,2565
28
+ recce/data/index.html,sha256=0gl6lXkM8EKzI77w9mla9EyfHnVfaH2uua6bskSlYpo,40259
29
+ recce/data/index.txt,sha256=lwU7wJpAlhXZUhUNKdm1kJ3hxgADAdm55xKAAhCOjik,3514
30
+ recce/data/_next/static/E_HPXsXdrqHg2YEHmU3mK/_buildManifest.js,sha256=gZrGHi2LPMw1gkjYWs13MYkJyb5aOtihBRSJ1w0E6QA,224
31
+ recce/data/_next/static/E_HPXsXdrqHg2YEHmU3mK/_ssgManifest.js,sha256=Z49s4suAsf5y_GfnQSvm4qtq2ggxEbZPfEDTXjy6XgA,80
32
+ recce/data/_next/static/chunks/1f229bf6-d9fe92e56db8d93b.js,sha256=NvhILR-yLwIu-WlvwD9Hkr2H_I7ZK64vwYvR6c84wC0,172836
33
+ recce/data/_next/static/chunks/29e3cc0d-8c150e37dff9631b.js,sha256=4ZQR-OYMhGWnYPNwUjG5FpsTVzVTPEAf6T0v0E5g-4o,700
34
+ recce/data/_next/static/chunks/36e1c10d-bb0210cbd6573a8d.js,sha256=SkfIoUJXsrjEoql4hRRcWKtW2vMfHOAHUm4NE6eaho4,7797
35
+ recce/data/_next/static/chunks/3998a672-eaad84bdd88cc73e.js,sha256=7FRm86VFsyXQL6M4J0qFq7e4cvhs48uKJF2Qp0tYraM,9024
36
+ recce/data/_next/static/chunks/3a92ee20-3b5d922d4157af5e.js,sha256=Ou-yjvdFB0Zy_Im93w9LrR2LyB_aRnaNn1Sz1EB18mI,177688
37
+ recce/data/_next/static/chunks/450c323b-1bb5db526e54435a.js,sha256=3M8dU9CapPo-oey7uyaRBaSrnwoPHUQb671T-_Nv7bs,2205
38
+ recce/data/_next/static/chunks/47d8844f-79a1b53c66a7d7ec.js,sha256=WwhEczkWeoHd3z0pTrh4u_XwBoUxePZ7rjEMPjajmx8,697
39
+ recce/data/_next/static/chunks/6dc81886-c94b9b91bc2c3caf.js,sha256=xIxqOzAWk07uQb5pgQGMv0O4CHereLF86Fwm2wX0Mmo,69733
40
+ recce/data/_next/static/chunks/6ef81909-694dc38134099299.js,sha256=KiPoS30Exnv9fi1X2HvxnydUFJnWfY-ZeifdexVAEXA,49001
41
+ recce/data/_next/static/chunks/700-3b65fc3666820d00.js,sha256=JokVG7hi66aCWFukVWlzc2vIBKa7EFW7JrSGW9F_2tU,124133
42
+ recce/data/_next/static/chunks/778-aef312bffb4c0312.js,sha256=0r8zj3JFDP8_0FxXPE8b_4aeW2nmwYi8wh5GiWBY5VM,1361523
43
+ recce/data/_next/static/chunks/7a8a3e83-d7fa409d97b38b2b.js,sha256=MmsF3qQgQXqSPGhUHQbIqAtVz7Maa_O3rWErEq0N3gY,1649
44
+ recce/data/_next/static/chunks/7f27ae6c-413f6b869a04183a.js,sha256=8Hs6bhtsCfZiOFrX3_IBxLZKPsdqhkLzikrACS1Pe0M,779
45
+ recce/data/_next/static/chunks/8d700b6a.ed11a130057c7a47.js,sha256=ObDzyvm0pCB9K8yFyj5vin5cVzTr5IqVO4XD-KHtXmo,119972
46
+ recce/data/_next/static/chunks/9746af58-d74bef4d03eea6ab.js,sha256=9MwsjNv8XMd92eUpXYeA32Ahk8ORP_oWMXnpTYOQQ-c,4177
47
+ recce/data/_next/static/chunks/a30376cd-7d806e1602f2dc3a.js,sha256=cvkpSEaZn5Johnsf3DT_x-hKNlNIhYFb6CZcMqpXpTE,797
48
+ recce/data/_next/static/chunks/b63b1b3f-7395c74e11a14e95.js,sha256=g2ArwRSeMZ-o6dODDGh3orC0iRkyxjXTk4NgyVk1nBw,572
49
+ recce/data/_next/static/chunks/c132bf7d-8102037f9ccf372a.js,sha256=CSRe9MSZI7ohCFzU6umTdDDkw2aBiLhA0HLurQwrjUY,198537
50
+ recce/data/_next/static/chunks/c1ceaa8b-a1e442154d23515e.js,sha256=mL85IeBYKB6YBgKlDs2n5lA7iLaxU8nTEtE8jduhGRI,81302
51
+ recce/data/_next/static/chunks/cd9f8d63-e020f408095ed77c.js,sha256=GeYFrOTA_N2zLZhmnWoJJOzgo_Jc9hk8svIHuTysdUg,82989
52
+ recce/data/_next/static/chunks/ce84277d-f42c2c58049cea2d.js,sha256=4FzO_5dSRNQKZHQ2EmZW0iau4yBguMBJ324J0e70UXQ,2562
53
+ recce/data/_next/static/chunks/e24bf851-0f8cbc99656833e7.js,sha256=aaPLADhg4KN7KoE09dpPiE831gBYqepVrIJj6Qh2amk,154153
54
+ recce/data/_next/static/chunks/fee69bc6-f17d36c080742e74.js,sha256=r51nWC424b7AoD-Y68JLMXDDpS_n-IUL3zcJNStzOLA,483
55
+ recce/data/_next/static/chunks/framework-ded83d71b51ce901.js,sha256=0Xsxxnmw5fjRHz8ni6vlaF9tQjfjNGZcZv2oMy7A_T4,140000
56
+ recce/data/_next/static/chunks/main-a0859f1f36d0aa6c.js,sha256=nTSd5jisBq_nX5_3Yf1JMakSk9Rq5IQEhtzeFU0VRyY,111204
57
+ recce/data/_next/static/chunks/main-app-0225a2255968e566.js,sha256=zVNui79GYFi-pNlmSB_zwxzps-uRW9L1-HZXXBUFj-Y,471
58
+ recce/data/_next/static/chunks/polyfills-42372ed130431b0a.js,sha256=CXPB1kyIrcjjyVBBDLWLKI9yEY1ZZbeASUON648vloM,112594
59
+ recce/data/_next/static/chunks/webpack-b787cb1a4f2293de.js,sha256=JMFnMBlHCoK4ti0UmBLCfdf5Vb1lgvJm7C3nzW8KbbQ,3899
60
+ recce/data/_next/static/chunks/app/layout-c713a2829d3279e4.js,sha256=Y0QZ74X1tmZrRQBM1HhnrmFyKgQx4aKRPE4KL6KSh3I,233
61
+ recce/data/_next/static/chunks/app/page-7086764277331fcb.js,sha256=y_cRY7_yvMXI-PsE1gLWRz6rd07RP5H5zUVvrID-2fY,225920
62
+ recce/data/_next/static/chunks/app/_not-found/page-8a886fa0855c3105.js,sha256=T5MBvLNarbZQll8vwvggCZWFzcNwqe6LlL0hGI9YPXA,1751
63
+ recce/data/_next/static/chunks/pages/_app-d5672bf3d8b6371b.js,sha256=UcYdHJMmCNfuMevCyY_iFfFwMGbxcEkLGRbBnEx_cCU,284
64
+ recce/data/_next/static/chunks/pages/_error-ed75be3f25588548.js,sha256=o_MwN3cYfszhI-hy_wkB0XAyTgcEcXt43rrzk-oKIe0,250
65
+ recce/data/_next/static/css/88b8abc134cfd59a.css,sha256=Tb97QjWxV5rOawZojbeD9SSETGsG2p9iaOrENjzAjYM,7235
66
+ recce/data/_next/static/css/c9ecb46a4b21c126.css,sha256=JbGypR8aDNuZavNvH6dhPtSbMVSCsy0ycPrz_6XkiVc,21925
67
+ recce/data/_next/static/media/montserrat-cyrillic-800-normal.22628180.woff2,sha256=P5Sx5PNkdTlDYzAdulW_OPRfMokDLi6XTpmS8KJSRoI,11148
68
+ recce/data/_next/static/media/montserrat-cyrillic-800-normal.31d693bb.woff,sha256=ITxULbMzWscxwUi_v3GpzTSYVWlwq_z9fpEvAkEvHJw,11020
69
+ recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.7e2c1e62.woff,sha256=6J3PqBk_hOFVM8PpfZeSfwZQumQd6LTPPjnaVha2KQ0,12672
70
+ recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.94a63aea.woff2,sha256=qHQDcPj9VkK-6sE5nxIKvejtNLo5RwBULzyH9nZsEwo,12052
71
+ recce/data/_next/static/media/montserrat-latin-800-normal.6f8fa298.woff2,sha256=Tyiv8SvOCaTmT_S2FaOZ5FuZz52F1aVV9hzIfrI7sEI,19036
72
+ recce/data/_next/static/media/montserrat-latin-800-normal.97e20d5e.woff,sha256=O3hUbMaqKvL7tlGscLIlvxQbLpHgOmCRLfwQ6RjJvE0,20784
73
+ recce/data/_next/static/media/montserrat-latin-ext-800-normal.013b84f9.woff2,sha256=tOnyR2cgiUm1cKtlrN9CY6FzD2yAMBe90slHKC0cBms,33776
74
+ recce/data/_next/static/media/montserrat-latin-ext-800-normal.aff52ab0.woff,sha256=IaGLu1tg0bPED9SLQjsK_VdkG3_RCq82GBmSP56xNFU,41956
75
+ recce/data/_next/static/media/montserrat-vietnamese-800-normal.5f21869b.woff,sha256=9ke3AivSl-ihV218s2s9NyJS8t0ETKDdqIK4rJWiPl0,7544
76
+ recce/data/_next/static/media/montserrat-vietnamese-800-normal.c0035377.woff2,sha256=bnmP7vEVe-4gLSDBsmKqD-SATv6-Pg-pxnTpSj7BCeI,7948
77
+ recce/data/imgs/feedback/thumbs-down.png,sha256=q9KVIbaZku1TWkYHuleYlO-b6HsTApYh3St5xNHMGMg,10695
78
+ recce/data/imgs/feedback/thumbs-up.png,sha256=VF3BH8bmYEqcSsMDJO57xMqW4t6crCXUXaMlOPgI_OE,10556
79
+ recce/data/logo/recce-logo-white.png,sha256=y3re8iEucJnMUkAkRS2CjWHTlOydyvgWdWjuQKcXDbk,46923
80
+ recce/event/CONFIG,sha256=w8_AVcNu_JF-t8lNmjOqtsXbeOawMzpEhkISaMlm-iU,48
81
+ recce/event/SENTRY_DNS,sha256=nWXZevLC4qDScvNtjs329X13oxqvtFI_Kiu6cfCDOBA,83
82
+ recce/event/__init__.py,sha256=5yUqhpRUPejLbaQb7kRUXYtXUwqGYzm8ewga-PYmssQ,8387
83
+ recce/event/collector.py,sha256=1Y02A77CkMMrRv-5F1KUAMGebG7m3wXhsvcPdXM2Ugg,5661
84
+ recce/event/track.py,sha256=xDyDWblhR6mp0tezEYhkA0aOyZLqXBpJyHZwhI2xhU8,4803
85
+ recce/models/__init__.py,sha256=2ai4y8o0HfV358-qjSBBEC0KxqBwsdrbAdG2kT12mIo,104
86
+ recce/models/check.py,sha256=jjR1SGyczjrqyK-0Zas6ikLIGSgVp54lvfcQA19AniI,1588
87
+ recce/models/run.py,sha256=QK2gvOWvko9YYhd2NLs3BPt5l4MSCZGwpzTAiqx9zJw,1161
88
+ recce/models/types.py,sha256=leifP8zMuUcsK4nmtBlcI-Lz1mvDhGYg__POrR_hODg,3130
89
+ recce/tasks/__init__.py,sha256=qtOCHacoGndJ3MunCXe8HtYXpy8b-6jOl5ZCI5IuM2M,316
90
+ recce/tasks/core.py,sha256=JFYa1CfgOiRPQ7KVTwMuxJjhMB-pvCwB-xezVt-h3RU,4080
91
+ recce/tasks/dataframe.py,sha256=03UBWwt0DFTXlaEOtnV5i_mxdRKD7UbRayewEL2Ub48,3650
92
+ recce/tasks/histogram.py,sha256=SMdSznzrBdAFvAbhsoUGAK9o0QUMYy00IVbamUVTpBk,13601
93
+ recce/tasks/lineage.py,sha256=_PbY0ZkDr620U8V2olqoX_T9XA0-G8ILt_6m1Q5TfBs,541
94
+ recce/tasks/profile.py,sha256=gMgms9qvdDsihh2aSC6LvCm9ggah4Oq3xjvmCh_exrU,11352
95
+ recce/tasks/query.py,sha256=k3y_IK1_3D2j4Scw-70ccDjVMa-Oe9jqxlDyLHfjagw,12790
96
+ recce/tasks/rowcount.py,sha256=DIC17VUKtGhEHz6lW4VFLHyD6F4e4QV0i_Dsz4HAv1w,9750
97
+ recce/tasks/schema.py,sha256=HHrSvhd_ZJdrNj2QKi9W8vmig0NuYci5cgsKFvp2bu4,2274
98
+ recce/tasks/top_k.py,sha256=vY3VCBmg61E8I4V-9-hJOv5RCYCmhxl6sHiKR9Zv7eE,5521
99
+ recce/tasks/valuediff.py,sha256=XJWkA307B5qTerT87fJRhJxPCqjmXn5eILYCXDfPtSQ,16439
100
+ recce/util/__init__.py,sha256=0lcJectK7Z7k9h0EaYCcv4Bgw2PN03OdJoxb3tbV5j8,37
101
+ recce/util/breaking.py,sha256=_63SJhEqYVIsIp7SqXA9Muh2fDcvgjm9RhfZ3nTNJFQ,12593
102
+ recce/util/cache.py,sha256=QB6wzxe0M3jNTwP0M27Ys8F2hF-oda4-LyXXG9THuZQ,646
103
+ recce/util/cll.py,sha256=eg32KNz4Ec-FkOLSgMwP8TrW_TTUydI7xTb_UAbt-oI,12164
104
+ recce/util/io.py,sha256=53s4uDFT6ftpI-12MBxfv-RiBkWvPXMvdxPO9lJrjJM,3374
105
+ recce/util/lineage.py,sha256=C-jNqRARgwAEQoicO5t7D0XGBkcVs6SyxLzfzCAqkPQ,707
106
+ recce/util/logger.py,sha256=6UgLFkRiur9jJfu2ZRdo4LUvMw4f75V-l-1HT1-sgKo,747
107
+ recce/util/pydantic_model.py,sha256=KumKuyCjbTzEMsKLE4-b-eZfp0gLhYDdmVtw1-hxiJw,587
108
+ recce/util/recce_cloud.py,sha256=F9Y4zqUVqQAzbLrWnccJdSjGPHzhGCVBfN4mOGVwpL8,6822
109
+ recce/util/singleton.py,sha256=1cU99I0f9tjuMQLMJyLsK1oK3fZJMsO5-TbRHAMXqds,627
110
+ recce/yaml/__init__.py,sha256=EgXYlFeJZchatUClRDXbIC5Oqb2_nBvB2NqItYVihio,1292
111
+ recce_nightly-1.4.0.20250514.dist-info/licenses/LICENSE,sha256=CQjjMy9aYPhfe8xG_bcpIfKtNkdxLZ5IOb8oPygtUhY,11343
112
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
113
+ tests/test_cli.py,sha256=f0n15QNVAyCqkygwIUp2aaoNAQau1zZp-nXpK4yyf1E,5444
114
+ tests/test_config.py,sha256=ODDFe_XF6gphmSmmc422dGLBaCCmG-IjDzTkD5SJsJE,1557
115
+ tests/test_core.py,sha256=oDaZz1nrMxoi-3GwA7sRwCJjk99M6C7dyBqGiJmB62A,785
116
+ tests/test_dbt.py,sha256=n3-Y3NaJI8ewdBKGoOldsWpTedwzCZM4Cp_6UYaURo8,1323
117
+ tests/test_pull_request.py,sha256=HmZo5MoDaoKSgPwbLxJ3Ur3ajZ7IxhkzJxaOmhg6bwE,3562
118
+ tests/test_server.py,sha256=7MYAr3ZvLIeFQ_DlvUW9sgV7wBr0gDMJchEC97zup8M,3383
119
+ tests/test_state.py,sha256=p6rIwEh78GBBocqv98elX14WzqrpXNpnfd4uWI8u1bI,5022
120
+ tests/test_summary.py,sha256=D0WvAkdO-vzGcvholH2rfS1wTxUXjVHwWm59fWy45eA,2876
121
+ tests/adapter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
122
+ tests/adapter/dbt_adapter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
123
+ tests/adapter/dbt_adapter/conftest.py,sha256=bLPgVhwLZpHsYm1bf7CrjNwqu3XZQuzc7CJDjbu8qZk,272
124
+ tests/adapter/dbt_adapter/dbt_test_helper.py,sha256=6yvz8UXzzFyNaL2uUHjJm1zPlhe2PUEpnkH737iRTjQ,9957
125
+ tests/adapter/dbt_adapter/test_dbt_adapter.py,sha256=Y5TSlqkXGjJC6hC7YYs45bnRht5aou_KLjPMjpAGxNM,830
126
+ tests/adapter/dbt_adapter/test_dbt_cll.py,sha256=J_jZ3am8czzSWDxW08Fw1gSggziPBH0pl8bJmz7uFQE,4109
127
+ tests/adapter/dbt_adapter/test_selector.py,sha256=uKFm0QxrxG-xyUEXGobCMueCRUssgnZMyo-S1Nlk3_s,6856
128
+ tests/tasks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
129
+ tests/tasks/conftest.py,sha256=UefgbNfJufLOmgHLiEFXIjOVmu8-58GbS6m5-NcEu20,143
130
+ tests/tasks/test_histogram.py,sha256=g69R2Ljvcd8RQTnq7EMZEa93_1vVWNe4ZLg990rWuyA,4088
131
+ tests/tasks/test_lineage.py,sha256=HODSP2_uSu98e4jV-t9TIOSrln_5mXd-6baKv9aEmws,1095
132
+ tests/tasks/test_preset_checks.py,sha256=fAro5kAv67YiXgRFj7hDAgZEd8fVSHW_VTapVDq4G04,1457
133
+ tests/tasks/test_profile.py,sha256=c26igXN1r6sw-iDf79Skis3B-q2o3VPRamQCuZ43GfY,10262
134
+ tests/tasks/test_query.py,sha256=_Lnew7hVEaFtZs3hWcTgF67YFtgE7AkDVdWyLr9oF5E,4253
135
+ tests/tasks/test_row_count.py,sha256=21PaP2aq-x8-pqwzWHRT1sixhQ8g3CQNRWOZTTmbK0s,3151
136
+ tests/tasks/test_schema.py,sha256=7ds4Vx8ixaiIWDR49Lvjem4xlPkRP1cXazDRY3roUak,3121
137
+ tests/tasks/test_top_k.py,sha256=YR_GS__DJsbDlQVaEEdJvNQ3fh1VmV5Nb3G7lb0r6YM,1779
138
+ tests/tasks/test_valuediff.py,sha256=_xQJGgxsXoy2NYk_Z6Hsw2FlVh6zk2nN_iUueyRN1e8,2046
139
+ recce_nightly-1.4.0.20250514.dist-info/METADATA,sha256=UDAsDhfJj9EFwSQ3lrAYIKAIEbg7eH7MIRTNheALq7A,9299
140
+ recce_nightly-1.4.0.20250514.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
141
+ recce_nightly-1.4.0.20250514.dist-info/entry_points.txt,sha256=oqoY_IiwIqXbgrIsPnlqUqao2eiIeP2dprowkOlmeyg,40
142
+ recce_nightly-1.4.0.20250514.dist-info/top_level.txt,sha256=6PKGVpf75idP0C6KEaldDzzZUauIxNu1ZDstau1pI4I,12
143
+ recce_nightly-1.4.0.20250514.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.3.1)
2
+ Generator: setuptools (80.4.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,6 +1,7 @@
1
1
  import pytest
2
2
 
3
3
  from recce.core import set_default_context
4
+
4
5
  from .dbt_test_helper import DbtTestHelper
5
6
 
6
7