dbt-adapters 0.1.0a1__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 dbt-adapters might be problematic. Click here for more details.

Files changed (147) hide show
  1. dbt/__init__.py +0 -0
  2. dbt/adapters/__about__.py +1 -0
  3. dbt/adapters/__init__.py +7 -0
  4. dbt/adapters/base/README.md +13 -0
  5. dbt/adapters/base/__init__.py +15 -0
  6. dbt/adapters/base/column.py +166 -0
  7. dbt/adapters/base/connections.py +426 -0
  8. dbt/adapters/base/impl.py +1654 -0
  9. dbt/adapters/base/meta.py +131 -0
  10. dbt/adapters/base/plugin.py +32 -0
  11. dbt/adapters/base/query_headers.py +101 -0
  12. dbt/adapters/base/relation.py +471 -0
  13. dbt/adapters/cache.py +521 -0
  14. dbt/adapters/capability.py +52 -0
  15. dbt/adapters/clients/__init__.py +0 -0
  16. dbt/adapters/clients/jinja.py +24 -0
  17. dbt/adapters/contracts/__init__.py +0 -0
  18. dbt/adapters/contracts/connection.py +228 -0
  19. dbt/adapters/contracts/macros.py +11 -0
  20. dbt/adapters/contracts/relation.py +125 -0
  21. dbt/adapters/events/README.md +57 -0
  22. dbt/adapters/events/__init__.py +0 -0
  23. dbt/adapters/events/adapter_types.proto +517 -0
  24. dbt/adapters/events/adapter_types_pb2.py +208 -0
  25. dbt/adapters/events/base_types.py +40 -0
  26. dbt/adapters/events/logging.py +83 -0
  27. dbt/adapters/events/types.py +423 -0
  28. dbt/adapters/exceptions/__init__.py +40 -0
  29. dbt/adapters/exceptions/alias.py +24 -0
  30. dbt/adapters/exceptions/cache.py +68 -0
  31. dbt/adapters/exceptions/compilation.py +255 -0
  32. dbt/adapters/exceptions/connection.py +16 -0
  33. dbt/adapters/exceptions/database.py +51 -0
  34. dbt/adapters/factory.py +246 -0
  35. dbt/adapters/protocol.py +173 -0
  36. dbt/adapters/reference_keys.py +39 -0
  37. dbt/adapters/relation_configs/README.md +25 -0
  38. dbt/adapters/relation_configs/__init__.py +12 -0
  39. dbt/adapters/relation_configs/config_base.py +44 -0
  40. dbt/adapters/relation_configs/config_change.py +24 -0
  41. dbt/adapters/relation_configs/config_validation.py +57 -0
  42. dbt/adapters/sql/__init__.py +2 -0
  43. dbt/adapters/sql/connections.py +195 -0
  44. dbt/adapters/sql/impl.py +273 -0
  45. dbt/adapters/utils.py +69 -0
  46. dbt/include/global_project/__init__.py +4 -0
  47. dbt/include/global_project/dbt_project.yml +7 -0
  48. dbt/include/global_project/docs/overview.md +43 -0
  49. dbt/include/global_project/macros/adapters/apply_grants.sql +167 -0
  50. dbt/include/global_project/macros/adapters/columns.sql +137 -0
  51. dbt/include/global_project/macros/adapters/freshness.sql +16 -0
  52. dbt/include/global_project/macros/adapters/indexes.sql +41 -0
  53. dbt/include/global_project/macros/adapters/metadata.sql +96 -0
  54. dbt/include/global_project/macros/adapters/persist_docs.sql +33 -0
  55. dbt/include/global_project/macros/adapters/relation.sql +79 -0
  56. dbt/include/global_project/macros/adapters/schema.sql +20 -0
  57. dbt/include/global_project/macros/adapters/show.sql +22 -0
  58. dbt/include/global_project/macros/adapters/timestamps.sql +44 -0
  59. dbt/include/global_project/macros/adapters/validate_sql.sql +10 -0
  60. dbt/include/global_project/macros/etc/datetime.sql +62 -0
  61. dbt/include/global_project/macros/etc/statement.sql +52 -0
  62. dbt/include/global_project/macros/generic_test_sql/accepted_values.sql +27 -0
  63. dbt/include/global_project/macros/generic_test_sql/not_null.sql +9 -0
  64. dbt/include/global_project/macros/generic_test_sql/relationships.sql +23 -0
  65. dbt/include/global_project/macros/generic_test_sql/unique.sql +12 -0
  66. dbt/include/global_project/macros/get_custom_name/get_custom_alias.sql +36 -0
  67. dbt/include/global_project/macros/get_custom_name/get_custom_database.sql +32 -0
  68. dbt/include/global_project/macros/get_custom_name/get_custom_schema.sql +60 -0
  69. dbt/include/global_project/macros/materializations/configs.sql +21 -0
  70. dbt/include/global_project/macros/materializations/hooks.sql +35 -0
  71. dbt/include/global_project/macros/materializations/models/clone/can_clone_table.sql +7 -0
  72. dbt/include/global_project/macros/materializations/models/clone/clone.sql +67 -0
  73. dbt/include/global_project/macros/materializations/models/clone/create_or_replace_clone.sql +7 -0
  74. dbt/include/global_project/macros/materializations/models/incremental/column_helpers.sql +80 -0
  75. dbt/include/global_project/macros/materializations/models/incremental/incremental.sql +92 -0
  76. dbt/include/global_project/macros/materializations/models/incremental/is_incremental.sql +13 -0
  77. dbt/include/global_project/macros/materializations/models/incremental/merge.sql +131 -0
  78. dbt/include/global_project/macros/materializations/models/incremental/on_schema_change.sql +144 -0
  79. dbt/include/global_project/macros/materializations/models/incremental/strategies.sql +79 -0
  80. dbt/include/global_project/macros/materializations/models/materialized_view.sql +121 -0
  81. dbt/include/global_project/macros/materializations/models/table.sql +64 -0
  82. dbt/include/global_project/macros/materializations/models/view.sql +72 -0
  83. dbt/include/global_project/macros/materializations/seeds/helpers.sql +128 -0
  84. dbt/include/global_project/macros/materializations/seeds/seed.sql +60 -0
  85. dbt/include/global_project/macros/materializations/snapshots/helpers.sql +181 -0
  86. dbt/include/global_project/macros/materializations/snapshots/snapshot.sql +99 -0
  87. dbt/include/global_project/macros/materializations/snapshots/snapshot_merge.sql +25 -0
  88. dbt/include/global_project/macros/materializations/snapshots/strategies.sql +174 -0
  89. dbt/include/global_project/macros/materializations/tests/helpers.sql +14 -0
  90. dbt/include/global_project/macros/materializations/tests/test.sql +60 -0
  91. dbt/include/global_project/macros/materializations/tests/where_subquery.sql +15 -0
  92. dbt/include/global_project/macros/python_model/python.sql +103 -0
  93. dbt/include/global_project/macros/relations/column/columns_spec_ddl.sql +89 -0
  94. dbt/include/global_project/macros/relations/create.sql +23 -0
  95. dbt/include/global_project/macros/relations/create_backup.sql +17 -0
  96. dbt/include/global_project/macros/relations/create_intermediate.sql +17 -0
  97. dbt/include/global_project/macros/relations/drop.sql +41 -0
  98. dbt/include/global_project/macros/relations/drop_backup.sql +14 -0
  99. dbt/include/global_project/macros/relations/materialized_view/alter.sql +55 -0
  100. dbt/include/global_project/macros/relations/materialized_view/create.sql +10 -0
  101. dbt/include/global_project/macros/relations/materialized_view/drop.sql +14 -0
  102. dbt/include/global_project/macros/relations/materialized_view/refresh.sql +9 -0
  103. dbt/include/global_project/macros/relations/materialized_view/rename.sql +10 -0
  104. dbt/include/global_project/macros/relations/materialized_view/replace.sql +10 -0
  105. dbt/include/global_project/macros/relations/rename.sql +35 -0
  106. dbt/include/global_project/macros/relations/rename_intermediate.sql +14 -0
  107. dbt/include/global_project/macros/relations/replace.sql +50 -0
  108. dbt/include/global_project/macros/relations/schema.sql +8 -0
  109. dbt/include/global_project/macros/relations/table/create.sql +60 -0
  110. dbt/include/global_project/macros/relations/table/drop.sql +14 -0
  111. dbt/include/global_project/macros/relations/table/rename.sql +10 -0
  112. dbt/include/global_project/macros/relations/table/replace.sql +10 -0
  113. dbt/include/global_project/macros/relations/view/create.sql +27 -0
  114. dbt/include/global_project/macros/relations/view/drop.sql +14 -0
  115. dbt/include/global_project/macros/relations/view/rename.sql +10 -0
  116. dbt/include/global_project/macros/relations/view/replace.sql +66 -0
  117. dbt/include/global_project/macros/utils/any_value.sql +9 -0
  118. dbt/include/global_project/macros/utils/array_append.sql +8 -0
  119. dbt/include/global_project/macros/utils/array_concat.sql +7 -0
  120. dbt/include/global_project/macros/utils/array_construct.sql +12 -0
  121. dbt/include/global_project/macros/utils/bool_or.sql +9 -0
  122. dbt/include/global_project/macros/utils/cast_bool_to_text.sql +7 -0
  123. dbt/include/global_project/macros/utils/concat.sql +7 -0
  124. dbt/include/global_project/macros/utils/data_types.sql +129 -0
  125. dbt/include/global_project/macros/utils/date_spine.sql +75 -0
  126. dbt/include/global_project/macros/utils/date_trunc.sql +7 -0
  127. dbt/include/global_project/macros/utils/dateadd.sql +14 -0
  128. dbt/include/global_project/macros/utils/datediff.sql +14 -0
  129. dbt/include/global_project/macros/utils/escape_single_quotes.sql +8 -0
  130. dbt/include/global_project/macros/utils/except.sql +9 -0
  131. dbt/include/global_project/macros/utils/generate_series.sql +53 -0
  132. dbt/include/global_project/macros/utils/hash.sql +7 -0
  133. dbt/include/global_project/macros/utils/intersect.sql +9 -0
  134. dbt/include/global_project/macros/utils/last_day.sql +15 -0
  135. dbt/include/global_project/macros/utils/length.sql +11 -0
  136. dbt/include/global_project/macros/utils/listagg.sql +30 -0
  137. dbt/include/global_project/macros/utils/literal.sql +7 -0
  138. dbt/include/global_project/macros/utils/position.sql +11 -0
  139. dbt/include/global_project/macros/utils/replace.sql +14 -0
  140. dbt/include/global_project/macros/utils/right.sql +12 -0
  141. dbt/include/global_project/macros/utils/safe_cast.sql +9 -0
  142. dbt/include/global_project/macros/utils/split_part.sql +26 -0
  143. dbt/include/global_project/tests/generic/builtin.sql +30 -0
  144. dbt_adapters-0.1.0a1.dist-info/METADATA +81 -0
  145. dbt_adapters-0.1.0a1.dist-info/RECORD +147 -0
  146. dbt_adapters-0.1.0a1.dist-info/WHEEL +4 -0
  147. dbt_adapters-0.1.0a1.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,228 @@
1
+ import abc
2
+ from dataclasses import dataclass, field
3
+ import itertools
4
+ from typing import (
5
+ Any,
6
+ Callable,
7
+ ClassVar,
8
+ Dict,
9
+ Iterable,
10
+ List,
11
+ Optional,
12
+ Tuple,
13
+ )
14
+
15
+ from dbt_common.contracts.util import Replaceable
16
+ from dbt_common.dataclass_schema import (
17
+ ExtensibleDbtClassMixin,
18
+ StrEnum,
19
+ ValidatedStringMixin,
20
+ dbtClassMixin,
21
+ )
22
+
23
+ # TODO: this is a very bad dependency - shared global state
24
+ from dbt_common.events.contextvars import get_node_info
25
+ from dbt_common.events.functions import fire_event
26
+ from dbt_common.exceptions import DbtInternalError
27
+ from dbt_common.utils import md5
28
+ from mashumaro.jsonschema.annotations import Pattern
29
+ from typing_extensions import Protocol, Annotated
30
+
31
+ from dbt.adapters.events.types import NewConnectionOpening
32
+ from dbt.adapters.utils import translate_aliases
33
+
34
+
35
+ class Identifier(ValidatedStringMixin):
36
+ ValidationRegex = r"^[A-Za-z_][A-Za-z0-9_]+$"
37
+
38
+
39
+ @dataclass
40
+ class AdapterResponse(dbtClassMixin):
41
+ _message: str
42
+ code: Optional[str] = None
43
+ rows_affected: Optional[int] = None
44
+
45
+ def __str__(self):
46
+ return self._message
47
+
48
+
49
+ class ConnectionState(StrEnum):
50
+ INIT = "init"
51
+ OPEN = "open"
52
+ CLOSED = "closed"
53
+ FAIL = "fail"
54
+
55
+
56
+ @dataclass(init=False)
57
+ class Connection(ExtensibleDbtClassMixin, Replaceable):
58
+ # Annotated is used by mashumaro for jsonschema generation
59
+ type: Annotated[Identifier, Pattern(r"^[A-Za-z_][A-Za-z0-9_]+$")]
60
+ name: Optional[str] = None
61
+ state: ConnectionState = ConnectionState.INIT
62
+ transaction_open: bool = False
63
+ _handle: Optional[Any] = None
64
+ _credentials: Optional[Any] = None
65
+
66
+ def __init__(
67
+ self,
68
+ type: Identifier,
69
+ name: Optional[str],
70
+ credentials: dbtClassMixin,
71
+ state: ConnectionState = ConnectionState.INIT,
72
+ transaction_open: bool = False,
73
+ handle: Optional[Any] = None,
74
+ ) -> None:
75
+ self.type = type
76
+ self.name = name
77
+ self.state = state
78
+ self.credentials = credentials
79
+ self.transaction_open = transaction_open
80
+ self.handle = handle
81
+
82
+ @property
83
+ def credentials(self):
84
+ return self._credentials
85
+
86
+ @credentials.setter
87
+ def credentials(self, value):
88
+ self._credentials = value
89
+
90
+ @property
91
+ def handle(self):
92
+ if isinstance(self._handle, LazyHandle):
93
+ try:
94
+ # this will actually change 'self._handle'.
95
+ self._handle.resolve(self)
96
+ except RecursionError as exc:
97
+ raise DbtInternalError(
98
+ "A connection's open() method attempted to read the handle value"
99
+ ) from exc
100
+ return self._handle
101
+
102
+ @handle.setter
103
+ def handle(self, value):
104
+ self._handle = value
105
+
106
+
107
+ class LazyHandle:
108
+ """The opener must be a callable that takes a Connection object and opens the
109
+ connection, updating the handle on the Connection.
110
+ """
111
+
112
+ def __init__(self, opener: Callable[[Connection], Connection]) -> None:
113
+ self.opener = opener
114
+
115
+ def resolve(self, connection: Connection) -> Connection:
116
+ fire_event(
117
+ NewConnectionOpening(connection_state=connection.state, node_info=get_node_info())
118
+ )
119
+ return self.opener(connection)
120
+
121
+
122
+ # see https://github.com/python/mypy/issues/4717#issuecomment-373932080
123
+ # and https://github.com/python/mypy/issues/5374
124
+ # for why we have type: ignore. Maybe someday dataclasses + abstract classes
125
+ # will work.
126
+ @dataclass # type: ignore
127
+ class Credentials(ExtensibleDbtClassMixin, Replaceable, metaclass=abc.ABCMeta):
128
+ database: str
129
+ schema: str
130
+ _ALIASES: ClassVar[Dict[str, str]] = field(default={}, init=False)
131
+
132
+ @abc.abstractproperty
133
+ def type(self) -> str:
134
+ raise NotImplementedError("type not implemented for base credentials class")
135
+
136
+ @property
137
+ def unique_field(self) -> str:
138
+ """Hashed and included in anonymous telemetry to track adapter adoption.
139
+ Return the field from Credentials that can uniquely identify
140
+ one team/organization using this adapter
141
+ """
142
+ raise NotImplementedError("unique_field not implemented for base credentials class")
143
+
144
+ def hashed_unique_field(self) -> str:
145
+ return md5(self.unique_field)
146
+
147
+ def connection_info(self, *, with_aliases: bool = False) -> Iterable[Tuple[str, Any]]:
148
+ """Return an ordered iterator of key/value pairs for pretty-printing."""
149
+ as_dict = self.to_dict(omit_none=False)
150
+ connection_keys = set(self._connection_keys())
151
+ aliases: List[str] = []
152
+ if with_aliases:
153
+ aliases = [k for k, v in self._ALIASES.items() if v in connection_keys]
154
+ for key in itertools.chain(self._connection_keys(), aliases):
155
+ if key in as_dict:
156
+ yield key, as_dict[key]
157
+
158
+ @abc.abstractmethod
159
+ def _connection_keys(self) -> Tuple[str, ...]:
160
+ raise NotImplementedError
161
+
162
+ @classmethod
163
+ def __pre_deserialize__(cls, data):
164
+ data = super().__pre_deserialize__(data)
165
+ # Need to fixup dbname => database, pass => password
166
+ data = cls.translate_aliases(data)
167
+ return data
168
+
169
+ @classmethod
170
+ def translate_aliases(cls, kwargs: Dict[str, Any], recurse: bool = False) -> Dict[str, Any]:
171
+ return translate_aliases(kwargs, cls._ALIASES, recurse)
172
+
173
+ def __post_serialize__(self, dct):
174
+ # no super() -- do we need it?
175
+ if self._ALIASES:
176
+ dct.update(
177
+ {
178
+ new_name: dct[canonical_name]
179
+ for new_name, canonical_name in self._ALIASES.items()
180
+ if canonical_name in dct
181
+ }
182
+ )
183
+ return dct
184
+
185
+
186
+ class HasCredentials(Protocol):
187
+ credentials: Credentials
188
+ profile_name: str
189
+ target_name: str
190
+ threads: int
191
+
192
+ def to_target_dict(self):
193
+ raise NotImplementedError("to_target_dict not implemented")
194
+
195
+
196
+ DEFAULT_QUERY_COMMENT = """
197
+ {%- set comment_dict = {} -%}
198
+ {%- do comment_dict.update(
199
+ app='dbt',
200
+ dbt_version=dbt_version,
201
+ profile_name=target.get('profile_name'),
202
+ target_name=target.get('target_name'),
203
+ ) -%}
204
+ {%- if node is not none -%}
205
+ {%- do comment_dict.update(
206
+ node_id=node.unique_id,
207
+ ) -%}
208
+ {% else %}
209
+ {# in the node context, the connection name is the node_id #}
210
+ {%- do comment_dict.update(connection_name=connection_name) -%}
211
+ {%- endif -%}
212
+ {{ return(tojson(comment_dict)) }}
213
+ """
214
+
215
+
216
+ @dataclass
217
+ class QueryComment(dbtClassMixin):
218
+ comment: str = DEFAULT_QUERY_COMMENT
219
+ append: bool = False
220
+ job_label: bool = field(default=False, metadata={"alias": "job-label"})
221
+
222
+
223
+ class AdapterRequiredConfig(HasCredentials, Protocol):
224
+ project_name: str
225
+ query_comment: QueryComment
226
+ cli_vars: Dict[str, Any]
227
+ target_path: str
228
+ log_cache_events: bool
@@ -0,0 +1,11 @@
1
+ from typing import Optional
2
+
3
+ from dbt_common.clients.jinja import MacroProtocol
4
+ from typing_extensions import Protocol
5
+
6
+
7
+ class MacroResolverProtocol(Protocol):
8
+ def find_macro_by_name(
9
+ self, name: str, root_project_name: str, package: Optional[str]
10
+ ) -> Optional[MacroProtocol]:
11
+ raise NotImplementedError("find_macro_by_name not implemented")
@@ -0,0 +1,125 @@
1
+ from collections.abc import Mapping
2
+ from dataclasses import dataclass
3
+ from typing import Dict, Optional
4
+
5
+ from dbt_common.contracts.util import Replaceable
6
+ from dbt_common.dataclass_schema import StrEnum, dbtClassMixin
7
+ from dbt_common.exceptions import CompilationError, DataclassNotDictError
8
+ from dbt_common.utils import deep_merge
9
+ from typing_extensions import Protocol
10
+
11
+
12
+ class RelationType(StrEnum):
13
+ Table = "table"
14
+ View = "view"
15
+ CTE = "cte"
16
+ MaterializedView = "materialized_view"
17
+ External = "external"
18
+ Ephemeral = "ephemeral"
19
+
20
+
21
+ class RelationConfig(Protocol):
22
+ name: str
23
+ database: str
24
+ schema: str
25
+ identifier: str
26
+ quoting_dict: Dict[str, bool]
27
+ config: Dict[str, str]
28
+
29
+
30
+ class ComponentName(StrEnum):
31
+ Database = "database"
32
+ Schema = "schema"
33
+ Identifier = "identifier"
34
+
35
+
36
+ class HasQuoting(Protocol):
37
+ quoting: Dict[str, bool]
38
+
39
+
40
+ class FakeAPIObject(dbtClassMixin, Replaceable, Mapping):
41
+ # override the mapping truthiness, len is always >1
42
+ def __bool__(self):
43
+ return True
44
+
45
+ def __getitem__(self, key):
46
+ try:
47
+ return getattr(self, key)
48
+ except AttributeError:
49
+ raise KeyError(key) from None
50
+
51
+ def __iter__(self):
52
+ raise DataclassNotDictError(self)
53
+
54
+ def __len__(self):
55
+ raise DataclassNotDictError(self)
56
+
57
+ def incorporate(self, **kwargs):
58
+ value = self.to_dict(omit_none=True)
59
+ value = deep_merge(value, kwargs)
60
+ return self.from_dict(value)
61
+
62
+
63
+ @dataclass
64
+ class Policy(FakeAPIObject):
65
+ database: bool = True
66
+ schema: bool = True
67
+ identifier: bool = True
68
+
69
+ def get_part(self, key: ComponentName) -> bool:
70
+ if key == ComponentName.Database:
71
+ return self.database
72
+ elif key == ComponentName.Schema:
73
+ return self.schema
74
+ elif key == ComponentName.Identifier:
75
+ return self.identifier
76
+ else:
77
+ raise ValueError(
78
+ "Got a key of {}, expected one of {}".format(key, list(ComponentName))
79
+ )
80
+
81
+ def replace_dict(self, dct: Dict[ComponentName, bool]):
82
+ kwargs: Dict[str, bool] = {}
83
+ for k, v in dct.items():
84
+ kwargs[str(k)] = v
85
+ return self.replace(**kwargs)
86
+
87
+
88
+ @dataclass
89
+ class Path(FakeAPIObject):
90
+ database: Optional[str] = None
91
+ schema: Optional[str] = None
92
+ identifier: Optional[str] = None
93
+
94
+ def __post_init__(self):
95
+ # handle pesky jinja2.Undefined sneaking in here and messing up rende
96
+ if not isinstance(self.database, (type(None), str)):
97
+ raise CompilationError("Got an invalid path database: {}".format(self.database))
98
+ if not isinstance(self.schema, (type(None), str)):
99
+ raise CompilationError("Got an invalid path schema: {}".format(self.schema))
100
+ if not isinstance(self.identifier, (type(None), str)):
101
+ raise CompilationError("Got an invalid path identifier: {}".format(self.identifier))
102
+
103
+ def get_lowered_part(self, key: ComponentName) -> Optional[str]:
104
+ part = self.get_part(key)
105
+ if part is not None:
106
+ part = part.lower()
107
+ return part
108
+
109
+ def get_part(self, key: ComponentName) -> Optional[str]:
110
+ if key == ComponentName.Database:
111
+ return self.database
112
+ elif key == ComponentName.Schema:
113
+ return self.schema
114
+ elif key == ComponentName.Identifier:
115
+ return self.identifier
116
+ else:
117
+ raise ValueError(
118
+ "Got a key of {}, expected one of {}".format(key, list(ComponentName))
119
+ )
120
+
121
+ def replace_dict(self, dct: Dict[ComponentName, str]):
122
+ kwargs: Dict[str, str] = {}
123
+ for k, v in dct.items():
124
+ kwargs[str(k)] = v
125
+ return self.replace(**kwargs)
@@ -0,0 +1,57 @@
1
+ # Events Module
2
+ The Events module is responsible for communicating internal dbt structures into a consumable interface. Because the "event" classes are based entirely on protobuf definitions, the interface is really clearly defined, whether or not protobufs are used to consume it. We use Betterproto for compiling the protobuf message definitions into Python classes.
3
+
4
+ # Using the Events Module
5
+ The event module provides types that represent what is happening in dbt in `events.types`. These types are intended to represent an exhaustive list of all things happening within dbt that will need to be logged, streamed, or printed. To fire an event, `common.events.functions::fire_event` is the entry point to the module from everywhere in dbt.
6
+
7
+ # Logging
8
+ When events are processed via `fire_event`, nearly everything is logged. Whether or not the user has enabled the debug flag, all debug messages are still logged to the file. However, some events are particularly time consuming to construct because they return a huge amount of data. Today, the only messages in this category are cache events and are only logged if the `--log-cache-events` flag is on. This is important because these messages should not be created unless they are going to be logged, because they cause a noticable performance degredation. These events use a "fire_event_if" functions.
9
+
10
+ # Adding a New Event
11
+ * Add a new message in types.proto, and a second message with the same name + "Msg". The "Msg" message should have two fields, an "info" field of EventInfo, and a "data" field referring to the message name without "Msg"
12
+ * run the protoc compiler to update adapter_types_pb2.py: make adapter_proto_types
13
+ * Add a wrapping class in core/dbt/adapters/event/types.py with a Level superclass plus code and message methods
14
+
15
+ We have switched from using betterproto to using google protobuf, because of a lack of support for Struct fields in betterproto.
16
+
17
+ The google protobuf interface is janky and very much non-Pythonic. The "generated" classes in types_pb2.py do not resemble regular Python classes. They do not have normal constructors; they can only be constructed empty. They can be "filled" by setting fields individually or using a json_format method like ParseDict. We have wrapped the logging events with a class (in types.py) which allows using a constructor -- keywords only, no positional parameters.
18
+
19
+ ## Required for Every Event
20
+
21
+ - a method `code`, that's unique across events
22
+ - assign a log level by using the Level mixin: `DebugLevel`, `InfoLevel`, `WarnLevel`, or `ErrorLevel`
23
+ - a message()
24
+
25
+ Example
26
+ ```
27
+ class PartialParsingDeletedExposure(DebugLevel):
28
+ def code(self):
29
+ return "I049"
30
+
31
+ def message(self) -> str:
32
+ return f"Partial parsing: deleted exposure {self.unique_id}"
33
+
34
+ ```
35
+
36
+
37
+ # Adapter Maintainers
38
+ To integrate existing log messages from adapters, you likely have a line of code like this in your adapter already:
39
+ ```python
40
+ from dbt.logger import GLOBAL_LOGGER as logger
41
+ ```
42
+
43
+ Simply change it to these two lines with your adapter's database name, and all your existing call sites will now use the new system for v1.0:
44
+
45
+ ```python
46
+
47
+ from dbt.adapters.events.logging import AdapterLogger
48
+
49
+ logger = AdapterLogger("<database name>")
50
+ # e.g. AdapterLogger("Snowflake")
51
+ ```
52
+
53
+ ## Compiling types.proto
54
+
55
+ After adding a new message in `adapter_types.proto`, either:
56
+ - In the repository root directory: `make adapter_proto_types`
57
+ - In the `core/dbt/adapters/events` directory: `protoc -I=. --python_out=. types.proto`
File without changes