dbt-bouncer 1.31.2rc3__py3-none-any.whl → 2.0.0rc1__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.
Files changed (36) hide show
  1. dbt_bouncer/artifact_parsers/dbt_cloud/catalog_latest.py +21 -21
  2. dbt_bouncer/artifact_parsers/dbt_cloud/manifest_latest.py +1745 -1745
  3. dbt_bouncer/artifact_parsers/dbt_cloud/run_results_latest.py +22 -22
  4. dbt_bouncer/artifact_parsers/parsers_catalog.py +26 -24
  5. dbt_bouncer/artifact_parsers/parsers_common.py +57 -36
  6. dbt_bouncer/artifact_parsers/parsers_manifest.py +98 -69
  7. dbt_bouncer/artifact_parsers/parsers_run_results.py +32 -19
  8. dbt_bouncer/check_base.py +22 -11
  9. dbt_bouncer/checks/catalog/check_catalog_sources.py +22 -12
  10. dbt_bouncer/checks/catalog/check_columns.py +175 -105
  11. dbt_bouncer/checks/common.py +24 -3
  12. dbt_bouncer/checks/manifest/check_exposures.py +79 -52
  13. dbt_bouncer/checks/manifest/check_lineage.py +69 -40
  14. dbt_bouncer/checks/manifest/check_macros.py +177 -104
  15. dbt_bouncer/checks/manifest/check_metadata.py +28 -18
  16. dbt_bouncer/checks/manifest/check_models.py +842 -496
  17. dbt_bouncer/checks/manifest/check_seeds.py +63 -0
  18. dbt_bouncer/checks/manifest/check_semantic_models.py +28 -20
  19. dbt_bouncer/checks/manifest/check_snapshots.py +57 -33
  20. dbt_bouncer/checks/manifest/check_sources.py +246 -137
  21. dbt_bouncer/checks/manifest/check_unit_tests.py +97 -54
  22. dbt_bouncer/checks/run_results/check_run_results.py +34 -20
  23. dbt_bouncer/config_file_parser.py +47 -28
  24. dbt_bouncer/config_file_validator.py +11 -8
  25. dbt_bouncer/global_context.py +31 -0
  26. dbt_bouncer/main.py +128 -67
  27. dbt_bouncer/runner.py +61 -31
  28. dbt_bouncer/utils.py +146 -50
  29. dbt_bouncer/version.py +1 -1
  30. {dbt_bouncer-1.31.2rc3.dist-info → dbt_bouncer-2.0.0rc1.dist-info}/METADATA +15 -15
  31. dbt_bouncer-2.0.0rc1.dist-info/RECORD +37 -0
  32. dbt_bouncer-1.31.2rc3.dist-info/RECORD +0 -35
  33. {dbt_bouncer-1.31.2rc3.dist-info → dbt_bouncer-2.0.0rc1.dist-info}/WHEEL +0 -0
  34. {dbt_bouncer-1.31.2rc3.dist-info → dbt_bouncer-2.0.0rc1.dist-info}/entry_points.txt +0 -0
  35. {dbt_bouncer-1.31.2rc3.dist-info → dbt_bouncer-2.0.0rc1.dist-info}/licenses/LICENSE +0 -0
  36. {dbt_bouncer-1.31.2rc3.dist-info → dbt_bouncer-2.0.0rc1.dist-info}/top_level.txt +0 -0
dbt_bouncer/utils.py CHANGED
@@ -1,17 +1,17 @@
1
- # mypy: disable-error-code="arg-type,attr-defined,union-attr"
2
-
3
1
  """Re-usable functions for dbt-bouncer."""
4
2
 
5
3
  import importlib
4
+ import importlib.util
5
+ import inspect
6
6
  import logging
7
7
  import os
8
8
  import re
9
9
  import sys
10
+ from collections.abc import Mapping
10
11
  from functools import lru_cache
11
12
  from pathlib import Path
12
- from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Type
13
+ from typing import TYPE_CHECKING, Any
13
14
 
14
- import click
15
15
  import yaml
16
16
  from packaging.version import Version as PyPIVersion
17
17
  from semver import Version
@@ -31,7 +31,7 @@ def clean_path_str(path: str) -> str:
31
31
 
32
32
 
33
33
  def create_github_comment_file(
34
- failed_checks: List[List[str]], show_all_failures: bool
34
+ failed_checks: list[list[str]], show_all_failures: bool
35
35
  ) -> None:
36
36
  """Create a markdown file containing a comment for GitHub."""
37
37
  md_formatted_comment = make_markdown_table(
@@ -59,7 +59,7 @@ def create_github_comment_file(
59
59
 
60
60
 
61
61
  def get_nested_value(
62
- d: Dict[str, Any], keys: List[str], default: Optional[Any] = None
62
+ d: dict[str, Any], keys: list[str], default: Any | None = None
63
63
  ) -> Any:
64
64
  """Retrieve a value from a nested dictionary using a list of keys.
65
65
 
@@ -104,11 +104,11 @@ def resource_in_path(check, resource) -> bool:
104
104
  )
105
105
 
106
106
 
107
- def find_missing_meta_keys(meta_config, required_keys) -> List[str]:
107
+ def find_missing_meta_keys(meta_config, required_keys) -> list[str]:
108
108
  """Find missing keys in a meta config.
109
109
 
110
110
  Returns:
111
- List[str]: List of missing keys.
111
+ list[str]: List of missing keys.
112
112
 
113
113
  """
114
114
  # Get all keys in meta config
@@ -150,54 +150,133 @@ def flatten(structure: Any, key: str = "", path: str = "", flattened=None):
150
150
  return flattened
151
151
 
152
152
 
153
+ def _extract_checks_from_module(
154
+ module: Any, module_name: str, check_objects: list[type["BaseCheck"]]
155
+ ) -> None:
156
+ """Extract Check* classes from a loaded module.
157
+
158
+ Inspects the given module and appends any class whose name starts with
159
+ "Check" and is defined within the specified module (not imported from
160
+ elsewhere) to the provided check_objects list.
161
+
162
+ Args:
163
+ module: The loaded module object to inspect.
164
+ module_name: The fully qualified name of the module (used to filter
165
+ out imported classes).
166
+ check_objects: A list to which discovered check classes will be
167
+ appended.
168
+
169
+ """
170
+ for name, obj in inspect.getmembers(module):
171
+ if (
172
+ inspect.isclass(obj)
173
+ and name.startswith("Check")
174
+ and obj.__module__ == module_name
175
+ ):
176
+ check_objects.append(obj)
177
+
178
+
179
+ def _load_custom_checks(
180
+ custom_checks_dir: Path, check_objects: list[type["BaseCheck"]]
181
+ ) -> None:
182
+ """Load custom check classes from a directory.
183
+
184
+ Scans the specified directory for Python files in subdirectories
185
+ (e.g., `custom_checks_dir/category/check_file.py`) and loads any
186
+ Check* classes defined in them.
187
+
188
+ Each file is loaded as a uniquely named module to avoid conflicts with
189
+ internal checks or other custom checks.
190
+
191
+ Args:
192
+ custom_checks_dir: Path to the directory containing custom checks.
193
+ check_objects: A list to which discovered check classes will be
194
+ appended.
195
+
196
+ Raises:
197
+ RuntimeError: If a custom check file fails to load.
198
+
199
+ """
200
+ logging.debug(f"{custom_checks_dir=}")
201
+ if custom_checks_dir.exists():
202
+ custom_check_files = [
203
+ f for f in custom_checks_dir.glob("*/*.py") if f.is_file()
204
+ ]
205
+ logging.debug(f"{custom_check_files=}")
206
+
207
+ for check_file in custom_check_files:
208
+ # Use a unique module name to avoid conflicts
209
+ unique_module_name = (
210
+ f"custom_check_{check_file.stem}_{abs(hash(str(check_file)))}"
211
+ )
212
+
213
+ try:
214
+ spec = importlib.util.spec_from_file_location(
215
+ unique_module_name, check_file
216
+ )
217
+ if spec and spec.loader:
218
+ module = importlib.util.module_from_spec(spec)
219
+ sys.modules[unique_module_name] = module
220
+ spec.loader.exec_module(module)
221
+
222
+ _extract_checks_from_module(
223
+ module, unique_module_name, check_objects
224
+ )
225
+ except Exception as e:
226
+ raise RuntimeError(
227
+ f"Failed to load custom check file {check_file}: {e}"
228
+ ) from e
229
+ else:
230
+ logging.warning(
231
+ f"Custom checks directory `{custom_checks_dir}` does not exist."
232
+ )
233
+
234
+
153
235
  @lru_cache
154
- def get_check_objects() -> List[Type["BaseCheck"]]:
155
- """Get list of Check* classes and check_* functions.
236
+ def get_check_objects(
237
+ custom_checks_dir: Path | None = None,
238
+ ) -> list[type["BaseCheck"]]:
239
+ """Get list of Check* classes.
240
+
241
+ This function dynamically discovers and loads check classes from two sources:
242
+ 1. Internal checks located in the `checks` directory of the package.
243
+ 2. Custom checks located in the specified `custom_checks_dir` (if provided).
244
+
245
+ It filters for classes that:
246
+ - Start with "Check".
247
+ - Are defined within the loaded module (not imported).
248
+
249
+ The result is cached using `@lru_cache` to avoid redundant file scanning
250
+ and module loading on subsequent calls. Import errors in individual files
251
+ are logged as warnings and do not stop execution.
252
+
253
+ Args:
254
+ custom_checks_dir: Path to a directory containing custom checks.
156
255
 
157
256
  Returns:
158
- List[Type[BaseCheck]]: List of Check* classes.
257
+ list[type[BaseCheck]]: List of Check* classes.
159
258
 
160
259
  """
260
+ check_objects: list[type["BaseCheck"]] = []
161
261
 
162
- def import_check(check_class_name: str, check_file_path: str) -> None:
163
- """Import the Check* class to locals()."""
164
- spec = importlib.util.spec_from_file_location(check_class_name, check_file_path)
165
- module = importlib.util.module_from_spec(spec)
166
- spec.loader.exec_module(module)
167
- sys._getframe().f_locals[check_class_name] = module
168
- check_objects.append(locals()[check_class_name])
169
-
170
- check_objects: List[Type["BaseCheck"]] = []
262
+ # 1. Load internal checks
171
263
  check_files = [
172
264
  f for f in (Path(__file__).parent / "checks").glob("*/*.py") if f.is_file()
173
265
  ]
174
266
  for check_file in check_files:
175
- check_qual_name = ".".join(
176
- [x.replace(".py", "") for x in check_file.parts[-4:]]
267
+ # e.g. dbt_bouncer.checks.manifest.check_models
268
+ module_name = ".".join(
269
+ ["dbt_bouncer", "checks", check_file.parts[-2], check_file.stem]
177
270
  )
178
- imported_check_file = importlib.import_module(check_qual_name)
179
-
180
- for obj in [i for i in dir(imported_check_file) if i.startswith("Check")]:
181
- import_check(obj, check_file.absolute().__str__())
271
+ try:
272
+ module = importlib.import_module(module_name)
273
+ _extract_checks_from_module(module, module_name, check_objects)
274
+ except ImportError:
275
+ logging.warning(f"Failed to import internal check module: {module_name}")
182
276
 
183
- config_file_path = click.get_current_context().obj["config_file_path"]
184
- custom_checks_dir = click.get_current_context().obj["custom_checks_dir"]
277
+ # 2. Load custom checks (if any)
185
278
  if custom_checks_dir is not None:
186
- custom_checks_dir = config_file_path.parent / custom_checks_dir
187
- logging.debug(f"{custom_checks_dir=}")
188
- custom_check_files = [
189
- f for f in Path(custom_checks_dir).glob("*/*.py") if f.is_file()
190
- ]
191
- logging.debug(f"{custom_check_files=}")
192
-
193
- for check_file in custom_check_files:
194
- spec = importlib.util.spec_from_file_location("custom_check", check_file)
195
- foo = importlib.util.module_from_spec(spec)
196
- sys.modules["custom_check"] = foo
197
- spec.loader.exec_module(foo)
198
- for obj in dir(foo):
199
- if obj.startswith("Check"):
200
- import_check(obj, check_file.absolute().__str__())
279
+ _load_custom_checks(Path(custom_checks_dir), check_objects)
201
280
 
202
281
  logging.debug(f"Loaded {len(check_objects)} `Check*` classes.")
203
282
 
@@ -233,6 +312,26 @@ def get_package_version_number(version_string: str) -> Version:
233
312
  return Version(*p.release)
234
313
 
235
314
 
315
+ def is_description_populated(description: str, min_description_length: int) -> bool:
316
+ """Check if a description is populated.
317
+
318
+ Args:
319
+ description (str): Description.
320
+ min_description_length (int): Minimum length of the description.
321
+
322
+ Returns:
323
+ bool: Whether a description is validly populated.
324
+
325
+ """
326
+ return len(
327
+ description.strip()
328
+ ) >= min_description_length and description.strip().lower() not in (
329
+ "none",
330
+ "null",
331
+ "n/a",
332
+ )
333
+
334
+
236
335
  def load_config_from_yaml(config_file: Path) -> Mapping[str, Any]:
237
336
  """Safely load a YAML file to a dict object.
238
337
 
@@ -259,7 +358,7 @@ def load_config_from_yaml(config_file: Path) -> Mapping[str, Any]:
259
358
  return conf
260
359
 
261
360
 
262
- def make_markdown_table(array: List[List[str]]) -> str:
361
+ def make_markdown_table(array: list[list[str]]) -> str:
263
362
  """Transform a list of lists into a markdown table. The first element is the header row.
264
363
 
265
364
  Returns:
@@ -281,7 +380,7 @@ def make_markdown_table(array: List[List[str]]) -> str:
281
380
  return markdown
282
381
 
283
382
 
284
- def object_in_path(include_pattern: str, path: str) -> bool:
383
+ def object_in_path(include_pattern: str | None, path: str) -> bool:
285
384
  """Determine if an object is included in the specified path pattern.
286
385
 
287
386
  If no pattern is specified then all objects are included.
@@ -290,9 +389,6 @@ def object_in_path(include_pattern: str, path: str) -> bool:
290
389
  bool: True if the object is included in the path pattern, False otherwise.
291
390
 
292
391
  """
293
- if include_pattern is not None:
294
- return (
295
- re.compile(include_pattern.strip()).match(clean_path_str(path)) is not None
296
- )
297
- else:
392
+ if include_pattern is None:
298
393
  return True
394
+ return re.compile(include_pattern.strip()).match(clean_path_str(path)) is not None
dbt_bouncer/version.py CHANGED
@@ -5,4 +5,4 @@ def version() -> str:
5
5
  str: The version of `dbt-bouncer`.
6
6
 
7
7
  """
8
- return "1.31.2rc3"
8
+ return "2.0.0rc1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbt-bouncer
3
- Version: 1.31.2rc3
3
+ Version: 2.0.0rc1
4
4
  Summary: Configure and enforce conventions for your dbt project.
5
5
  Author-email: Padraic Slattery <pgoslatara@gmail.com>
6
6
  Maintainer-email: Padraic Slattery <pgoslatara@gmail.com>
@@ -13,43 +13,40 @@ Classifier: Programming Language :: Python :: 3 :: Only
13
13
  Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
15
  Classifier: Programming Language :: Python :: 3.13
16
- Requires-Python: <3.14,>=3.11
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Requires-Python: <3.15,>=3.11
17
18
  Description-Content-Type: text/markdown
18
19
  License-File: LICENSE
19
- Requires-Dist: click<9
20
+ Requires-Dist: click!=8.3.0,!=8.3.1,<9
20
21
  Requires-Dist: dbt-artifacts-parser>=0.8
21
22
  Requires-Dist: h11>=0.16.0
22
23
  Requires-Dist: jellyfish<2,>=1
23
24
  Requires-Dist: jinja2<4,>=3
24
25
  Requires-Dist: jinja2-simple-tags<1
25
- Requires-Dist: packaging<25
26
+ Requires-Dist: packaging<26
26
27
  Requires-Dist: progress
27
28
  Requires-Dist: pydantic<3,>=2
29
+ Requires-Dist: pytest<=10
28
30
  Requires-Dist: pyyaml<7
29
31
  Requires-Dist: requests<3,>=2
30
32
  Requires-Dist: tabulate<1
31
33
  Requires-Dist: toml<1
32
34
  Requires-Dist: semver<4
33
35
  Provides-Extra: dev
34
- Requires-Dist: autoflake~=2.0; extra == "dev"
35
- Requires-Dist: black~=25.0; extra == "dev"
36
- Requires-Dist: dbt-core<2,>=1.10.0; extra == "dev"
36
+ Requires-Dist: bandit~=1.0; extra == "dev"
37
+ Requires-Dist: dbt-core<2,>=1.11.2; extra == "dev"
37
38
  Requires-Dist: dbt-duckdb~=1.0; extra == "dev"
38
- Requires-Dist: isort~=7.0; extra == "dev"
39
- Requires-Dist: mypy~=1.0; extra == "dev"
40
- Requires-Dist: pre-commit<5,>=3; extra == "dev"
41
- Requires-Dist: pytest<=10; extra == "dev"
39
+ Requires-Dist: prek<1,>=0.1; extra == "dev"
42
40
  Requires-Dist: pytest-cov<8,>=5; extra == "dev"
43
41
  Requires-Dist: pytest-xdist~=3.0; extra == "dev"
42
+ Requires-Dist: pyupgrade~=3.0; extra == "dev"
44
43
  Requires-Dist: ruff~=0.0; extra == "dev"
45
44
  Requires-Dist: shandy-sqlfmt[jinjafmt]~=0.0; extra == "dev"
46
- Requires-Dist: types-PyYaml~=6.0; extra == "dev"
47
- Requires-Dist: types-tabulate~=0.0; extra == "dev"
48
- Requires-Dist: types-toml~=0.0; extra == "dev"
45
+ Requires-Dist: ty>=0.0.7; extra == "dev"
49
46
  Provides-Extra: docs
50
47
  Requires-Dist: mike~=2.0; extra == "docs"
51
48
  Requires-Dist: mkdocs~=1.0; extra == "docs"
52
- Requires-Dist: mkdocstrings-python<2; extra == "docs"
49
+ Requires-Dist: mkdocstrings-python<3; extra == "docs"
53
50
  Requires-Dist: mkdocs-click~=0.0; extra == "docs"
54
51
  Requires-Dist: mkdocs-git-revision-date-localized-plugin~=1.0; extra == "docs"
55
52
  Requires-Dist: mkdocs-material~=9.0; extra == "docs"
@@ -75,6 +72,9 @@ Dynamic: license-file
75
72
  <a>
76
73
  <img src="https://img.shields.io/badge/License-MIT-yellow.svg">
77
74
  </a>
75
+ <a>
76
+ <img alt="security: bandit" href="https://github.com/PyCQA/bandit" src="https://img.shields.io/badge/security-bandit-yellow.svg">
77
+ </a>
78
78
  <a>
79
79
  <img src="https://img.shields.io/github/last-commit/godatadriven/dbt-bouncer/main">
80
80
  </a>
@@ -0,0 +1,37 @@
1
+ dbt_bouncer/__init__.py,sha256=vJ9zw-0crTEO2MzmPQUUCebBQCSYiOleGNUUx_eX3eo,33
2
+ dbt_bouncer/check_base.py,sha256=q40xQ7nG51V7YXhob20_Csgsv57v_4hnIOXGiD7Q4Jg,2920
3
+ dbt_bouncer/config_file_parser.py,sha256=iun73dJfaC6n171YihA4pEVM22wngHOIcwXGVC7BU-k,5653
4
+ dbt_bouncer/config_file_validator.py,sha256=oOs4lgflLIMKdARra3Je0MggzF4gEfBRwFWioSn-BNQ,11330
5
+ dbt_bouncer/global_context.py,sha256=5ct2jjtaTtfgO8vHYCBETaxOoYG4u5lDaBltFn0RJzE,690
6
+ dbt_bouncer/logger.py,sha256=qkwB-SVUE4YUUp-MtmbcDPUX7t3zdniQL5Linuomr94,1804
7
+ dbt_bouncer/main.py,sha256=wQtl3i7QDoo4ymiYrneaRBecDHWSNwSBY7B0GSnT1NU,8694
8
+ dbt_bouncer/runner.py,sha256=1JjMecab6d5UYkWBa4bkw5SWlA0RDb40sbp7YB_9BYw,11650
9
+ dbt_bouncer/utils.py,sha256=WaqIVRCvuHRqnN3lMd9xtzLGJ-E06gz3Ols6jIZZC5k,12810
10
+ dbt_bouncer/version.py,sha256=Xd_u4K-00ASNLNIka953jW8CU5JQazjTBPzuFpHkfQ8,151
11
+ dbt_bouncer/artifact_parsers/parsers_catalog.py,sha256=CbW_8IoNX8Son32Z5Ca2aqoyqPLalD6zKokogZOe-6s,3173
12
+ dbt_bouncer/artifact_parsers/parsers_common.py,sha256=R6CBF8EwpqUZnApLFST3CxSB9eauPaz_oU8bDXU5kCo,7390
13
+ dbt_bouncer/artifact_parsers/parsers_manifest.py,sha256=79zMP2MhOsaqioc8VxO9vMRJcdY1ALQ_CvWEPO8OpWE,10698
14
+ dbt_bouncer/artifact_parsers/parsers_run_results.py,sha256=6gy-O8DtM7wvkK8-CO63e4PDcUrWPPk8fowkCfnc9z4,4301
15
+ dbt_bouncer/artifact_parsers/dbt_cloud/catalog_latest.py,sha256=OxPqLdD5FuBHMasFCrbrMSf2DQLGBBSwWZGq0Yqd9PA,1986
16
+ dbt_bouncer/artifact_parsers/dbt_cloud/manifest_latest.py,sha256=ckKaCAtbUfwxvdBfCaCCYpHKGGU4t8K8tpswhCfVSQs,112404
17
+ dbt_bouncer/artifact_parsers/dbt_cloud/run_results_latest.py,sha256=BtQyf3nOLSYk5kk8zXaGvh1zfwMVQpRLJ3K-WD2h_FY,2048
18
+ dbt_bouncer/checks/common.py,sha256=o_SNf027I5pRDYHGiJozd1oth1mlKEyr6dP-5ARVO-0,701
19
+ dbt_bouncer/checks/catalog/check_catalog_sources.py,sha256=B1genNB-fn_Q9S11M1BjK2LUfmC6ZcD5DgkzQ7akhIU,2589
20
+ dbt_bouncer/checks/catalog/check_columns.py,sha256=XAzVpCitEHtRXdIrR64rSaJzTty8WGW2ehBPGpsbwHE,18866
21
+ dbt_bouncer/checks/manifest/check_exposures.py,sha256=YOqDiXy5kRo8TXPQUCZmD0-6Q3TjyJ7gtbCiYEvUWi8,8108
22
+ dbt_bouncer/checks/manifest/check_lineage.py,sha256=YoUD8J3-k4wMesHZ5RqSFCml-ZXDHAA5L6_JnYNpno4,6887
23
+ dbt_bouncer/checks/manifest/check_macros.py,sha256=3mHLa7nzMhB37Kb4arzcBMADeEI2yFG3VT3Mc4CulXs,15315
24
+ dbt_bouncer/checks/manifest/check_metadata.py,sha256=O7VqiI8FTA7wrs5_dk_DP7PwvARojk5OuAtBbeZSsWU,2473
25
+ dbt_bouncer/checks/manifest/check_models.py,sha256=ixWgqml6sBFc5UoCXrv70wbv33xvWEG6Oa_cHzW5r_w,79436
26
+ dbt_bouncer/checks/manifest/check_seeds.py,sha256=JDl-LbWnPiZbmB2VTX64yqMIM30-g963Qn8pjSYpfSs,2076
27
+ dbt_bouncer/checks/manifest/check_semantic_models.py,sha256=DpFWkLEDvefHGPEYHr2hYYag83R9z29RU8yBwmGpaTk,2847
28
+ dbt_bouncer/checks/manifest/check_snapshots.py,sha256=Ke7OdGHLHYquNjiBrw0lMImAcpB7AHxScIim7WmWohI,4507
29
+ dbt_bouncer/checks/manifest/check_sources.py,sha256=ZsV3aL10vKX_UM4ip2pAEkGUQdTWJcIVl6hzdXXnT6E,20921
30
+ dbt_bouncer/checks/manifest/check_unit_tests.py,sha256=I0orkSnueseUHqCQv7pdmzawnxZTwepDzcl8RgS5GXg,10046
31
+ dbt_bouncer/checks/run_results/check_run_results.py,sha256=WL8neXGyPBhV_znbilVTF57__lXE97kCGB2lSc7931w,4614
32
+ dbt_bouncer-2.0.0rc1.dist-info/licenses/LICENSE,sha256=gGXp4VL__ZWlTWhXHRjWJmkxl5X9UJ7L7n1dr2WlfsY,1074
33
+ dbt_bouncer-2.0.0rc1.dist-info/METADATA,sha256=MjpYiM-8lhn01ALw2HUQxvMRYX2DsM-vjwDawXWZrtc,5717
34
+ dbt_bouncer-2.0.0rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
+ dbt_bouncer-2.0.0rc1.dist-info/entry_points.txt,sha256=BGHZ6oZsZjq5MUVKYSdbwy80f7cEOCTC-UqqEN1GrBg,53
36
+ dbt_bouncer-2.0.0rc1.dist-info/top_level.txt,sha256=TnVuJYP3nH_F7nkc63iXA34kAnwrOWWDpTUyd-GLpR4,12
37
+ dbt_bouncer-2.0.0rc1.dist-info/RECORD,,
@@ -1,35 +0,0 @@
1
- dbt_bouncer/__init__.py,sha256=vJ9zw-0crTEO2MzmPQUUCebBQCSYiOleGNUUx_eX3eo,33
2
- dbt_bouncer/check_base.py,sha256=haCZiOn-7cod2XPWoOjUozJVVV7JGOK8OSwvZYsLwTw,2565
3
- dbt_bouncer/config_file_parser.py,sha256=JjFoPhFARgPB_q8BnjRp9C9E5FhO1mcBWrDYEyeOfc4,5009
4
- dbt_bouncer/config_file_validator.py,sha256=CzuEh_1cNQ-2zl7TA-9RKMECOAOoxcQLgODh9-7JHwA,11262
5
- dbt_bouncer/logger.py,sha256=qkwB-SVUE4YUUp-MtmbcDPUX7t3zdniQL5Linuomr94,1804
6
- dbt_bouncer/main.py,sha256=n-jOsKlDwAlB2uF__J_DtkU8BC7CqeKMOU_f8axB1fo,6433
7
- dbt_bouncer/runner.py,sha256=fdgpOUS8ckS_rZbklOUqFSxmD6I8WYRhQU09HZI0Ghs,10628
8
- dbt_bouncer/utils.py,sha256=-jZjc6R0tjHWqpTjgHIb7Ej6Cqwdbchbl7L8IB4mo1I,9890
9
- dbt_bouncer/version.py,sha256=jTw3-MfxlpBMMndkhV7FXFhjGnqbMBCIVzzObL1fknM,152
10
- dbt_bouncer/artifact_parsers/parsers_catalog.py,sha256=2VbD3zib0jZdy7SCaYNQeYDXlxKpQykgOY7rUNnjQH0,3130
11
- dbt_bouncer/artifact_parsers/parsers_common.py,sha256=KAbnDHPnC2uHn91FK8UZ8wYOs-jTBYQSzyuowKxCSUU,6729
12
- dbt_bouncer/artifact_parsers/parsers_manifest.py,sha256=I9UnoNIHiAXXMGkZ-JEAbYKT6oGgBFtIUoOx14HeReU,9644
13
- dbt_bouncer/artifact_parsers/parsers_run_results.py,sha256=Qv6HhHmD1jxFPypgvmexl5JfVEaltREiCikJPIYQ9dE,3786
14
- dbt_bouncer/artifact_parsers/dbt_cloud/catalog_latest.py,sha256=W575XZj7U9fC7recAUzf63cFBh4gghyjYSVYmoKGN5Q,2062
15
- dbt_bouncer/artifact_parsers/dbt_cloud/manifest_latest.py,sha256=EPgjUz2pRW2nS1_ZgLgXK9douoymKJ5vRk7VM3Emm0w,117707
16
- dbt_bouncer/artifact_parsers/dbt_cloud/run_results_latest.py,sha256=d_bCyY3AM77UEemKnPlHCDcRF_UmfAO_vmPiNQ2kHIY,2111
17
- dbt_bouncer/checks/common.py,sha256=WTaZZ1vQpi1AfTu_8OLlfADngeNiVAmQ5lVaeYNUBtc,192
18
- dbt_bouncer/checks/catalog/check_catalog_sources.py,sha256=680dT_lqEem73X9Ur27-GiUskj7ALHaA16HdOUIePAo,2278
19
- dbt_bouncer/checks/catalog/check_columns.py,sha256=uQoFGW3CDxdsFPVtmGIxbm_gVwUr9AF02zfO-3D8-1s,16124
20
- dbt_bouncer/checks/manifest/check_exposures.py,sha256=qPeKwIuDmnsu5_eBgco64RYpSzhq1UueutOz-9Cpah4,7085
21
- dbt_bouncer/checks/manifest/check_lineage.py,sha256=EHUXdR5D-ihwdwfvrIGewH8bL2yHXi1cfghv3VFe1I0,5949
22
- dbt_bouncer/checks/manifest/check_macros.py,sha256=RzkKCBcyLHGKvKFZ1Cn_QGTAEjH_T_z_8IazKOJZH3c,12318
23
- dbt_bouncer/checks/manifest/check_metadata.py,sha256=E9M-EXHU9JcR__5FotvVbhWc0M-H-JieB-9Wzbunsxg,2199
24
- dbt_bouncer/checks/manifest/check_models.py,sha256=_6wL2aMNUSOqk3dInbLpcOYhVGoORnkd9HRjBTcoVTk,67851
25
- dbt_bouncer/checks/manifest/check_semantic_models.py,sha256=GFVPCn16PcNlXFLCbWMEG6NADccJnxC-latmBQ23OrU,2500
26
- dbt_bouncer/checks/manifest/check_snapshots.py,sha256=jmQNNVDn2s4UMJd0P7NAzzPPLIXWiDuE9qKTRiA4430,3795
27
- dbt_bouncer/checks/manifest/check_sources.py,sha256=HW-uZ9toO9veNaahAdxqquerC85zwaTJKQmRhvn8qbo,17092
28
- dbt_bouncer/checks/manifest/check_unit_tests.py,sha256=3_0FG91nSfC3k_dBDrJgRjF8rpzeA6GKSr3DmDP0ZTo,8417
29
- dbt_bouncer/checks/run_results/check_run_results.py,sha256=LLX8Uziyc4hv303K31wLtuXMXng3WVJF2z1j_GbogAI,4117
30
- dbt_bouncer-1.31.2rc3.dist-info/licenses/LICENSE,sha256=gGXp4VL__ZWlTWhXHRjWJmkxl5X9UJ7L7n1dr2WlfsY,1074
31
- dbt_bouncer-1.31.2rc3.dist-info/METADATA,sha256=Yj1D6xMP47fjUicbowY-IQL8rqPFN7U_Qw2i7ep8rD4,5716
32
- dbt_bouncer-1.31.2rc3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
- dbt_bouncer-1.31.2rc3.dist-info/entry_points.txt,sha256=BGHZ6oZsZjq5MUVKYSdbwy80f7cEOCTC-UqqEN1GrBg,53
34
- dbt_bouncer-1.31.2rc3.dist-info/top_level.txt,sha256=TnVuJYP3nH_F7nkc63iXA34kAnwrOWWDpTUyd-GLpR4,12
35
- dbt_bouncer-1.31.2rc3.dist-info/RECORD,,