dbt-common 1.0.0b1__tar.gz → 1.0.1__tar.gz
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.
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/PKG-INFO +18 -3
- dbt_common-1.0.1/README.md +37 -0
- dbt_common-1.0.1/dbt_common/__about__.py +1 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/clients/system.py +137 -2
- dbt_common-1.0.1/dbt_common/constants.py +6 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/context.py +8 -2
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/dataclass_schema.py +1 -0
- dbt_common-1.0.1/dbt_common/record.py +208 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/ui.py +4 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/utils/executor.py +2 -2
- dbt_common-1.0.0b1/README.md +0 -22
- dbt_common-1.0.0b1/dbt_common/__about__.py +0 -1
- dbt_common-1.0.0b1/dbt_common/constants.py +0 -1
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/.gitignore +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/CHANGELOG.md +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/LICENSE +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/codecov.yml +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/__init__.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/clients/__init__.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/clients/_jinja_blocks.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/clients/agate_helper.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/clients/jinja.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/contracts/__init__.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/contracts/config/__init__.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/contracts/config/base.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/contracts/config/materialization.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/contracts/config/metadata.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/contracts/config/properties.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/contracts/constraints.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/contracts/util.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/README.md +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/__init__.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/base_types.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/contextvars.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/event_handler.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/event_manager.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/event_manager_client.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/format.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/functions.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/helpers.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/interfaces.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/logger.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/types.proto +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/types.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/events/types_pb2.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/exceptions/__init__.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/exceptions/base.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/exceptions/cache.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/exceptions/connection.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/exceptions/contracts.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/exceptions/events.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/exceptions/jinja.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/exceptions/macros.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/exceptions/system.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/helper_types.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/invocation.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/py.typed +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/semver.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/tests.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/utils/__init__.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/utils/casting.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/utils/connection.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/utils/dict.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/utils/encoding.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/utils/formatting.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/dbt_common/utils/jinja.py +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/docs/arch/adr-0001-build-tooling.md +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/pyproject.toml +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/agate/__init__.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/agate/data_types.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/colorama/__init__.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/isodate/__init__.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/__init__.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/config.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/__init__.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/const.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/helpers.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/__init__.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/code/__init__.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/code/builder.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/code/lines.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/helpers.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/mixin.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/types/__init__.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/types/common.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/types/pack.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/types/unpack.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/dialect.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/exceptions.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/helper.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/jsonschema/__init__.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/jsonschema/annotations.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/jsonschema/builder.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/jsonschema/dialects.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/jsonschema/models.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/jsonschema/schema.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/mixins/__init__.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/mixins/dict.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/mixins/json.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/mixins/msgpack.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/mixins/orjson.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/mixins/toml.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/mixins/yaml.pyi +0 -0
- {dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/types.pyi +0 -0
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: dbt-common
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.1
|
4
4
|
Summary: The shared common utilities that dbt-core and adapter implementations use
|
5
5
|
Project-URL: Homepage, https://github.com/dbt-labs/dbt-common
|
6
6
|
Project-URL: Repository, https://github.com/dbt-labs/dbt-common.git
|
@@ -59,10 +59,25 @@ Requires-Dist: pytest-xdist<4.0,>=3.2; extra == 'test'
|
|
59
59
|
Requires-Dist: pytest<8.0,>=7.3; extra == 'test'
|
60
60
|
Description-Content-Type: text/markdown
|
61
61
|
|
62
|
-
##
|
62
|
+
## dbt-common
|
63
63
|
|
64
64
|
The shared common utilities for dbt-core and adapter implementations use
|
65
65
|
|
66
|
+
### Releasing dbt-common
|
67
|
+
To release a new version of dbt-common to pypi, you'll need to:
|
68
|
+
1. Bump the `version` in [dbt_common_/__about__.py](https://github.com/dbt-labs/dbt-common/blob/main/dbt_common/__about__.py)
|
69
|
+
2. Run the [release workflow](https://github.com/dbt-labs/dbt-common/actions/workflows/release.yml) to test pypi and confirm a successful test release in: https://test.pypi.org/project/dbt-common/
|
70
|
+
3. Run the [release workflow](https://github.com/dbt-labs/dbt-common/actions/workflows/release.yml) to prod pypi and confirm a successful release in: https://pypi.org/project/dbt-common/
|
71
|
+
4. Bump the version of `dbt-common` in `dbt-core` and `dbt-adapters` if you're releasing a new major version or a pre-release:
|
72
|
+
* `dbt-core`: [setup.py](https://github.com/dbt-labs/dbt-core/blob/main/core/setup.py)
|
73
|
+
* `dbt-adapters`: [pyproject.toml](https://github.com/dbt-labs/dbt-adapters/blob/main/pyproject.toml)
|
74
|
+
* Adapter Implementations:
|
75
|
+
* `dbt-postgres`: [pyproject.toml](https://github.com/dbt-labs/dbt-postgres/blob/main/pyproject.toml)
|
76
|
+
* `dbt-snowflake`: [setup.py](https://github.com/dbt-labs/dbt-snowflake/blob/main/setup.py)
|
77
|
+
* `dbt-bigquery`: [setup.py](https://github.com/dbt-labs/dbt-bigquery/blob/main/setup.py)
|
78
|
+
* `dbt-redshift`: [setup.py](https://github.com/dbt-labs/dbt-redshift/blob/main/setup.py)
|
79
|
+
* `dbt-spark`: [setup.py](https://github.com/dbt-labs/dbt-spark/blob/main/setup.py)
|
80
|
+
|
66
81
|
## Getting started
|
67
82
|
|
68
83
|
- [Install dbt](https://docs.getdbt.com/docs/get-started/installation)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
## dbt-common
|
2
|
+
|
3
|
+
The shared common utilities for dbt-core and adapter implementations use
|
4
|
+
|
5
|
+
### Releasing dbt-common
|
6
|
+
To release a new version of dbt-common to pypi, you'll need to:
|
7
|
+
1. Bump the `version` in [dbt_common_/__about__.py](https://github.com/dbt-labs/dbt-common/blob/main/dbt_common/__about__.py)
|
8
|
+
2. Run the [release workflow](https://github.com/dbt-labs/dbt-common/actions/workflows/release.yml) to test pypi and confirm a successful test release in: https://test.pypi.org/project/dbt-common/
|
9
|
+
3. Run the [release workflow](https://github.com/dbt-labs/dbt-common/actions/workflows/release.yml) to prod pypi and confirm a successful release in: https://pypi.org/project/dbt-common/
|
10
|
+
4. Bump the version of `dbt-common` in `dbt-core` and `dbt-adapters` if you're releasing a new major version or a pre-release:
|
11
|
+
* `dbt-core`: [setup.py](https://github.com/dbt-labs/dbt-core/blob/main/core/setup.py)
|
12
|
+
* `dbt-adapters`: [pyproject.toml](https://github.com/dbt-labs/dbt-adapters/blob/main/pyproject.toml)
|
13
|
+
* Adapter Implementations:
|
14
|
+
* `dbt-postgres`: [pyproject.toml](https://github.com/dbt-labs/dbt-postgres/blob/main/pyproject.toml)
|
15
|
+
* `dbt-snowflake`: [setup.py](https://github.com/dbt-labs/dbt-snowflake/blob/main/setup.py)
|
16
|
+
* `dbt-bigquery`: [setup.py](https://github.com/dbt-labs/dbt-bigquery/blob/main/setup.py)
|
17
|
+
* `dbt-redshift`: [setup.py](https://github.com/dbt-labs/dbt-redshift/blob/main/setup.py)
|
18
|
+
* `dbt-spark`: [setup.py](https://github.com/dbt-labs/dbt-spark/blob/main/setup.py)
|
19
|
+
|
20
|
+
## Getting started
|
21
|
+
|
22
|
+
- [Install dbt](https://docs.getdbt.com/docs/get-started/installation)
|
23
|
+
- Read the [introduction](https://docs.getdbt.com/docs/introduction/) and [viewpoint](https://docs.getdbt.com/docs/about/viewpoint/)
|
24
|
+
|
25
|
+
## Join the dbt Community
|
26
|
+
|
27
|
+
- Be part of the conversation in the [dbt Community Slack](http://community.getdbt.com/)
|
28
|
+
- Read more on the [dbt Community Discourse](https://discourse.getdbt.com)
|
29
|
+
|
30
|
+
## Reporting bugs and contributing code
|
31
|
+
|
32
|
+
- Want to report a bug or request a feature? Let us know and open [an issue](https://github.com/dbt-labs/dbt-common/issues/new/choose)
|
33
|
+
- Want to help us build dbt? Check out the [Contributing Guide](https://github.com/dbt-labs/dbt-common/blob/HEAD/CONTRIBUTING.md)
|
34
|
+
|
35
|
+
## Code of Conduct
|
36
|
+
|
37
|
+
Everyone interacting in the dbt project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [dbt Code of Conduct](https://community.getdbt.com/code-of-conduct).
|
@@ -0,0 +1 @@
|
|
1
|
+
version = "1.0.1"
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import dbt_common.exceptions.base
|
2
|
+
import dataclasses
|
2
3
|
import errno
|
3
4
|
import fnmatch
|
4
5
|
import functools
|
@@ -25,7 +26,9 @@ from dbt_common.events.types import (
|
|
25
26
|
SystemReportReturnCode,
|
26
27
|
)
|
27
28
|
from dbt_common.exceptions import DbtInternalError
|
29
|
+
from dbt_common.record import record_function, Recorder, Record
|
28
30
|
from dbt_common.utils.connection import connection_exception_retry
|
31
|
+
|
29
32
|
from pathspec import PathSpec # type: ignore
|
30
33
|
|
31
34
|
if sys.platform == "win32":
|
@@ -35,6 +38,49 @@ else:
|
|
35
38
|
c_bool = None
|
36
39
|
|
37
40
|
|
41
|
+
@dataclasses.dataclass
|
42
|
+
class FindMatchingParams:
|
43
|
+
root_path: str
|
44
|
+
relative_paths_to_search: List[str]
|
45
|
+
file_pattern: str
|
46
|
+
# ignore_spec: Optional[PathSpec] = None
|
47
|
+
|
48
|
+
def __init__(
|
49
|
+
self,
|
50
|
+
root_path: str,
|
51
|
+
relative_paths_to_search: List[str],
|
52
|
+
file_pattern: str,
|
53
|
+
ignore_spec: Optional[Any] = None,
|
54
|
+
):
|
55
|
+
self.root_path = root_path
|
56
|
+
rps = list(relative_paths_to_search)
|
57
|
+
rps.sort()
|
58
|
+
self.relative_paths_to_search = rps
|
59
|
+
self.file_pattern = file_pattern
|
60
|
+
|
61
|
+
def _include(self) -> bool:
|
62
|
+
# Do not record or replay filesystem searches that were performed against
|
63
|
+
# files which are actually part of dbt's implementation.
|
64
|
+
return (
|
65
|
+
"dbt/include/global_project" not in self.root_path
|
66
|
+
and "/plugins/postgres/dbt/include/" not in self.root_path
|
67
|
+
)
|
68
|
+
|
69
|
+
|
70
|
+
@dataclasses.dataclass
|
71
|
+
class FindMatchingResult:
|
72
|
+
matches: List[Dict[str, Any]]
|
73
|
+
|
74
|
+
|
75
|
+
@Recorder.register_record_type
|
76
|
+
class FindMatchingRecord(Record):
|
77
|
+
"""Record of calls to the directory search function find_matching()"""
|
78
|
+
|
79
|
+
params_cls = FindMatchingParams
|
80
|
+
result_cls = FindMatchingResult
|
81
|
+
|
82
|
+
|
83
|
+
@record_function(FindMatchingRecord)
|
38
84
|
def find_matching(
|
39
85
|
root_path: str,
|
40
86
|
relative_paths_to_search: List[str],
|
@@ -94,6 +140,34 @@ def find_matching(
|
|
94
140
|
return matching
|
95
141
|
|
96
142
|
|
143
|
+
@dataclasses.dataclass
|
144
|
+
class LoadFileParams:
|
145
|
+
path: str
|
146
|
+
strip: bool = True
|
147
|
+
|
148
|
+
def _include(self) -> bool:
|
149
|
+
# Do not record or replay file reads that were performed against files
|
150
|
+
# which are actually part of dbt's implementation.
|
151
|
+
return (
|
152
|
+
"dbt/include/global_project" not in self.path
|
153
|
+
and "/plugins/postgres/dbt/include/" not in self.path
|
154
|
+
)
|
155
|
+
|
156
|
+
|
157
|
+
@dataclasses.dataclass
|
158
|
+
class LoadFileResult:
|
159
|
+
contents: str
|
160
|
+
|
161
|
+
|
162
|
+
@Recorder.register_record_type
|
163
|
+
class LoadFileRecord(Record):
|
164
|
+
"""Record of file load operation"""
|
165
|
+
|
166
|
+
params_cls = LoadFileParams
|
167
|
+
result_cls = LoadFileResult
|
168
|
+
|
169
|
+
|
170
|
+
@record_function(LoadFileRecord)
|
97
171
|
def load_file_contents(path: str, strip: bool = True) -> str:
|
98
172
|
path = convert_path(path)
|
99
173
|
with open(path, "rb") as handle:
|
@@ -164,6 +238,29 @@ def supports_symlinks() -> bool:
|
|
164
238
|
return getattr(os, "symlink", None) is not None
|
165
239
|
|
166
240
|
|
241
|
+
@dataclasses.dataclass
|
242
|
+
class WriteFileParams:
|
243
|
+
path: str
|
244
|
+
contents: str
|
245
|
+
|
246
|
+
def _include(self) -> bool:
|
247
|
+
# Do not record or replay file reads that were performed against files
|
248
|
+
# which are actually part of dbt's implementation.
|
249
|
+
return (
|
250
|
+
"dbt/include/global_project" not in self.path
|
251
|
+
and "/plugins/postgres/dbt/include/" not in self.path
|
252
|
+
)
|
253
|
+
|
254
|
+
|
255
|
+
@Recorder.register_record_type
|
256
|
+
class WriteFileRecord(Record):
|
257
|
+
"""Record of a file write operation."""
|
258
|
+
|
259
|
+
params_cls = WriteFileParams
|
260
|
+
result_cls = None
|
261
|
+
|
262
|
+
|
263
|
+
@record_function(WriteFileRecord)
|
167
264
|
def write_file(path: str, contents: str = "") -> bool:
|
168
265
|
path = convert_path(path)
|
169
266
|
try:
|
@@ -195,11 +292,28 @@ def write_file(path: str, contents: str = "") -> bool:
|
|
195
292
|
|
196
293
|
|
197
294
|
def read_json(path: str) -> Dict[str, Any]:
|
198
|
-
|
295
|
+
path = convert_path(path)
|
296
|
+
with open(path, "r") as f:
|
297
|
+
return json.load(f)
|
199
298
|
|
200
299
|
|
201
300
|
def write_json(path: str, data: Dict[str, Any]) -> bool:
|
202
|
-
|
301
|
+
path = convert_path(path)
|
302
|
+
try:
|
303
|
+
make_directory(os.path.dirname(path))
|
304
|
+
with open(path, "w", encoding="utf-8") as f:
|
305
|
+
json.dump(data, f, cls=dbt_common.utils.encoding.JSONEncoder)
|
306
|
+
except Exception as exc:
|
307
|
+
# See write_file() for an explanation of this error handling.
|
308
|
+
if os.name == "nt":
|
309
|
+
if getattr(exc, "winerror", 0) == 3:
|
310
|
+
reason = "Path was too long"
|
311
|
+
else:
|
312
|
+
reason = "Path was possibly too long"
|
313
|
+
fire_event(SystemCouldNotWrite(path=path, reason=reason, exc=str(exc)))
|
314
|
+
else:
|
315
|
+
raise
|
316
|
+
return True
|
203
317
|
|
204
318
|
|
205
319
|
def _windows_rmdir_readonly(func: Callable[[str], Any], path: str, exc: Tuple[Any, OSError, Any]):
|
@@ -573,3 +687,24 @@ def rmtree(path):
|
|
573
687
|
"""
|
574
688
|
path = convert_path(path)
|
575
689
|
return shutil.rmtree(path, onerror=chmod_and_retry)
|
690
|
+
|
691
|
+
|
692
|
+
@dataclasses.dataclass
|
693
|
+
class GetEnvParams:
|
694
|
+
pass
|
695
|
+
|
696
|
+
|
697
|
+
@dataclasses.dataclass
|
698
|
+
class GetEnvResult:
|
699
|
+
env: Dict[str, str]
|
700
|
+
|
701
|
+
|
702
|
+
@Recorder.register_record_type
|
703
|
+
class GetEnvRecord(Record):
|
704
|
+
params_cls = GetEnvParams
|
705
|
+
result_cls = GetEnvResult
|
706
|
+
|
707
|
+
|
708
|
+
@record_function(GetEnvRecord)
|
709
|
+
def get_env() -> Dict[str, str]:
|
710
|
+
return dict(os.environ)
|
@@ -0,0 +1,6 @@
|
|
1
|
+
# Prefix which identifies environment variables which contains secrets.
|
2
|
+
SECRET_ENV_PREFIX = "DBT_ENV_SECRET_"
|
3
|
+
|
4
|
+
# Prefix which identifies environment variables that should not be visible
|
5
|
+
# via macros, flags, or other user-facing mechanisms.
|
6
|
+
PRIVATE_ENV_PREFIX = "DBT_ENV_PRIVATE_"
|
@@ -1,19 +1,25 @@
|
|
1
1
|
from contextvars import ContextVar, copy_context
|
2
2
|
from typing import List, Mapping, Optional
|
3
3
|
|
4
|
-
from dbt_common.constants import SECRET_ENV_PREFIX
|
4
|
+
from dbt_common.constants import PRIVATE_ENV_PREFIX, SECRET_ENV_PREFIX
|
5
5
|
|
6
6
|
|
7
7
|
class InvocationContext:
|
8
8
|
def __init__(self, env: Mapping[str, str]):
|
9
|
-
self._env = env
|
9
|
+
self._env = {k: v for k, v in env.items() if not k.startswith(PRIVATE_ENV_PREFIX)}
|
10
10
|
self._env_secrets: Optional[List[str]] = None
|
11
|
+
self._env_private = {k: v for k, v in env.items() if k.startswith(PRIVATE_ENV_PREFIX)}
|
12
|
+
self.recorder = None
|
11
13
|
# This class will also eventually manage the invocation_id, flags, event manager, etc.
|
12
14
|
|
13
15
|
@property
|
14
16
|
def env(self) -> Mapping[str, str]:
|
15
17
|
return self._env
|
16
18
|
|
19
|
+
@property
|
20
|
+
def env_private(self) -> Mapping[str, str]:
|
21
|
+
return self._env_private
|
22
|
+
|
17
23
|
@property
|
18
24
|
def env_secrets(self) -> List[str]:
|
19
25
|
if self._env_secrets is None:
|
@@ -0,0 +1,208 @@
|
|
1
|
+
"""The record module provides a mechanism for recording dbt's interaction with
|
2
|
+
external systems during a command invocation, so that the command can be re-run
|
3
|
+
later with the recording 'replayed' to dbt.
|
4
|
+
|
5
|
+
If dbt behaves sufficiently deterministically, we will be able to use the
|
6
|
+
record/replay mechanism in several interesting test and debugging scenarios.
|
7
|
+
"""
|
8
|
+
import functools
|
9
|
+
import dataclasses
|
10
|
+
import json
|
11
|
+
import os
|
12
|
+
from enum import Enum
|
13
|
+
from typing import Any, Dict, List, Mapping, Optional, Type
|
14
|
+
|
15
|
+
from dbt_common.context import get_invocation_context
|
16
|
+
|
17
|
+
|
18
|
+
class Record:
|
19
|
+
"""An instance of this abstract Record class represents a request made by dbt
|
20
|
+
to an external process or the operating system. The 'params' are the arguments
|
21
|
+
to the request, and the 'result' is what is returned."""
|
22
|
+
|
23
|
+
params_cls: type
|
24
|
+
result_cls: Optional[type]
|
25
|
+
|
26
|
+
def __init__(self, params, result) -> None:
|
27
|
+
self.params = params
|
28
|
+
self.result = result
|
29
|
+
|
30
|
+
def to_dict(self) -> Dict[str, Any]:
|
31
|
+
return {
|
32
|
+
"params": self.params._to_dict() if hasattr(self.params, "_to_dict") else dataclasses.asdict(self.params), # type: ignore
|
33
|
+
"result": self.result._to_dict() if hasattr(self.result, "_to_dict") else dataclasses.asdict(self.result) if self.result is not None else None, # type: ignore
|
34
|
+
}
|
35
|
+
|
36
|
+
@classmethod
|
37
|
+
def from_dict(cls, dct: Mapping) -> "Record":
|
38
|
+
p = (
|
39
|
+
cls.params_cls._from_dict(dct["params"])
|
40
|
+
if hasattr(cls.params_cls, "_from_dict")
|
41
|
+
else cls.params_cls(**dct["params"])
|
42
|
+
)
|
43
|
+
r = (
|
44
|
+
cls.result_cls._from_dict(dct["result"]) # type: ignore
|
45
|
+
if hasattr(cls.result_cls, "_from_dict")
|
46
|
+
else cls.result_cls(**dct["result"])
|
47
|
+
if cls.result_cls is not None
|
48
|
+
else None
|
49
|
+
)
|
50
|
+
return cls(params=p, result=r)
|
51
|
+
|
52
|
+
|
53
|
+
class Diff:
|
54
|
+
"""Marker class for diffs?"""
|
55
|
+
|
56
|
+
pass
|
57
|
+
|
58
|
+
|
59
|
+
class RecorderMode(Enum):
|
60
|
+
RECORD = 1
|
61
|
+
REPLAY = 2
|
62
|
+
|
63
|
+
|
64
|
+
class Recorder:
|
65
|
+
_record_cls_by_name: Dict[str, Type] = {}
|
66
|
+
_record_name_by_params_name: Dict[str, str] = {}
|
67
|
+
|
68
|
+
def __init__(self, mode: RecorderMode, recording_path: Optional[str] = None) -> None:
|
69
|
+
self.mode = mode
|
70
|
+
self._records_by_type: Dict[str, List[Record]] = {}
|
71
|
+
self._replay_diffs: List["Diff"] = []
|
72
|
+
|
73
|
+
if recording_path is not None:
|
74
|
+
self._records_by_type = self.load(recording_path)
|
75
|
+
|
76
|
+
@classmethod
|
77
|
+
def register_record_type(cls, rec_type) -> Any:
|
78
|
+
cls._record_cls_by_name[rec_type.__name__] = rec_type
|
79
|
+
cls._record_name_by_params_name[rec_type.params_cls.__name__] = rec_type.__name__
|
80
|
+
return rec_type
|
81
|
+
|
82
|
+
def add_record(self, record: Record) -> None:
|
83
|
+
rec_cls_name = record.__class__.__name__ # type: ignore
|
84
|
+
if rec_cls_name not in self._records_by_type:
|
85
|
+
self._records_by_type[rec_cls_name] = []
|
86
|
+
self._records_by_type[rec_cls_name].append(record)
|
87
|
+
|
88
|
+
def pop_matching_record(self, params: Any) -> Optional[Record]:
|
89
|
+
rec_type_name = self._record_name_by_params_name[type(params).__name__]
|
90
|
+
records = self._records_by_type[rec_type_name]
|
91
|
+
match: Optional[Record] = None
|
92
|
+
for rec in records:
|
93
|
+
if rec.params == params:
|
94
|
+
match = rec
|
95
|
+
records.remove(match)
|
96
|
+
break
|
97
|
+
|
98
|
+
return match
|
99
|
+
|
100
|
+
def write(self, file_name) -> None:
|
101
|
+
with open(file_name, "w") as file:
|
102
|
+
json.dump(self._to_dict(), file)
|
103
|
+
|
104
|
+
def _to_dict(self) -> Dict:
|
105
|
+
dct: Dict[str, Any] = {}
|
106
|
+
|
107
|
+
for record_type in self._records_by_type:
|
108
|
+
record_list = [r.to_dict() for r in self._records_by_type[record_type]]
|
109
|
+
dct[record_type] = record_list
|
110
|
+
|
111
|
+
return dct
|
112
|
+
|
113
|
+
@classmethod
|
114
|
+
def load(cls, file_name: str) -> Dict[str, List[Record]]:
|
115
|
+
with open(file_name) as file:
|
116
|
+
loaded_dct = json.load(file)
|
117
|
+
|
118
|
+
records_by_type: Dict[str, List[Record]] = {}
|
119
|
+
|
120
|
+
for record_type_name in loaded_dct:
|
121
|
+
record_cls = cls._record_cls_by_name[record_type_name]
|
122
|
+
rec_list = []
|
123
|
+
for record_dct in loaded_dct[record_type_name]:
|
124
|
+
rec = record_cls.from_dict(record_dct)
|
125
|
+
rec_list.append(rec) # type: ignore
|
126
|
+
records_by_type[record_type_name] = rec_list
|
127
|
+
|
128
|
+
return records_by_type
|
129
|
+
|
130
|
+
def expect_record(self, params: Any) -> Any:
|
131
|
+
record = self.pop_matching_record(params)
|
132
|
+
|
133
|
+
if record is None:
|
134
|
+
raise Exception()
|
135
|
+
|
136
|
+
result_tuple = dataclasses.astuple(record.result)
|
137
|
+
return result_tuple[0] if len(result_tuple) == 1 else result_tuple
|
138
|
+
|
139
|
+
def write_diffs(self, diff_file_name) -> None:
|
140
|
+
json.dump(
|
141
|
+
self._replay_diffs,
|
142
|
+
open(diff_file_name, "w"),
|
143
|
+
)
|
144
|
+
|
145
|
+
def print_diffs(self) -> None:
|
146
|
+
print(repr(self._replay_diffs))
|
147
|
+
|
148
|
+
|
149
|
+
def get_record_mode_from_env() -> Optional[RecorderMode]:
|
150
|
+
replay_val = os.environ.get("DBT_REPLAY")
|
151
|
+
if replay_val is not None and replay_val != "0" and replay_val.lower() != "false":
|
152
|
+
return RecorderMode.REPLAY
|
153
|
+
|
154
|
+
record_val = os.environ.get("DBT_RECORD")
|
155
|
+
if record_val is not None and record_val != "0" and record_val.lower() != "false":
|
156
|
+
return RecorderMode.RECORD
|
157
|
+
|
158
|
+
return None
|
159
|
+
|
160
|
+
|
161
|
+
def record_function(record_type, method=False, tuple_result=False):
|
162
|
+
def record_function_inner(func_to_record):
|
163
|
+
# To avoid runtime overhead and other unpleasantness, we only apply the
|
164
|
+
# record/replay decorator if a relevant env var is set.
|
165
|
+
if get_record_mode_from_env() is None:
|
166
|
+
return func_to_record
|
167
|
+
|
168
|
+
@functools.wraps(func_to_record)
|
169
|
+
def record_replay_wrapper(*args, **kwargs):
|
170
|
+
recorder: Recorder = None
|
171
|
+
try:
|
172
|
+
recorder = get_invocation_context().recorder
|
173
|
+
except LookupError:
|
174
|
+
pass
|
175
|
+
|
176
|
+
if recorder is None:
|
177
|
+
return func_to_record(*args, **kwargs)
|
178
|
+
|
179
|
+
# For methods, peel off the 'self' argument before calling the
|
180
|
+
# params constructor.
|
181
|
+
param_args = args[1:] if method else args
|
182
|
+
|
183
|
+
params = record_type.params_cls(*param_args, **kwargs)
|
184
|
+
|
185
|
+
include = True
|
186
|
+
if hasattr(params, "_include"):
|
187
|
+
include = params._include()
|
188
|
+
|
189
|
+
if not include:
|
190
|
+
return func_to_record(*args, **kwargs)
|
191
|
+
|
192
|
+
if recorder.mode == RecorderMode.REPLAY:
|
193
|
+
return recorder.expect_record(params)
|
194
|
+
|
195
|
+
r = func_to_record(*args, **kwargs)
|
196
|
+
result = (
|
197
|
+
None
|
198
|
+
if r is None or record_type.result_cls is None
|
199
|
+
else record_type.result_cls(*r)
|
200
|
+
if tuple_result
|
201
|
+
else record_type.result_cls(r)
|
202
|
+
)
|
203
|
+
recorder.add_record(record_type(params=params, result=result))
|
204
|
+
return r
|
205
|
+
|
206
|
+
return record_replay_wrapper
|
207
|
+
|
208
|
+
return record_function_inner
|
@@ -74,6 +74,6 @@ def executor(config: HasThreadingConfig) -> ConnectingExecutor:
|
|
74
74
|
else:
|
75
75
|
return MultiThreadedExecutor(
|
76
76
|
max_workers=config.threads,
|
77
|
-
initializer=_thread_initializer,
|
78
|
-
initargs=(get_invocation_context(),),
|
77
|
+
initializer=_thread_initializer, # type: ignore
|
78
|
+
initargs=(get_invocation_context(),), # type: ignore
|
79
79
|
)
|
dbt_common-1.0.0b1/README.md
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
## Understanding dbt-common
|
2
|
-
|
3
|
-
The shared common utilities for dbt-core and adapter implementations use
|
4
|
-
|
5
|
-
## Getting started
|
6
|
-
|
7
|
-
- [Install dbt](https://docs.getdbt.com/docs/get-started/installation)
|
8
|
-
- Read the [introduction](https://docs.getdbt.com/docs/introduction/) and [viewpoint](https://docs.getdbt.com/docs/about/viewpoint/)
|
9
|
-
|
10
|
-
## Join the dbt Community
|
11
|
-
|
12
|
-
- Be part of the conversation in the [dbt Community Slack](http://community.getdbt.com/)
|
13
|
-
- Read more on the [dbt Community Discourse](https://discourse.getdbt.com)
|
14
|
-
|
15
|
-
## Reporting bugs and contributing code
|
16
|
-
|
17
|
-
- Want to report a bug or request a feature? Let us know and open [an issue](https://github.com/dbt-labs/dbt-common/issues/new/choose)
|
18
|
-
- Want to help us build dbt? Check out the [Contributing Guide](https://github.com/dbt-labs/dbt-common/blob/HEAD/CONTRIBUTING.md)
|
19
|
-
|
20
|
-
## Code of Conduct
|
21
|
-
|
22
|
-
Everyone interacting in the dbt project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [dbt Code of Conduct](https://community.getdbt.com/code-of-conduct).
|
@@ -1 +0,0 @@
|
|
1
|
-
version = "1.0.0b1"
|
@@ -1 +0,0 @@
|
|
1
|
-
SECRET_ENV_PREFIX = "DBT_ENV_SECRET_"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/code/__init__.pyi
RENAMED
File without changes
|
{dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/code/builder.pyi
RENAMED
File without changes
|
{dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/code/lines.pyi
RENAMED
File without changes
|
File without changes
|
File without changes
|
{dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/types/__init__.pyi
RENAMED
File without changes
|
{dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/types/common.pyi
RENAMED
File without changes
|
{dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/types/pack.pyi
RENAMED
File without changes
|
{dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/core/meta/types/unpack.pyi
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dbt_common-1.0.0b1 → dbt_common-1.0.1}/third-party-stubs/mashumaro/jsonschema/annotations.pyi
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|