dbt-common 1.23.0__py3-none-any.whl → 1.24.0__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.
dbt_common/__about__.py CHANGED
@@ -1 +1 @@
1
- version = "1.23.0"
1
+ version = "1.24.0"
@@ -1,11 +1,11 @@
1
1
  import os
2
2
  import traceback
3
- from typing import Any, List, Optional, Protocol, Tuple
3
+ from typing import Any, List, Optional, Protocol, Tuple, Union
4
4
 
5
5
  from dbt_common.events.base_types import BaseEvent, EventLevel, msg_from_base_event, TCallback
6
6
  from dbt_common.events.logger import LoggerConfig, _Logger, _TextLogger, _JsonLogger, LineFormat
7
7
  from dbt_common.exceptions.events import EventCompilationError
8
- from dbt_common.helper_types import WarnErrorOptions
8
+ from dbt_common.helper_types import WarnErrorOptions, WarnErrorOptionsV2
9
9
 
10
10
 
11
11
  class EventManager:
@@ -13,7 +13,7 @@ class EventManager:
13
13
  self.loggers: List[_Logger] = []
14
14
  self.callbacks: List[TCallback] = []
15
15
  self._warn_error: Optional[bool] = None
16
- self._warn_error_options: Optional[WarnErrorOptions] = None
16
+ self._warn_error_options: Optional[Union[WarnErrorOptions, WarnErrorOptionsV2]] = None
17
17
  self.require_warn_or_error_handling: bool = False
18
18
 
19
19
  @property
@@ -29,15 +29,18 @@ class EventManager:
29
29
  self._warn_error = warn_error
30
30
 
31
31
  @property
32
- def warn_error_options(self) -> WarnErrorOptions:
32
+ def warn_error_options(self) -> Union[WarnErrorOptions, WarnErrorOptionsV2]:
33
33
  if self._warn_error_options is None:
34
34
  from dbt_common.events.functions import WARN_ERROR_OPTIONS
35
35
 
36
- return WARN_ERROR_OPTIONS
36
+ return WARN_ERROR_OPTIONS._warn_error_options_v2
37
+
37
38
  return self._warn_error_options
38
39
 
39
40
  @warn_error_options.setter
40
- def warn_error_options(self, warn_error_options: WarnErrorOptions) -> None:
41
+ def warn_error_options(
42
+ self, warn_error_options: Union[WarnErrorOptions, WarnErrorOptionsV2]
43
+ ) -> None:
41
44
  self._warn_error_options = warn_error_options
42
45
 
43
46
  def fire_event(
@@ -52,7 +55,7 @@ class EventManager:
52
55
  if force_warn_or_error_handling or (
53
56
  self.require_warn_or_error_handling and msg.info.level == "warn"
54
57
  ):
55
- if self.warn_error or self.warn_error_options.includes(e):
58
+ if self.warn_error or self.warn_error_options.errors(e):
56
59
  # This has the potential to create an infinite loop if the handling of the raised
57
60
  # EventCompilationError fires an event as a warning instead of an error.
58
61
  raise EventCompilationError(e.message(), node)
@@ -95,7 +98,7 @@ class IEventManager(Protocol):
95
98
  callbacks: List[TCallback]
96
99
  loggers: List[_Logger]
97
100
  warn_error: bool
98
- warn_error_options: WarnErrorOptions
101
+ warn_error_options: Union[WarnErrorOptions, WarnErrorOptionsV2]
99
102
  require_warn_or_error_handling: bool
100
103
 
101
104
  def fire_event(
@@ -65,109 +65,162 @@ class IncludeExclude(dbtClassMixin):
65
65
 
66
66
 
67
67
  class WarnErrorOptions(IncludeExclude):
68
+ """Deprecated, use WarnErrorOptionsV2 instead."""
69
+
70
+ DEPRECATIONS = "Deprecations"
71
+
72
+ def __init__(
73
+ self,
74
+ include: Union[str, List[str]],
75
+ exclude: Optional[List[str]] = None,
76
+ valid_error_names: Optional[Set[str]] = None,
77
+ silence: Optional[List[str]] = None,
78
+ ):
79
+ self.silence = silence or []
80
+ self._valid_error_names: Set[str] = valid_error_names or set()
81
+ self._valid_error_names.add(self.DEPRECATIONS)
82
+ super().__init__(include=include, exclude=(exclude or []))
83
+
84
+ self._warn_error_options_v2 = WarnErrorOptionsV2(
85
+ error=self.include,
86
+ warn=self.exclude,
87
+ silence=self.silence,
88
+ valid_error_names=self._valid_error_names,
89
+ )
90
+
91
+ def __post_init__(self):
92
+ # We don't want IncludeExclude's post_init to run, so we override it.
93
+ # We are fine with just having the WarnErrorOptionsV2's post_init run on instantiation.
94
+ pass
95
+
96
+ def includes(self, item_name: Union[str, BaseEvent]) -> bool:
97
+ return self._warn_error_options_v2.includes(item_name)
98
+
99
+ def errors(self, item_name: Union[str, BaseEvent]) -> bool:
100
+ """Exists for forward compatibility with WarnErrorOptionsV2."""
101
+ return self._warn_error_options_v2.errors(item_name)
102
+
103
+ def silenced(self, item_name: Union[str, BaseEvent]) -> bool:
104
+ return self._warn_error_options_v2.silenced(item_name)
105
+
106
+
107
+ @dataclass
108
+ class WarnErrorOptionsV2(dbtClassMixin):
68
109
  """
69
110
  This class is used to configure the behavior of the warn_error feature (now part of fire_event).
70
111
 
71
- include: "all", "*", or a list of event names.
72
- exclude: a list of event names.
112
+ error: "all", "*", or a list of event names.
113
+ warn: a list of event names.
73
114
  silence: a list of event names.
74
- valid_error_names: a set of event names that can be named in include, exclude, and silence.
115
+ valid_error_names: a set of event names that can be named in error, warn, and silence.
75
116
 
76
117
  In a hierarchy of configuration, the following rules apply:
77
118
  1. named > Deprecations > "all"/"*"
78
- 2. silence > exclude > include
119
+ 2. silence > warn > error
79
120
  3. (1) > (2)
80
121
  """
81
122
 
123
+ ERROR_ALL = ("all", "*")
82
124
  DEPRECATIONS = "Deprecations"
83
125
 
126
+ error: Union[str, List[str]]
127
+ warn: List[str]
128
+ silence: List[str]
129
+
84
130
  def __init__(
85
131
  self,
86
- include: Union[str, List[str]],
87
- exclude: Optional[List[str]] = None,
88
- valid_error_names: Optional[Set[str]] = None,
132
+ error: Optional[Union[str, List[str]]] = None,
133
+ warn: Optional[List[str]] = None,
89
134
  silence: Optional[List[str]] = None,
135
+ valid_error_names: Optional[Set[str]] = None,
90
136
  ):
91
- self.silence = silence or []
92
137
  self._valid_error_names: Set[str] = valid_error_names or set()
93
138
  self._valid_error_names.add(self.DEPRECATIONS)
94
- super().__init__(include=include, exclude=(exclude or []))
95
139
 
96
- def __post_init__(self):
97
- if isinstance(self.include, str) and self.include not in self.INCLUDE_ALL:
98
- raise ValidationError(
99
- f"include must be one of {self.INCLUDE_ALL} or a list of strings"
100
- )
140
+ # We can't do `= error or []` because if someone passes in an empty list, and latter appends to that list
141
+ # they would expect references to the original list to be updated.
142
+ self.error = error if error is not None else []
143
+ self.warn = warn if warn is not None else []
144
+ self.silence = silence if silence is not None else []
145
+
146
+ # since we're overriding the dataclass auto __init__, we need to call __post_init__ manually
147
+ self.__post_init__()
101
148
 
102
- # To specify exclude, either `include` must be "all" or "deprecations" must be
103
- # in `include` or `silence`.
104
- if self.exclude and not (
105
- self.include in self.INCLUDE_ALL
106
- or self.DEPRECATIONS in self.include
149
+ def __post_init__(self):
150
+ if isinstance(self.error, str) and self.error not in self.ERROR_ALL:
151
+ raise ValidationError(f"error must be one of {self.ERROR_ALL} or a list of strings")
152
+
153
+ # To specify `warn`, one of the following must be true
154
+ # 1. `error` must be "all"/"*"
155
+ # 2. "deprecations" must be in either `error` or `silence`.
156
+ if self.warn and not (
157
+ self.error in self.ERROR_ALL
158
+ or self.DEPRECATIONS in self.error
107
159
  or self.DEPRECATIONS in self.silence
108
160
  ):
109
161
  raise ValidationError(
110
- f"exclude can only be specified if include is one of {self.INCLUDE_ALL} or "
111
- f"{self.DEPRECATIONS} is in include or silence."
162
+ f"`warn` can only be specified if `error` is one of {self.ERROR_ALL} or "
163
+ f"{self.DEPRECATIONS} is in `error` or silence."
112
164
  )
113
165
 
114
- if isinstance(self.include, list):
115
- self._validate_items(self.include)
166
+ if isinstance(self.error, list):
167
+ self._validate_items(self.error)
116
168
 
117
- if isinstance(self.exclude, list):
118
- self._validate_items(self.exclude)
169
+ if isinstance(self.warn, list):
170
+ self._validate_items(self.warn)
119
171
 
120
172
  if isinstance(self.silence, list):
121
173
  self._validate_items(self.silence)
122
174
 
123
- def _includes_all(self) -> bool:
124
- """Is `*` or `all` set as include?"""
125
- return self.include in self.INCLUDE_ALL
175
+ def _validate_items(self, items: List[str]):
176
+ for item in items:
177
+ if item not in self._valid_error_names:
178
+ raise ValidationError(f"{item} is not a valid dbt error name.")
179
+
180
+ def _error_all(self) -> bool:
181
+ """Is `*` or `all` set as error?"""
182
+ return self.error in self.ERROR_ALL
126
183
 
127
- def _named_inclusion(self, item_name: str) -> bool:
128
- """Is the item_name named in the include list?"""
129
- return item_name in self.include
184
+ def _named_error(self, item_name: str) -> bool:
185
+ """Is the item_name named in the error list?"""
186
+ return item_name in self.error
130
187
 
131
- def _named_exclusion(self, item_name: str) -> bool:
132
- """Is the item_name named in the exclude list?"""
133
- return item_name in self.exclude
188
+ def _named_warn(self, item_name: str) -> bool:
189
+ """Is the item_name named in the warn list?"""
190
+ return item_name in self.warn
134
191
 
135
192
  def _named_silence(self, item_name: str) -> bool:
136
193
  """Is the item_name named in the silence list?"""
137
194
  return item_name in self.silence
138
195
 
139
- def _include_as_deprecation(self, event: Optional[BaseEvent]) -> bool:
140
- """Is event included as a deprecation?"""
196
+ def _error_as_deprecation(self, event: Optional[BaseEvent]) -> bool:
197
+ """Is the event a deprecation, and if so should it be treated as an error?"""
141
198
  return (
142
- event is not None
143
- and event.code().startswith("D")
144
- and self.DEPRECATIONS in self.include
199
+ event is not None and event.code().startswith("D") and self.DEPRECATIONS in self.error
145
200
  )
146
201
 
147
- def _exclude_as_deprecation(self, event: Optional[BaseEvent]) -> bool:
148
- """Is event excluded as a deprecation?"""
202
+ def _warn_as_deprecation(self, event: Optional[BaseEvent]) -> bool:
203
+ """Is the event a deprecation, and if so should it be treated as an warning?"""
149
204
  return (
150
- event is not None
151
- and event.code().startswith("D")
152
- and self.DEPRECATIONS in self.exclude
205
+ event is not None and event.code().startswith("D") and self.DEPRECATIONS in self.warn
153
206
  )
154
207
 
155
208
  def _silence_as_deprecation(self, event: Optional[BaseEvent]) -> bool:
156
- """Is event silenced as a deprecation?"""
209
+ """Is the event a deprecation, and if so should it be silenced?"""
157
210
  return (
158
211
  event is not None
159
212
  and event.code().startswith("D")
160
213
  and self.DEPRECATIONS in self.silence
161
214
  )
162
215
 
163
- def includes(self, item_name: Union[str, BaseEvent]) -> bool:
164
- """Is the event included?
216
+ def errors(self, item_name: Union[str, BaseEvent]) -> bool:
217
+ """Should the event be treated as an error?
165
218
 
166
- An event included if any of the following are true:
167
- - The event is named in `include` and not named in `exclude` or `silence`
168
- - "*" or "all" is specified for `include`, and the event is not named in `exclude` or `silence`
169
- - The event is a deprecation, "deprecations" is in `include`, and the event is not named in `exclude` or `silence`
170
- nor is "deprecations" in `exclude` or `silence`
219
+ An event should error if any of the following are true:
220
+ - The event is named in `error` and not named in `warn` or `silence`
221
+ - "*" or "all" is specified for `error`, and the event is not named in `warn` or `silence`
222
+ - The event is a deprecation, "deprecations" is in `error`, and the event is not named in `warn` or `silence`
223
+ nor is "deprecations" in `warn` or `silence`
171
224
  """
172
225
  # Setup based on item_name type
173
226
  if isinstance(item_name, str):
@@ -178,29 +231,31 @@ class WarnErrorOptions(IncludeExclude):
178
231
  event = item_name
179
232
 
180
233
  # Pre-compute checks that will be used multiple times
181
- named_elsewhere = self._named_exclusion(event_name) or self._named_silence(event_name)
182
- deprecation_elsewhere = self._exclude_as_deprecation(
234
+ named_elsewhere = self._named_warn(event_name) or self._named_silence(event_name)
235
+ deprecation_elsewhere = self._warn_as_deprecation(event) or self._silence_as_deprecation(
183
236
  event
184
- ) or self._silence_as_deprecation(event)
237
+ )
185
238
 
186
239
  # Calculate result
187
- if self._named_inclusion(event_name) and not named_elsewhere:
240
+ if self._named_error(event_name) and not named_elsewhere:
188
241
  return True
189
- elif self._include_as_deprecation(event) and not (
190
- named_elsewhere or deprecation_elsewhere
191
- ):
242
+ elif self._error_as_deprecation(event) and not (named_elsewhere or deprecation_elsewhere):
192
243
  return True
193
- elif self._includes_all() and not (named_elsewhere or deprecation_elsewhere):
244
+ elif self._error_all() and not (named_elsewhere or deprecation_elsewhere):
194
245
  return True
195
246
  else:
196
247
  return False
197
248
 
249
+ def includes(self, item_name: Union[str, BaseEvent]) -> bool:
250
+ """Deprecated, use `errors` instead."""
251
+ return self.errors(item_name)
252
+
198
253
  def silenced(self, item_name: Union[str, BaseEvent]) -> bool:
199
254
  """Is the event silenced?
200
255
 
201
256
  An event silenced if any of the following are true:
202
257
  - The event is named in `silence`
203
- - "Deprecations" is in `silence` and the event is not named in `include` or `exclude`
258
+ - "Deprecations" is in `silence` and the event is not named in `error` or `warn`
204
259
  """
205
260
  # Setup based on item_name type
206
261
  if isinstance(item_name, str):
@@ -211,7 +266,7 @@ class WarnErrorOptions(IncludeExclude):
211
266
  event = item_name
212
267
 
213
268
  # Pre-compute checks that will be used multiple times
214
- named_elsewhere = self._named_inclusion(event_name) or self._named_exclusion(event_name)
269
+ named_elsewhere = self._named_error(event_name) or self._named_warn(event_name)
215
270
 
216
271
  # Calculate result
217
272
  if self._named_silence(event_name):
@@ -221,11 +276,6 @@ class WarnErrorOptions(IncludeExclude):
221
276
  else:
222
277
  return False
223
278
 
224
- def _validate_items(self, items: List[str]):
225
- for item in items:
226
- if item not in self._valid_error_names:
227
- raise ValidationError(f"{item} is not a valid dbt error name.")
228
-
229
279
 
230
280
  FQNPath = Tuple[str, ...]
231
281
  PathSet = AbstractSet[FQNPath]
dbt_common/ui.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from os import getenv as os_getenv
2
2
  import sys
3
3
  import textwrap
4
- from typing import Dict
4
+ from typing import Dict, Optional
5
5
 
6
6
  import colorama
7
7
 
@@ -78,13 +78,19 @@ def line_wrap_message(msg: str, subtract: int = 0, dedent: bool = True, prefix:
78
78
  return "\n".join(textwrap.fill(chunk, width=width, break_on_hyphens=False) for chunk in chunks)
79
79
 
80
80
 
81
- def warning_tag(msg: str) -> str:
82
- return f'[{yellow("WARNING")}]: {msg}'
81
+ def warning_tag(msg: str, event_name: Optional[str] = None) -> str:
82
+ tag = f'[{yellow("WARNING")}]'
83
+ if event_name:
84
+ tag += f"[{event_name}]"
85
+ return f"{tag}: {msg}"
83
86
 
84
87
 
85
- def deprecation_tag(msg: str) -> str:
86
- return warning_tag(f"Deprecated functionality\n\n{msg}")
88
+ def deprecation_tag(msg: str, event_name: Optional[str] = None) -> str:
89
+ return warning_tag(f"Deprecated functionality\n\n{msg}", event_name)
87
90
 
88
91
 
89
- def error_tag(msg: str) -> str:
90
- return f'[{red("ERROR")}]: {msg}'
92
+ def error_tag(msg: str, event_name: Optional[str] = None) -> str:
93
+ tag = f'[{red("ERROR")}]'
94
+ if event_name:
95
+ tag += f"[{event_name}]"
96
+ return f"{tag}: {msg}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbt-common
3
- Version: 1.23.0
3
+ Version: 1.24.0
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
@@ -1,16 +1,16 @@
1
- dbt_common/__about__.py,sha256=aQAgejfvBJWgErscsekMI9-f-XZYA6Im-fYbFUo9xPI,19
1
+ dbt_common/__about__.py,sha256=E8iFJObH8LUoUScRPYZad7ih455nH0reOnZSmEuNdh4,19
2
2
  dbt_common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  dbt_common/behavior_flags.py,sha256=hQzxCqQSweJbRp_xoQqNnlUF77PBuOdCdLOSdcBlkxk,4885
4
4
  dbt_common/constants.py,sha256=-Y5DIL1SDPQWtlCNizXRYxFgbx1D7LaLs1ysamvGMRk,278
5
5
  dbt_common/context.py,sha256=-ErtKG4xfOh1-Y569fwu6u2O381nRan18HhATrYDoZE,2950
6
6
  dbt_common/dataclass_schema.py,sha256=u2S0dxwxIghv8RMqC91HlWZJVxmsC_844yZQaGyOwdY,5563
7
- dbt_common/helper_types.py,sha256=v6ak-05SodNDxJM7BGXyCT4yPM-OUhcvznjemXRYT-g,9117
7
+ dbt_common/helper_types.py,sha256=LuUILGUG_q35iULjtW-bb_UchLV2y7iQdSqpUKiLtAA,11200
8
8
  dbt_common/invocation.py,sha256=xw0NBIE-6LHd135cx4non-MkGGsia0mYN0lMkmNEucE,435
9
9
  dbt_common/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  dbt_common/record.py,sha256=QLrKppBHYuV7ZTckOMi4Gnz7jLQJcOa5kp4PwK0JmwY,21889
11
11
  dbt_common/semver.py,sha256=Znewz6tc_NBpXr4mZf20bK_RayPL4ODrnxDbkUZrrRo,15034
12
12
  dbt_common/tests.py,sha256=6lC_JuRtoYO6cbAF8-R5aTM4HtQiM_EH8X5m_97duGY,315
13
- dbt_common/ui.py,sha256=rC-d4J3u0sBH_0L1AZdQ-mDxPrTDYecTFn65mNqQ-ig,2668
13
+ dbt_common/ui.py,sha256=geIk3ElFj5y_SG5EDc6RMJFEvYGdo-6C21l0pB8I-EU,2934
14
14
  dbt_common/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  dbt_common/clients/_jinja_blocks.py,sha256=eUjZLBtLCASJRRj1G8b9u15A3PQMDCKvytIdWkTLSP4,15451
16
16
  dbt_common/clients/agate_helper.py,sha256=anKKgKV5PSnFRuFeBwRMdHK3JCaQoUqB2ZXHD0su0Wo,9123
@@ -30,7 +30,7 @@ dbt_common/events/__init__.py,sha256=av08vfpxo0ek7PqZNtMxY8FODJ3xwph4ehRxgInx4LA
30
30
  dbt_common/events/base_types.py,sha256=bdDMbawAV0FkxmvuxgsTev82vxTuyu6rJiSkvEQPsO8,5525
31
31
  dbt_common/events/contextvars.py,sha256=EIs1P6NrJzx_IAV17x5cVqOAS4Lqbu6oc0etHtWCJOo,3097
32
32
  dbt_common/events/event_handler.py,sha256=jfi0PyqIOGnXCG9HEa0VIVULqNvXs1RYmAg0b50ChQs,1385
33
- dbt_common/events/event_manager.py,sha256=ElltioymOwrDmSdYpiyTNPOEFIOWQMQ9b_hAARmf5aE,4528
33
+ dbt_common/events/event_manager.py,sha256=jp91-qW7DmbAEHjmNzPUH8NrXpEOYNQVGeIyZBpkr8Y,4699
34
34
  dbt_common/events/event_manager_client.py,sha256=5IVdIuRVi5xCNQGiZqXdywlED2kLj1W_Pj0lh2HiDiI,1115
35
35
  dbt_common/events/format.py,sha256=x1RWDZ8G7ZMHmxdld6Q4VXca4kvnhiQOIaQXkC6Uo0Q,1609
36
36
  dbt_common/events/functions.py,sha256=R3DuyNy2TqOwNyMACVOYtiG1NjZ9FQa6FWKkzMeMCBY,4767
@@ -57,7 +57,7 @@ dbt_common/utils/encoding.py,sha256=6_kSY2FvGNYMg7oX7PrbvVioieydih3Kl7Ii802LaHI,
57
57
  dbt_common/utils/executor.py,sha256=pNY0UbPlwQmTE69Vt_Rj91YGCIOEaqeYU3CjAds0T70,2454
58
58
  dbt_common/utils/formatting.py,sha256=JUn5rzJ-uajs9wPCN0-f2iRFY1pOJF5YjTD9dERuLoc,165
59
59
  dbt_common/utils/jinja.py,sha256=JXgNmJArGGy0h7qkbNLA3zaEQmoF1CxsNBYTlIwFXDw,1101
60
- dbt_common-1.23.0.dist-info/METADATA,sha256=ba64BsaO0C5gCGrnpfKQ8IOxJsgdoX6ZKFJc7w3REMU,4946
61
- dbt_common-1.23.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
62
- dbt_common-1.23.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
63
- dbt_common-1.23.0.dist-info/RECORD,,
60
+ dbt_common-1.24.0.dist-info/METADATA,sha256=pMLQDmfri6a3jpg2HN8bct605SOz4SnRAW6J_ekNzDk,4946
61
+ dbt_common-1.24.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
62
+ dbt_common-1.24.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
63
+ dbt_common-1.24.0.dist-info/RECORD,,