dbt-common 1.8.0__py3-none-any.whl → 1.9.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.8.0"
1
+ version = "1.9.0"
@@ -9,8 +9,8 @@ except ImportError:
9
9
  from typing import Optional as NotRequired
10
10
 
11
11
  from dbt_common.events.functions import fire_event
12
- from dbt_common.events.types import BehaviorDeprecationEvent
13
- from dbt_common.exceptions import CompilationError
12
+ from dbt_common.events.types import BehaviorChangeEvent
13
+ from dbt_common.exceptions import CompilationError, DbtInternalError
14
14
 
15
15
 
16
16
  class BehaviorFlag(TypedDict):
@@ -20,16 +20,20 @@ class BehaviorFlag(TypedDict):
20
20
  Args:
21
21
  name: the name of the behavior flag
22
22
  default: default setting, starts as False, becomes True after a bake-in period
23
- deprecation_version: the version when the default will change to True
24
- deprecation_message: an additional message to send when the flag evaluates to False
23
+ description: an additional message to send when the flag evaluates to False
25
24
  docs_url: the url to the relevant docs on docs.getdbt.com
25
+
26
+ *Note*:
27
+ While `description` and `docs_url` are both listed as `NotRequired`, at least one of them is required.
28
+ This is validated when the flag is rendered in `BehaviorFlagRendered` below.
29
+ The goal of this restriction is to provide the end user with context so they can make an informed decision
30
+ about if, and when, to enable the behavior flag.
26
31
  """
27
32
 
28
33
  name: str
29
34
  default: bool
30
35
  source: NotRequired[str]
31
- deprecation_version: NotRequired[str]
32
- deprecation_message: NotRequired[str]
36
+ description: NotRequired[str]
33
37
  docs_url: NotRequired[str]
34
38
 
35
39
 
@@ -43,14 +47,33 @@ class BehaviorFlagRendered:
43
47
  """
44
48
 
45
49
  def __init__(self, flag: BehaviorFlag, user_overrides: Dict[str, Any]) -> None:
50
+ self._validate(flag)
51
+
46
52
  self.name = flag["name"]
47
53
  self.setting = user_overrides.get(flag["name"], flag["default"])
48
- self.deprecation_event = self._deprecation_event(flag)
54
+
55
+ default_description = (
56
+ f"""The behavior controlled by `{flag["name"]}` is currently turned off.\n"""
57
+ )
58
+ default_docs_url = "https://docs.getdbt.com/reference/global-configs/behavior-changes"
59
+ self._behavior_change_event = BehaviorChangeEvent(
60
+ flag_name=flag["name"],
61
+ flag_source=flag.get("source", self._default_source()),
62
+ description=flag.get("description", default_description),
63
+ docs_url=flag.get("docs_url", default_docs_url),
64
+ )
65
+
66
+ @staticmethod
67
+ def _validate(flag: BehaviorFlag) -> None:
68
+ if flag.get("description") is None and flag.get("docs_url") is None:
69
+ raise DbtInternalError(
70
+ "Behavior change flags require at least one of `description` and `docs_url`."
71
+ )
49
72
 
50
73
  @property
51
74
  def setting(self) -> bool:
52
75
  if self._setting is False:
53
- fire_event(self.deprecation_event)
76
+ fire_event(self._behavior_change_event)
54
77
  return self._setting
55
78
 
56
79
  @setting.setter
@@ -61,15 +84,6 @@ class BehaviorFlagRendered:
61
84
  def no_warn(self) -> bool:
62
85
  return self._setting
63
86
 
64
- def _deprecation_event(self, flag: BehaviorFlag) -> BehaviorDeprecationEvent:
65
- return BehaviorDeprecationEvent(
66
- flag_name=flag["name"],
67
- flag_source=flag.get("source", self._default_source()),
68
- deprecation_version=flag.get("deprecation_version"),
69
- deprecation_message=flag.get("deprecation_message"),
70
- docs_url=flag.get("docs_url"),
71
- )
72
-
73
87
  @staticmethod
74
88
  def _default_source() -> str:
75
89
  """
@@ -95,7 +109,7 @@ class Behavior:
95
109
  if adapter.behavior.my_flag:
96
110
  ...
97
111
 
98
- if adapter.behavior.my_flag.no_warn: # this will not fire the deprecation event
112
+ if adapter.behavior.my_flag.no_warn: # this will not fire the behavior change event
99
113
  ...
100
114
  ```
101
115
  ```jinja
@@ -103,7 +117,7 @@ class Behavior:
103
117
  ...
104
118
  {% endif %}
105
119
 
106
- {% if adapter.behavior.my_flag.no_warn %} {# this will not fire the deprecation event #}
120
+ {% if adapter.behavior.my_flag.no_warn %} {# this will not fire the behavior change event #}
107
121
  ...
108
122
  {% endif %}
109
123
  ```
@@ -6,7 +6,21 @@ from ast import literal_eval
6
6
  from collections import ChainMap
7
7
  from contextlib import contextmanager
8
8
  from itertools import chain, islice
9
- from typing import Any, Callable, Dict, Iterator, List, Mapping, Optional, Union, Set, Type
9
+ from types import CodeType
10
+ from typing import (
11
+ Any,
12
+ Callable,
13
+ Dict,
14
+ Iterator,
15
+ List,
16
+ Mapping,
17
+ Optional,
18
+ Union,
19
+ Set,
20
+ Type,
21
+ NoReturn,
22
+ )
23
+
10
24
  from typing_extensions import Protocol
11
25
 
12
26
  import jinja2
@@ -39,10 +53,17 @@ from dbt_common.exceptions.macros import MacroReturn, UndefinedMacroError, Caugh
39
53
  SUPPORTED_LANG_ARG = jinja2.nodes.Name("supported_languages", "param")
40
54
 
41
55
  # Global which can be set by dependents of dbt-common (e.g. core via flag parsing)
42
- MACRO_DEBUGGING = False
56
+ MACRO_DEBUGGING: Union[str, bool] = False
57
+
58
+ _ParseReturn = Union[jinja2.nodes.Node, List[jinja2.nodes.Node]]
59
+
60
+
61
+ # Temporary type capturing the concept the functions in this file expect for a "node"
62
+ class _NodeProtocol(Protocol):
63
+ pass
43
64
 
44
65
 
45
- def _linecache_inject(source, write):
66
+ def _linecache_inject(source: str, write: bool) -> str:
46
67
  if write:
47
68
  # this is the only reliable way to accomplish this. Obviously, it's
48
69
  # really darn noisy and will fill your temporary directory
@@ -58,18 +79,18 @@ def _linecache_inject(source, write):
58
79
  else:
59
80
  # `codecs.encode` actually takes a `bytes` as the first argument if
60
81
  # the second argument is 'hex' - mypy does not know this.
61
- rnd = codecs.encode(os.urandom(12), "hex") # type: ignore
82
+ rnd = codecs.encode(os.urandom(12), "hex")
62
83
  filename = rnd.decode("ascii")
63
84
 
64
85
  # put ourselves in the cache
65
86
  cache_entry = (len(source), None, [line + "\n" for line in source.splitlines()], filename)
66
87
  # linecache does in fact have an attribute `cache`, thanks
67
- linecache.cache[filename] = cache_entry # type: ignore
88
+ linecache.cache[filename] = cache_entry
68
89
  return filename
69
90
 
70
91
 
71
92
  class MacroFuzzParser(jinja2.parser.Parser):
72
- def parse_macro(self):
93
+ def parse_macro(self) -> jinja2.nodes.Macro:
73
94
  node = jinja2.nodes.Macro(lineno=next(self.stream).lineno)
74
95
 
75
96
  # modified to fuzz macros defined in the same file. this way
@@ -83,16 +104,13 @@ class MacroFuzzParser(jinja2.parser.Parser):
83
104
 
84
105
 
85
106
  class MacroFuzzEnvironment(jinja2.sandbox.SandboxedEnvironment):
86
- def _parse(self, source, name, filename):
107
+ def _parse(
108
+ self, source: str, name: Optional[str], filename: Optional[str]
109
+ ) -> jinja2.nodes.Template:
87
110
  return MacroFuzzParser(self, source, name, filename).parse()
88
111
 
89
- def _compile(self, source, filename):
112
+ def _compile(self, source: str, filename: str) -> CodeType:
90
113
  """
91
-
92
-
93
-
94
-
95
-
96
114
  Override jinja's compilation. Use to stash the rendered source inside
97
115
  the python linecache for debugging when the appropriate environment
98
116
  variable is set.
@@ -108,7 +126,7 @@ class MacroFuzzEnvironment(jinja2.sandbox.SandboxedEnvironment):
108
126
 
109
127
 
110
128
  class MacroFuzzTemplate(jinja2.nativetypes.NativeTemplate):
111
- environment_class = MacroFuzzEnvironment
129
+ environment_class = MacroFuzzEnvironment # type: ignore
112
130
 
113
131
  def new_context(
114
132
  self,
@@ -171,11 +189,11 @@ class NumberMarker(NativeMarker):
171
189
  pass
172
190
 
173
191
 
174
- def _is_number(value) -> bool:
192
+ def _is_number(value: Any) -> bool:
175
193
  return isinstance(value, (int, float)) and not isinstance(value, bool)
176
194
 
177
195
 
178
- def quoted_native_concat(nodes):
196
+ def quoted_native_concat(nodes: Iterator[str]) -> Any:
179
197
  """Handle special case for native_concat from the NativeTemplate.
180
198
 
181
199
  This is almost native_concat from the NativeTemplate, except in the
@@ -213,7 +231,7 @@ def quoted_native_concat(nodes):
213
231
  class NativeSandboxTemplate(jinja2.nativetypes.NativeTemplate): # mypy: ignore
214
232
  environment_class = NativeSandboxEnvironment # type: ignore
215
233
 
216
- def render(self, *args, **kwargs):
234
+ def render(self, *args: Any, **kwargs: Any) -> Any:
217
235
  """Render the template to produce a native Python type.
218
236
 
219
237
  If the result is a single node, its value is returned. Otherwise,
@@ -229,6 +247,11 @@ class NativeSandboxTemplate(jinja2.nativetypes.NativeTemplate): # mypy: ignore
229
247
  return self.environment.handle_exception()
230
248
 
231
249
 
250
+ class MacroProtocol(Protocol):
251
+ name: str
252
+ macro_sql: str
253
+
254
+
232
255
  NativeSandboxEnvironment.template_class = NativeSandboxTemplate # type: ignore
233
256
 
234
257
 
@@ -236,7 +259,7 @@ class TemplateCache:
236
259
  def __init__(self) -> None:
237
260
  self.file_cache: Dict[str, jinja2.Template] = {}
238
261
 
239
- def get_node_template(self, node) -> jinja2.Template:
262
+ def get_node_template(self, node: MacroProtocol) -> jinja2.Template:
240
263
  key = node.macro_sql
241
264
 
242
265
  if key in self.file_cache:
@@ -251,7 +274,7 @@ class TemplateCache:
251
274
  self.file_cache[key] = template
252
275
  return template
253
276
 
254
- def clear(self):
277
+ def clear(self) -> None:
255
278
  self.file_cache.clear()
256
279
 
257
280
 
@@ -262,13 +285,13 @@ class BaseMacroGenerator:
262
285
  def __init__(self, context: Optional[Dict[str, Any]] = None) -> None:
263
286
  self.context: Optional[Dict[str, Any]] = context
264
287
 
265
- def get_template(self):
288
+ def get_template(self) -> jinja2.Template:
266
289
  raise NotImplementedError("get_template not implemented!")
267
290
 
268
291
  def get_name(self) -> str:
269
292
  raise NotImplementedError("get_name not implemented!")
270
293
 
271
- def get_macro(self):
294
+ def get_macro(self) -> Callable:
272
295
  name = self.get_name()
273
296
  template = self.get_template()
274
297
  # make the module. previously we set both vars and local, but that's
@@ -286,7 +309,7 @@ class BaseMacroGenerator:
286
309
  except (TypeError, jinja2.exceptions.TemplateRuntimeError) as e:
287
310
  raise CaughtMacroError(e)
288
311
 
289
- def call_macro(self, *args, **kwargs):
312
+ def call_macro(self, *args: Any, **kwargs: Any) -> Any:
290
313
  # called from __call__ methods
291
314
  if self.context is None:
292
315
  raise DbtInternalError("Context is still None in call_macro!")
@@ -301,11 +324,6 @@ class BaseMacroGenerator:
301
324
  return e.value
302
325
 
303
326
 
304
- class MacroProtocol(Protocol):
305
- name: str
306
- macro_sql: str
307
-
308
-
309
327
  class CallableMacroGenerator(BaseMacroGenerator):
310
328
  def __init__(
311
329
  self,
@@ -315,7 +333,7 @@ class CallableMacroGenerator(BaseMacroGenerator):
315
333
  super().__init__(context)
316
334
  self.macro = macro
317
335
 
318
- def get_template(self):
336
+ def get_template(self) -> jinja2.Template:
319
337
  return template_cache.get_node_template(self.macro)
320
338
 
321
339
  def get_name(self) -> str:
@@ -332,14 +350,14 @@ class CallableMacroGenerator(BaseMacroGenerator):
332
350
  raise e
333
351
 
334
352
  # this makes MacroGenerator objects callable like functions
335
- def __call__(self, *args, **kwargs):
353
+ def __call__(self, *args: Any, **kwargs: Any) -> Any:
336
354
  return self.call_macro(*args, **kwargs)
337
355
 
338
356
 
339
357
  class MaterializationExtension(jinja2.ext.Extension):
340
358
  tags = ["materialization"]
341
359
 
342
- def parse(self, parser):
360
+ def parse(self, parser: jinja2.parser.Parser) -> _ParseReturn:
343
361
  node = jinja2.nodes.Macro(lineno=next(parser.stream).lineno)
344
362
  materialization_name = parser.parse_assign_target(name_only=True).name
345
363
 
@@ -382,7 +400,7 @@ class MaterializationExtension(jinja2.ext.Extension):
382
400
  class DocumentationExtension(jinja2.ext.Extension):
383
401
  tags = ["docs"]
384
402
 
385
- def parse(self, parser):
403
+ def parse(self, parser: jinja2.parser.Parser) -> _ParseReturn:
386
404
  node = jinja2.nodes.Macro(lineno=next(parser.stream).lineno)
387
405
  docs_name = parser.parse_assign_target(name_only=True).name
388
406
 
@@ -396,7 +414,7 @@ class DocumentationExtension(jinja2.ext.Extension):
396
414
  class TestExtension(jinja2.ext.Extension):
397
415
  tags = ["test"]
398
416
 
399
- def parse(self, parser):
417
+ def parse(self, parser: jinja2.parser.Parser) -> _ParseReturn:
400
418
  node = jinja2.nodes.Macro(lineno=next(parser.stream).lineno)
401
419
  test_name = parser.parse_assign_target(name_only=True).name
402
420
 
@@ -406,13 +424,19 @@ class TestExtension(jinja2.ext.Extension):
406
424
  return node
407
425
 
408
426
 
409
- def _is_dunder_name(name):
427
+ def _is_dunder_name(name: str) -> bool:
410
428
  return name.startswith("__") and name.endswith("__")
411
429
 
412
430
 
413
- def create_undefined(node=None):
431
+ def create_undefined(node: Optional[_NodeProtocol] = None) -> Type[jinja2.Undefined]:
414
432
  class Undefined(jinja2.Undefined):
415
- def __init__(self, hint=None, obj=None, name=None, exc=None):
433
+ def __init__(
434
+ self,
435
+ hint: Optional[str] = None,
436
+ obj: Any = None,
437
+ name: Optional[str] = None,
438
+ exc: Any = None,
439
+ ) -> None:
416
440
  super().__init__(hint=hint, name=name)
417
441
  self.node = node
418
442
  self.name = name
@@ -422,12 +446,12 @@ def create_undefined(node=None):
422
446
  self.unsafe_callable = False
423
447
  self.alters_data = False
424
448
 
425
- def __getitem__(self, name):
449
+ def __getitem__(self, name: Any) -> "Undefined":
426
450
  # Propagate the undefined value if a caller accesses this as if it
427
451
  # were a dictionary
428
452
  return self
429
453
 
430
- def __getattr__(self, name):
454
+ def __getattr__(self, name: str) -> "Undefined":
431
455
  if name == "name" or _is_dunder_name(name):
432
456
  raise AttributeError(
433
457
  "'{}' object has no attribute '{}'".format(type(self).__name__, name)
@@ -437,11 +461,11 @@ def create_undefined(node=None):
437
461
 
438
462
  return self.__class__(hint=self.hint, name=self.name)
439
463
 
440
- def __call__(self, *args, **kwargs):
464
+ def __call__(self, *args: Any, **kwargs: Any) -> "Undefined":
441
465
  return self
442
466
 
443
- def __reduce__(self):
444
- raise UndefinedCompilationError(name=self.name, node=node)
467
+ def __reduce__(self) -> NoReturn:
468
+ raise UndefinedCompilationError(name=self.name or "unknown", node=node)
445
469
 
446
470
  return Undefined
447
471
 
@@ -463,7 +487,7 @@ TEXT_FILTERS: Dict[str, Callable[[Any], Any]] = {
463
487
 
464
488
 
465
489
  def get_environment(
466
- node=None,
490
+ node: Optional[_NodeProtocol] = None,
467
491
  capture_macros: bool = False,
468
492
  native: bool = False,
469
493
  ) -> jinja2.Environment:
@@ -472,7 +496,7 @@ def get_environment(
472
496
  }
473
497
 
474
498
  if capture_macros:
475
- args["undefined"] = create_undefined(node)
499
+ args["undefined"] = create_undefined(node) # type: ignore
476
500
 
477
501
  args["extensions"].append(MaterializationExtension)
478
502
  args["extensions"].append(DocumentationExtension)
@@ -493,7 +517,7 @@ def get_environment(
493
517
 
494
518
 
495
519
  @contextmanager
496
- def catch_jinja(node=None) -> Iterator[None]:
520
+ def catch_jinja(node: Optional[_NodeProtocol] = None) -> Iterator[None]:
497
521
  try:
498
522
  yield
499
523
  except jinja2.exceptions.TemplateSyntaxError as e:
@@ -506,16 +530,16 @@ def catch_jinja(node=None) -> Iterator[None]:
506
530
  raise
507
531
 
508
532
 
509
- _TESTING_PARSE_CACHE: Dict[str, jinja2.Template] = {}
533
+ _TESTING_PARSE_CACHE: Dict[str, jinja2.nodes.Template] = {}
510
534
 
511
535
 
512
- def parse(string):
536
+ def parse(string: Any) -> jinja2.nodes.Template:
513
537
  str_string = str(string)
514
538
  if test_caching_enabled() and str_string in _TESTING_PARSE_CACHE:
515
539
  return _TESTING_PARSE_CACHE[str_string]
516
540
 
517
541
  with catch_jinja():
518
- parsed = get_environment().parse(str(string))
542
+ parsed: jinja2.nodes.Template = get_environment().parse(str(string))
519
543
  if test_caching_enabled():
520
544
  _TESTING_PARSE_CACHE[str_string] = parsed
521
545
  return parsed
@@ -524,10 +548,10 @@ def parse(string):
524
548
  def get_template(
525
549
  string: str,
526
550
  ctx: Dict[str, Any],
527
- node=None,
551
+ node: Optional[_NodeProtocol] = None,
528
552
  capture_macros: bool = False,
529
553
  native: bool = False,
530
- ):
554
+ ) -> jinja2.Template:
531
555
  with catch_jinja(node):
532
556
  env = get_environment(node, capture_macros, native=native)
533
557
 
@@ -535,7 +559,9 @@ def get_template(
535
559
  return env.from_string(template_source, globals=ctx)
536
560
 
537
561
 
538
- def render_template(template, ctx: Dict[str, Any], node=None) -> str:
562
+ def render_template(
563
+ template: jinja2.Template, ctx: Dict[str, Any], node: Optional[_NodeProtocol] = None
564
+ ) -> str:
539
565
  with catch_jinja(node):
540
566
  return template.render(ctx)
541
567
 
@@ -96,10 +96,14 @@ class BaseConfig(AdditionalPropertiesAllowed, Replaceable):
96
96
  return False
97
97
  return True
98
98
 
99
- # This is used in 'add_config_call' to create the combined config_call_dict.
100
- # 'meta' moved here from node
99
+ # This is used in 'merge_config_dicts' to create the combined orig_dict.
100
+ # Note: "clobber" fields aren't defined, because that's the default.
101
+ # "access" is currently the only Clobber field.
102
+ # This shouldn't really be defined here. It would be better to have it
103
+ # associated with the config definitions, but at the point we use it, we
104
+ # don't know which config we're dealing with.
101
105
  mergebehavior = {
102
- "append": ["pre-hook", "pre_hook", "post-hook", "post_hook", "tags"],
106
+ "append": ["pre-hook", "pre_hook", "post-hook", "post_hook", "tags", "packages"],
103
107
  "update": [
104
108
  "quoting",
105
109
  "column_types",
@@ -108,6 +112,7 @@ class BaseConfig(AdditionalPropertiesAllowed, Replaceable):
108
112
  "contract",
109
113
  ],
110
114
  "dict_key_append": ["grants"],
115
+ "object": ["snapshot_meta_column_names"],
111
116
  }
112
117
 
113
118
  @classmethod
@@ -180,6 +185,7 @@ class MergeBehavior(Metadata):
180
185
  Update = 2
181
186
  Clobber = 3
182
187
  DictKeyAppend = 4
188
+ Object = 5
183
189
 
184
190
  @classmethod
185
191
  def default_field(cls) -> "MergeBehavior":
@@ -215,8 +221,10 @@ def _listify(value: Any) -> List[Any]:
215
221
 
216
222
 
217
223
  # There are two versions of this code. The one here is for config
218
- # objects, the one in _add_config_call in core context_config.py is for
219
- # config_call_dict dictionaries.
224
+ # objects which can get the "MergeBehavior" from the field in the class,
225
+ # the one below in 'merge_config_dicts' (formerly in
226
+ # _add_config_call in core context_config.py) is for config_call dictionaries
227
+ # where we need to get the MergeBehavior from someplace else.
220
228
  def _merge_field_value(
221
229
  merge_behavior: MergeBehavior,
222
230
  self_value: Any,
@@ -225,7 +233,8 @@ def _merge_field_value(
225
233
  if merge_behavior == MergeBehavior.Clobber:
226
234
  return other_value
227
235
  elif merge_behavior == MergeBehavior.Append:
228
- return _listify(self_value) + _listify(other_value)
236
+ new_value = _listify(self_value) + _listify(other_value)
237
+ return new_value
229
238
  elif merge_behavior == MergeBehavior.Update:
230
239
  if not isinstance(self_value, dict):
231
240
  raise DbtInternalError(f"expected dict, got {self_value}")
@@ -258,6 +267,73 @@ def _merge_field_value(
258
267
  # clobber the list
259
268
  new_dict[new_key] = _listify(other_value[key])
260
269
  return new_dict
261
-
270
+ elif merge_behavior == MergeBehavior.Object:
271
+ # All fields in classes with MergeBehavior.Object should have a default of None
272
+ if not type(self_value).__name__ == type(other_value).__name__:
273
+ raise DbtInternalError(
274
+ f"got conflicting types: {type(self_value).__name__} and {type(other_value).__name__}"
275
+ )
276
+ new_value = self_value.copy()
277
+ new_value.update(other_value)
278
+ return new_value
262
279
  else:
263
280
  raise DbtInternalError(f"Got an invalid merge_behavior: {merge_behavior}")
281
+
282
+
283
+ # This is used in ContextConfig._add_config_call. It updates the orig_dict in place.
284
+ def merge_config_dicts(orig_dict: Dict[str, Any], new_dict: Dict[str, Any]) -> None:
285
+ # orig_dict is already encountered configs, new_dict is new
286
+ # This mirrors code in _merge_field_value in model_config.py which is similar but
287
+ # operates on config objects.
288
+ if orig_dict == {}:
289
+ orig_dict.update(new_dict)
290
+ return
291
+ for k, v in new_dict.items():
292
+ # MergeBehavior for post-hook and pre-hook is to collect all
293
+ # values, instead of overwriting
294
+ if k in BaseConfig.mergebehavior["append"]:
295
+ if k in orig_dict: # should always be a list here
296
+ orig_dict[k] = _listify(orig_dict[k]) + _listify(v)
297
+ else:
298
+ orig_dict[k] = _listify(v)
299
+ elif k in BaseConfig.mergebehavior["update"]:
300
+ if not isinstance(v, dict):
301
+ raise DbtInternalError(f"expected dict, got {v}")
302
+ if k in orig_dict and isinstance(orig_dict[k], dict):
303
+ orig_dict[k].update(v)
304
+ else:
305
+ orig_dict[k] = v
306
+ elif k in BaseConfig.mergebehavior["dict_key_append"]:
307
+ if not isinstance(v, dict):
308
+ raise DbtInternalError(f"expected dict, got {v}")
309
+ if k in orig_dict: # should always be a dict
310
+ for key in orig_dict[k].keys():
311
+ orig_dict[k][key] = _listify(orig_dict[k][key])
312
+ for key, value in v.items():
313
+ extend = False
314
+ # This might start with a +, to indicate we should extend the list
315
+ # instead of just clobbering it. We don't want to remove the + here
316
+ # (like in the other method) because we want it preserved
317
+ if key.startswith("+"):
318
+ extend = True
319
+ if key in orig_dict[k] and extend:
320
+ # extend the list
321
+ orig_dict[k][key].extend(_listify(value))
322
+ else:
323
+ # clobber the list
324
+ orig_dict[k][key] = _listify(value)
325
+ else:
326
+ # This is always a dictionary
327
+ orig_dict[k] = v
328
+ # listify everything
329
+ for key, value in orig_dict[k].items():
330
+ orig_dict[k][key] = _listify(value)
331
+ elif k in BaseConfig.mergebehavior["object"]:
332
+ if not isinstance(v, dict):
333
+ raise DbtInternalError(f"expected dict, got {v}")
334
+ if k not in orig_dict:
335
+ orig_dict[k] = {}
336
+ for obj_k, obj_v in v.items():
337
+ orig_dict[k][obj_k] = obj_v
338
+ else: # Clobber
339
+ orig_dict[k] = v
@@ -26,17 +26,16 @@ message GenericMessage {
26
26
  // D - Deprecations
27
27
 
28
28
  // D018
29
- message BehaviorDeprecationEvent {
29
+ message BehaviorChangeEvent {
30
30
  string flag_name = 1;
31
31
  string flag_source = 2;
32
- string deprecation_version = 3;
33
- string deprecation_message = 4;
34
- string docs_url = 5;
32
+ string description = 3;
33
+ string docs_url = 4;
35
34
  }
36
35
 
37
- message BehaviorDeprecationEventMsg {
36
+ message BehaviorChangeEventMsg {
38
37
  EventInfo info = 1;
39
- BehaviorDeprecationEvent data = 2;
38
+ BehaviorChangeEvent data = 2;
40
39
  }
41
40
 
42
41
  // M - Deps generation
@@ -1,5 +1,3 @@
1
- from typing import Optional
2
-
3
1
  from dbt_common.events.base_types import (
4
2
  DebugLevel,
5
3
  InfoLevel,
@@ -38,33 +36,16 @@ from dbt_common.ui import warning_tag
38
36
  # =======================================================
39
37
 
40
38
 
41
- class BehaviorDeprecationEvent(WarnLevel):
42
- flag_name: str
43
- flag_source: str
44
- deprecation_version: Optional[str]
45
- deprecation_message: Optional[str]
46
- docs_url: Optional[str]
47
-
39
+ class BehaviorChangeEvent(WarnLevel):
48
40
  def code(self) -> str:
49
41
  return "D018"
50
42
 
51
43
  def message(self) -> str:
52
- msg = f"The legacy behavior controlled by `{self.flag_name}` is deprecated.\n"
53
-
54
- if self.deprecation_version:
55
- msg = (
56
- f"The legacy behavior is expected to be retired in `{self.deprecation_version}`.\n"
57
- )
58
-
59
- msg += f"The new behavior can be turned on by setting `flags.{self.flag_name}` to `True` in `dbt_project.yml`.\n"
60
-
61
- if self.deprecation_message:
62
- msg += f"{self.deprecation_message}.\n"
63
-
64
- docs_url = self.docs_url or f"https://docs.getdbt.com/search?q={self.flag_name}"
65
- msg += f"Visit {docs_url} for more information."
66
-
67
- return warning_tag(msg)
44
+ return warning_tag(
45
+ f"{self.description}\n"
46
+ f"You may opt into the new behavior sooner by setting `flags.{self.flag_name}` to `True` in `dbt_project.yml`.\n"
47
+ f"Visit {self.docs_url} for more information."
48
+ )
68
49
 
69
50
 
70
51
  # =======================================================
@@ -15,7 +15,7 @@ _sym_db = _symbol_database.Default()
15
15
  from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
16
16
 
17
17
 
18
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0btypes.proto\x12\x0bproto_types\x1a\x1fgoogle/protobuf/timestamp.proto\"\x91\x02\n\tEventInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\x12\x0b\n\x03msg\x18\x03 \x01(\t\x12\r\n\x05level\x18\x04 \x01(\t\x12\x15\n\rinvocation_id\x18\x05 \x01(\t\x12\x0b\n\x03pid\x18\x06 \x01(\x05\x12\x0e\n\x06thread\x18\x07 \x01(\t\x12&\n\x02ts\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x05\x65xtra\x18\t \x03(\x0b\x32!.proto_types.EventInfo.ExtraEntry\x12\x10\n\x08\x63\x61tegory\x18\n \x01(\t\x1a,\n\nExtraEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"6\n\x0eGenericMessage\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\"\x8e\x01\n\x18\x42\x65haviorDeprecationEvent\x12\x11\n\tflag_name\x18\x01 \x01(\t\x12\x13\n\x0b\x66lag_source\x18\x02 \x01(\t\x12\x1b\n\x13\x64\x65precation_version\x18\x03 \x01(\t\x12\x1b\n\x13\x64\x65precation_message\x18\x04 \x01(\t\x12\x10\n\x08\x64ocs_url\x18\x05 \x01(\t\"x\n\x1b\x42\x65haviorDeprecationEventMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\x33\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32%.proto_types.BehaviorDeprecationEvent\"1\n\x11RetryExternalCall\x12\x0f\n\x07\x61ttempt\x18\x01 \x01(\x05\x12\x0b\n\x03max\x18\x02 \x01(\x05\"j\n\x14RetryExternalCallMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12,\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x1e.proto_types.RetryExternalCall\"#\n\x14RecordRetryException\x12\x0b\n\x03\x65xc\x18\x01 \x01(\t\"p\n\x17RecordRetryExceptionMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12/\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32!.proto_types.RecordRetryException\"@\n\x13SystemCouldNotWrite\x12\x0c\n\x04path\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x0b\n\x03\x65xc\x18\x03 \x01(\t\"n\n\x16SystemCouldNotWriteMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12.\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32 .proto_types.SystemCouldNotWrite\"!\n\x12SystemExecutingCmd\x12\x0b\n\x03\x63md\x18\x01 \x03(\t\"l\n\x15SystemExecutingCmdMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12-\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x1f.proto_types.SystemExecutingCmd\"\x1c\n\x0cSystemStdOut\x12\x0c\n\x04\x62msg\x18\x01 \x01(\t\"`\n\x0fSystemStdOutMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\'\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x19.proto_types.SystemStdOut\"\x1c\n\x0cSystemStdErr\x12\x0c\n\x04\x62msg\x18\x01 \x01(\t\"`\n\x0fSystemStdErrMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\'\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x19.proto_types.SystemStdErr\",\n\x16SystemReportReturnCode\x12\x12\n\nreturncode\x18\x01 \x01(\x05\"t\n\x19SystemReportReturnCodeMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\x31\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32#.proto_types.SystemReportReturnCode\"\x19\n\nFormatting\x12\x0b\n\x03msg\x18\x01 \x01(\t\"\\\n\rFormattingMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12%\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x17.proto_types.Formatting\"\x13\n\x04Note\x12\x0b\n\x03msg\x18\x01 \x01(\t\"P\n\x07NoteMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\x1f\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x11.proto_types.Note\"\x19\n\nPrintEvent\x12\x0b\n\x03msg\x18\x01 \x01(\t\"\\\n\rPrintEventMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12%\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x17.proto_types.PrintEventb\x06proto3')
18
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0btypes.proto\x12\x0bproto_types\x1a\x1fgoogle/protobuf/timestamp.proto\"\x91\x02\n\tEventInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\x12\x0b\n\x03msg\x18\x03 \x01(\t\x12\r\n\x05level\x18\x04 \x01(\t\x12\x15\n\rinvocation_id\x18\x05 \x01(\t\x12\x0b\n\x03pid\x18\x06 \x01(\x05\x12\x0e\n\x06thread\x18\x07 \x01(\t\x12&\n\x02ts\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x05\x65xtra\x18\t \x03(\x0b\x32!.proto_types.EventInfo.ExtraEntry\x12\x10\n\x08\x63\x61tegory\x18\n \x01(\t\x1a,\n\nExtraEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"6\n\x0eGenericMessage\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\"d\n\x13\x42\x65haviorChangeEvent\x12\x11\n\tflag_name\x18\x01 \x01(\t\x12\x13\n\x0b\x66lag_source\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x10\n\x08\x64ocs_url\x18\x04 \x01(\t\"n\n\x16\x42\x65haviorChangeEventMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12.\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32 .proto_types.BehaviorChangeEvent\"1\n\x11RetryExternalCall\x12\x0f\n\x07\x61ttempt\x18\x01 \x01(\x05\x12\x0b\n\x03max\x18\x02 \x01(\x05\"j\n\x14RetryExternalCallMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12,\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x1e.proto_types.RetryExternalCall\"#\n\x14RecordRetryException\x12\x0b\n\x03\x65xc\x18\x01 \x01(\t\"p\n\x17RecordRetryExceptionMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12/\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32!.proto_types.RecordRetryException\"@\n\x13SystemCouldNotWrite\x12\x0c\n\x04path\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x0b\n\x03\x65xc\x18\x03 \x01(\t\"n\n\x16SystemCouldNotWriteMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12.\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32 .proto_types.SystemCouldNotWrite\"!\n\x12SystemExecutingCmd\x12\x0b\n\x03\x63md\x18\x01 \x03(\t\"l\n\x15SystemExecutingCmdMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12-\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x1f.proto_types.SystemExecutingCmd\"\x1c\n\x0cSystemStdOut\x12\x0c\n\x04\x62msg\x18\x01 \x01(\t\"`\n\x0fSystemStdOutMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\'\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x19.proto_types.SystemStdOut\"\x1c\n\x0cSystemStdErr\x12\x0c\n\x04\x62msg\x18\x01 \x01(\t\"`\n\x0fSystemStdErrMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\'\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x19.proto_types.SystemStdErr\",\n\x16SystemReportReturnCode\x12\x12\n\nreturncode\x18\x01 \x01(\x05\"t\n\x19SystemReportReturnCodeMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\x31\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32#.proto_types.SystemReportReturnCode\"\x19\n\nFormatting\x12\x0b\n\x03msg\x18\x01 \x01(\t\"\\\n\rFormattingMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12%\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x17.proto_types.Formatting\"\x13\n\x04Note\x12\x0b\n\x03msg\x18\x01 \x01(\t\"P\n\x07NoteMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12\x1f\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x11.proto_types.Note\"\x19\n\nPrintEvent\x12\x0b\n\x03msg\x18\x01 \x01(\t\"\\\n\rPrintEventMsg\x12$\n\x04info\x18\x01 \x01(\x0b\x32\x16.proto_types.EventInfo\x12%\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x17.proto_types.PrintEventb\x06proto3')
19
19
 
20
20
  _globals = globals()
21
21
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -30,48 +30,48 @@ if _descriptor._USE_C_DESCRIPTORS == False:
30
30
  _globals['_EVENTINFO_EXTRAENTRY']._serialized_end=335
31
31
  _globals['_GENERICMESSAGE']._serialized_start=337
32
32
  _globals['_GENERICMESSAGE']._serialized_end=391
33
- _globals['_BEHAVIORDEPRECATIONEVENT']._serialized_start=394
34
- _globals['_BEHAVIORDEPRECATIONEVENT']._serialized_end=536
35
- _globals['_BEHAVIORDEPRECATIONEVENTMSG']._serialized_start=538
36
- _globals['_BEHAVIORDEPRECATIONEVENTMSG']._serialized_end=658
37
- _globals['_RETRYEXTERNALCALL']._serialized_start=660
38
- _globals['_RETRYEXTERNALCALL']._serialized_end=709
39
- _globals['_RETRYEXTERNALCALLMSG']._serialized_start=711
40
- _globals['_RETRYEXTERNALCALLMSG']._serialized_end=817
41
- _globals['_RECORDRETRYEXCEPTION']._serialized_start=819
42
- _globals['_RECORDRETRYEXCEPTION']._serialized_end=854
43
- _globals['_RECORDRETRYEXCEPTIONMSG']._serialized_start=856
44
- _globals['_RECORDRETRYEXCEPTIONMSG']._serialized_end=968
45
- _globals['_SYSTEMCOULDNOTWRITE']._serialized_start=970
46
- _globals['_SYSTEMCOULDNOTWRITE']._serialized_end=1034
47
- _globals['_SYSTEMCOULDNOTWRITEMSG']._serialized_start=1036
48
- _globals['_SYSTEMCOULDNOTWRITEMSG']._serialized_end=1146
49
- _globals['_SYSTEMEXECUTINGCMD']._serialized_start=1148
50
- _globals['_SYSTEMEXECUTINGCMD']._serialized_end=1181
51
- _globals['_SYSTEMEXECUTINGCMDMSG']._serialized_start=1183
52
- _globals['_SYSTEMEXECUTINGCMDMSG']._serialized_end=1291
53
- _globals['_SYSTEMSTDOUT']._serialized_start=1293
54
- _globals['_SYSTEMSTDOUT']._serialized_end=1321
55
- _globals['_SYSTEMSTDOUTMSG']._serialized_start=1323
56
- _globals['_SYSTEMSTDOUTMSG']._serialized_end=1419
57
- _globals['_SYSTEMSTDERR']._serialized_start=1421
58
- _globals['_SYSTEMSTDERR']._serialized_end=1449
59
- _globals['_SYSTEMSTDERRMSG']._serialized_start=1451
60
- _globals['_SYSTEMSTDERRMSG']._serialized_end=1547
61
- _globals['_SYSTEMREPORTRETURNCODE']._serialized_start=1549
62
- _globals['_SYSTEMREPORTRETURNCODE']._serialized_end=1593
63
- _globals['_SYSTEMREPORTRETURNCODEMSG']._serialized_start=1595
64
- _globals['_SYSTEMREPORTRETURNCODEMSG']._serialized_end=1711
65
- _globals['_FORMATTING']._serialized_start=1713
66
- _globals['_FORMATTING']._serialized_end=1738
67
- _globals['_FORMATTINGMSG']._serialized_start=1740
68
- _globals['_FORMATTINGMSG']._serialized_end=1832
69
- _globals['_NOTE']._serialized_start=1834
70
- _globals['_NOTE']._serialized_end=1853
71
- _globals['_NOTEMSG']._serialized_start=1855
72
- _globals['_NOTEMSG']._serialized_end=1935
73
- _globals['_PRINTEVENT']._serialized_start=1937
74
- _globals['_PRINTEVENT']._serialized_end=1962
75
- _globals['_PRINTEVENTMSG']._serialized_start=1964
76
- _globals['_PRINTEVENTMSG']._serialized_end=2056
33
+ _globals['_BEHAVIORCHANGEEVENT']._serialized_start=393
34
+ _globals['_BEHAVIORCHANGEEVENT']._serialized_end=493
35
+ _globals['_BEHAVIORCHANGEEVENTMSG']._serialized_start=495
36
+ _globals['_BEHAVIORCHANGEEVENTMSG']._serialized_end=605
37
+ _globals['_RETRYEXTERNALCALL']._serialized_start=607
38
+ _globals['_RETRYEXTERNALCALL']._serialized_end=656
39
+ _globals['_RETRYEXTERNALCALLMSG']._serialized_start=658
40
+ _globals['_RETRYEXTERNALCALLMSG']._serialized_end=764
41
+ _globals['_RECORDRETRYEXCEPTION']._serialized_start=766
42
+ _globals['_RECORDRETRYEXCEPTION']._serialized_end=801
43
+ _globals['_RECORDRETRYEXCEPTIONMSG']._serialized_start=803
44
+ _globals['_RECORDRETRYEXCEPTIONMSG']._serialized_end=915
45
+ _globals['_SYSTEMCOULDNOTWRITE']._serialized_start=917
46
+ _globals['_SYSTEMCOULDNOTWRITE']._serialized_end=981
47
+ _globals['_SYSTEMCOULDNOTWRITEMSG']._serialized_start=983
48
+ _globals['_SYSTEMCOULDNOTWRITEMSG']._serialized_end=1093
49
+ _globals['_SYSTEMEXECUTINGCMD']._serialized_start=1095
50
+ _globals['_SYSTEMEXECUTINGCMD']._serialized_end=1128
51
+ _globals['_SYSTEMEXECUTINGCMDMSG']._serialized_start=1130
52
+ _globals['_SYSTEMEXECUTINGCMDMSG']._serialized_end=1238
53
+ _globals['_SYSTEMSTDOUT']._serialized_start=1240
54
+ _globals['_SYSTEMSTDOUT']._serialized_end=1268
55
+ _globals['_SYSTEMSTDOUTMSG']._serialized_start=1270
56
+ _globals['_SYSTEMSTDOUTMSG']._serialized_end=1366
57
+ _globals['_SYSTEMSTDERR']._serialized_start=1368
58
+ _globals['_SYSTEMSTDERR']._serialized_end=1396
59
+ _globals['_SYSTEMSTDERRMSG']._serialized_start=1398
60
+ _globals['_SYSTEMSTDERRMSG']._serialized_end=1494
61
+ _globals['_SYSTEMREPORTRETURNCODE']._serialized_start=1496
62
+ _globals['_SYSTEMREPORTRETURNCODE']._serialized_end=1540
63
+ _globals['_SYSTEMREPORTRETURNCODEMSG']._serialized_start=1542
64
+ _globals['_SYSTEMREPORTRETURNCODEMSG']._serialized_end=1658
65
+ _globals['_FORMATTING']._serialized_start=1660
66
+ _globals['_FORMATTING']._serialized_end=1685
67
+ _globals['_FORMATTINGMSG']._serialized_start=1687
68
+ _globals['_FORMATTINGMSG']._serialized_end=1779
69
+ _globals['_NOTE']._serialized_start=1781
70
+ _globals['_NOTE']._serialized_end=1800
71
+ _globals['_NOTEMSG']._serialized_start=1802
72
+ _globals['_NOTEMSG']._serialized_end=1882
73
+ _globals['_PRINTEVENT']._serialized_start=1884
74
+ _globals['_PRINTEVENT']._serialized_end=1909
75
+ _globals['_PRINTEVENTMSG']._serialized_start=1911
76
+ _globals['_PRINTEVENTMSG']._serialized_end=2003
77
77
  # @@protoc_insertion_point(module_scope)
@@ -1,8 +1,13 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ if TYPE_CHECKING:
4
+ from dbt_common.clients._jinja_blocks import Tag, TagIterator
5
+
1
6
  from dbt_common.exceptions import CompilationError
2
7
 
3
8
 
4
9
  class BlockDefinitionNotAtTopError(CompilationError):
5
- def __init__(self, tag_parser, tag_start) -> None:
10
+ def __init__(self, tag_parser: "TagIterator", tag_start: int) -> None:
6
11
  self.tag_parser = tag_parser
7
12
  self.tag_start = tag_start
8
13
  super().__init__(msg=self.get_message())
@@ -31,7 +36,7 @@ class MissingCloseTagError(CompilationError):
31
36
 
32
37
 
33
38
  class MissingControlFlowStartTagError(CompilationError):
34
- def __init__(self, tag, expected_tag: str, tag_parser) -> None:
39
+ def __init__(self, tag: "Tag", expected_tag: str, tag_parser: "TagIterator") -> None:
35
40
  self.tag = tag
36
41
  self.expected_tag = expected_tag
37
42
  self.tag_parser = tag_parser
@@ -47,7 +52,7 @@ class MissingControlFlowStartTagError(CompilationError):
47
52
 
48
53
 
49
54
  class NestedTagsError(CompilationError):
50
- def __init__(self, outer, inner) -> None:
55
+ def __init__(self, outer: "Tag", inner: "Tag") -> None:
51
56
  self.outer = outer
52
57
  self.inner = inner
53
58
  super().__init__(msg=self.get_message())
@@ -62,7 +67,7 @@ class NestedTagsError(CompilationError):
62
67
 
63
68
 
64
69
  class UnexpectedControlFlowEndTagError(CompilationError):
65
- def __init__(self, tag, expected_tag: str, tag_parser) -> None:
70
+ def __init__(self, tag: "Tag", expected_tag: str, tag_parser: "TagIterator") -> None:
66
71
  self.tag = tag
67
72
  self.expected_tag = expected_tag
68
73
  self.tag_parser = tag_parser
dbt_common/record.py CHANGED
@@ -29,8 +29,14 @@ class Record:
29
29
 
30
30
  def to_dict(self) -> Dict[str, Any]:
31
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
32
+ "params": self.params._to_dict()
33
+ if hasattr(self.params, "_to_dict")
34
+ else dataclasses.asdict(self.params),
35
+ "result": self.result._to_dict()
36
+ if hasattr(self.result, "_to_dict")
37
+ else dataclasses.asdict(self.result)
38
+ if self.result is not None
39
+ else None,
34
40
  }
35
41
 
36
42
  @classmethod
dbt_common/semver.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from dataclasses import dataclass
2
2
  import re
3
- from typing import Iterable, List, Union
3
+ from typing import Any, Iterable, List, Union
4
4
 
5
5
  import dbt_common.exceptions.base
6
6
  from dbt_common.exceptions import VersionsNotCompatibleError
@@ -67,9 +67,9 @@ $
67
67
  _VERSION_REGEX = re.compile(_VERSION_REGEX_PAT_STR, re.VERBOSE)
68
68
 
69
69
 
70
- def _cmp(a, b) -> int:
70
+ def _cmp(a: Any, b: Any) -> int:
71
71
  """Return negative if a<b, zero if a==b, positive if a>b."""
72
- return (a > b) - (a < b)
72
+ return int((a > b) - (a < b))
73
73
 
74
74
 
75
75
  @dataclass
@@ -102,7 +102,9 @@ class VersionSpecifier(VersionSpecification):
102
102
 
103
103
  matched = {k: v for k, v in match.groupdict().items() if v is not None}
104
104
 
105
- return cls.from_dict(matched)
105
+ spec = cls.from_dict(matched)
106
+ assert isinstance(spec, VersionSpecifier)
107
+ return spec
106
108
 
107
109
  def __str__(self) -> str:
108
110
  return self.to_version_string()
@@ -198,10 +200,11 @@ class VersionSpecifier(VersionSpecification):
198
200
  def __gt__(self, other: "VersionSpecifier") -> bool:
199
201
  return self.compare(other) == 1
200
202
 
201
- def __eq___(self, other: "VersionSpecifier") -> bool:
203
+ def __eq__(self, other: object) -> bool:
204
+ assert isinstance(other, VersionSpecifier)
202
205
  return self.compare(other) == 0
203
206
 
204
- def __cmp___(self, other: "VersionSpecifier") -> int:
207
+ def __cmp__(self, other: "VersionSpecifier") -> int:
205
208
  return self.compare(other)
206
209
 
207
210
  @property
@@ -221,8 +224,8 @@ class VersionSpecifier(VersionSpecification):
221
224
  return self.matcher == Matchers.EXACT
222
225
 
223
226
  @classmethod
224
- def _nat_cmp(cls, a, b) -> int:
225
- def cmp_prerelease_tag(a, b):
227
+ def _nat_cmp(cls, a: str, b: str) -> int:
228
+ def cmp_prerelease_tag(a: Union[str, int], b: Union[str, int]) -> int:
226
229
  if isinstance(a, int) and isinstance(b, int):
227
230
  return _cmp(a, b)
228
231
  elif isinstance(a, int):
@@ -234,10 +237,10 @@ class VersionSpecifier(VersionSpecification):
234
237
 
235
238
  a, b = a or "", b or ""
236
239
  a_parts, b_parts = a.split("."), b.split(".")
237
- a_parts = [int(x) if re.match(r"^\d+$", x) else x for x in a_parts]
238
- b_parts = [int(x) if re.match(r"^\d+$", x) else x for x in b_parts]
239
- for sub_a, sub_b in zip(a_parts, b_parts):
240
- cmp_result = cmp_prerelease_tag(sub_a, sub_b)
240
+ a_parts_2 = [int(x) if re.match(r"^\d+$", x) else x for x in a_parts]
241
+ b_parts_2 = [int(x) if re.match(r"^\d+$", x) else x for x in b_parts]
242
+ for sub_a, sub_b in zip(a_parts_2, b_parts_2):
243
+ cmp_result = cmp_prerelease_tag(sub_a, sub_b) # type: ignore
241
244
  if cmp_result != 0:
242
245
  return cmp_result
243
246
  else:
@@ -249,13 +252,15 @@ class VersionRange:
249
252
  start: VersionSpecifier
250
253
  end: VersionSpecifier
251
254
 
252
- def _try_combine_exact(self, a, b):
255
+ def _try_combine_exact(self, a: VersionSpecifier, b: VersionSpecifier) -> VersionSpecifier:
253
256
  if a.compare(b) == 0:
254
257
  return a
255
258
  else:
256
259
  raise VersionsNotCompatibleError()
257
260
 
258
- def _try_combine_lower_bound_with_exact(self, lower, exact):
261
+ def _try_combine_lower_bound_with_exact(
262
+ self, lower: VersionSpecifier, exact: VersionSpecifier
263
+ ) -> VersionSpecifier:
259
264
  comparison = lower.compare(exact)
260
265
 
261
266
  if comparison < 0 or (comparison == 0 and lower.matcher == Matchers.GREATER_THAN_OR_EQUAL):
@@ -263,7 +268,9 @@ class VersionRange:
263
268
 
264
269
  raise VersionsNotCompatibleError()
265
270
 
266
- def _try_combine_lower_bound(self, a, b):
271
+ def _try_combine_lower_bound(
272
+ self, a: VersionSpecifier, b: VersionSpecifier
273
+ ) -> VersionSpecifier:
267
274
  if b.is_unbounded:
268
275
  return a
269
276
  elif a.is_unbounded:
@@ -280,10 +287,12 @@ class VersionRange:
280
287
  elif a.is_exact:
281
288
  return self._try_combine_lower_bound_with_exact(b, a)
282
289
 
283
- elif b.is_exact:
290
+ else:
284
291
  return self._try_combine_lower_bound_with_exact(a, b)
285
292
 
286
- def _try_combine_upper_bound_with_exact(self, upper, exact):
293
+ def _try_combine_upper_bound_with_exact(
294
+ self, upper: VersionSpecifier, exact: VersionSpecifier
295
+ ) -> VersionSpecifier:
287
296
  comparison = upper.compare(exact)
288
297
 
289
298
  if comparison > 0 or (comparison == 0 and upper.matcher == Matchers.LESS_THAN_OR_EQUAL):
@@ -291,7 +300,9 @@ class VersionRange:
291
300
 
292
301
  raise VersionsNotCompatibleError()
293
302
 
294
- def _try_combine_upper_bound(self, a, b):
303
+ def _try_combine_upper_bound(
304
+ self, a: VersionSpecifier, b: VersionSpecifier
305
+ ) -> VersionSpecifier:
295
306
  if b.is_unbounded:
296
307
  return a
297
308
  elif a.is_unbounded:
@@ -308,15 +319,14 @@ class VersionRange:
308
319
  elif a.is_exact:
309
320
  return self._try_combine_upper_bound_with_exact(b, a)
310
321
 
311
- elif b.is_exact:
322
+ else:
312
323
  return self._try_combine_upper_bound_with_exact(a, b)
313
324
 
314
- def reduce(self, other):
325
+ def reduce(self, other: "VersionRange") -> "VersionRange":
315
326
  start = None
316
327
 
317
328
  if self.start.is_exact and other.start.is_exact:
318
329
  start = end = self._try_combine_exact(self.start, other.start)
319
-
320
330
  else:
321
331
  start = self._try_combine_lower_bound(self.start, other.start)
322
332
  end = self._try_combine_upper_bound(self.end, other.end)
@@ -326,7 +336,7 @@ class VersionRange:
326
336
 
327
337
  return VersionRange(start=start, end=end)
328
338
 
329
- def __str__(self):
339
+ def __str__(self) -> str:
330
340
  result = []
331
341
 
332
342
  if self.start.is_unbounded and self.end.is_unbounded:
@@ -340,7 +350,7 @@ class VersionRange:
340
350
 
341
351
  return ", ".join(result)
342
352
 
343
- def to_version_string_pair(self):
353
+ def to_version_string_pair(self) -> List[str]:
344
354
  to_return = []
345
355
 
346
356
  if not self.start.is_unbounded:
@@ -353,7 +363,7 @@ class VersionRange:
353
363
 
354
364
 
355
365
  class UnboundedVersionSpecifier(VersionSpecifier):
356
- def __init__(self, *args, **kwargs) -> None:
366
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
357
367
  super().__init__(
358
368
  matcher=Matchers.EXACT, major=None, minor=None, patch=None, prerelease=None, build=None
359
369
  )
@@ -418,7 +428,7 @@ def reduce_versions(*args: Union[VersionSpecifier, VersionRange, str]) -> Versio
418
428
  return to_return
419
429
 
420
430
 
421
- def versions_compatible(*args) -> bool:
431
+ def versions_compatible(*args: Union[VersionSpecifier, VersionRange, str]) -> bool:
422
432
  if len(args) == 1:
423
433
  return True
424
434
 
@@ -429,7 +439,9 @@ def versions_compatible(*args) -> bool:
429
439
  return False
430
440
 
431
441
 
432
- def find_possible_versions(requested_range, available_versions: Iterable[str]):
442
+ def find_possible_versions(
443
+ requested_range: VersionRange, available_versions: Iterable[str]
444
+ ) -> List[str]:
433
445
  possible_versions = []
434
446
 
435
447
  for version_string in available_versions:
@@ -443,7 +455,7 @@ def find_possible_versions(requested_range, available_versions: Iterable[str]):
443
455
 
444
456
 
445
457
  def resolve_to_specific_version(
446
- requested_range, available_versions: Iterable[str]
458
+ requested_range: VersionRange, available_versions: Iterable[str]
447
459
  ) -> Optional[str]:
448
460
  max_version = None
449
461
  max_version_string = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: dbt-common
3
- Version: 1.8.0
3
+ Version: 1.9.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,27 +1,27 @@
1
- dbt_common/__about__.py,sha256=J9Md0egz2m3v0DHzraSTc3Ep1dKM1wRt2RZSVicTmqM,18
1
+ dbt_common/__about__.py,sha256=cXjavBUobbggOyp9SOIeDA3iCRdu2Hzw1qBttGe-RYs,18
2
2
  dbt_common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- dbt_common/behavior_flags.py,sha256=fkk9snLsKH4mM4PklQSjjk9heuP7NvB4zFndgQNWM6E,4163
3
+ dbt_common/behavior_flags.py,sha256=GkrXvJ-Q7P73O0XcsIxyYeyiUAOe5E5DdNKIh6x3unE,4809
4
4
  dbt_common/constants.py,sha256=-Y5DIL1SDPQWtlCNizXRYxFgbx1D7LaLs1ysamvGMRk,278
5
5
  dbt_common/context.py,sha256=rk4EYBU4SpDXRhqbSvDTJwojilxPSoaiEdOxkXow_BU,2549
6
6
  dbt_common/dataclass_schema.py,sha256=u2S0dxwxIghv8RMqC91HlWZJVxmsC_844yZQaGyOwdY,5563
7
7
  dbt_common/helper_types.py,sha256=FWJGPmp7Qp2iToHyI4uvhkBbu_d1tl2_oF-obi98_N4,3917
8
8
  dbt_common/invocation.py,sha256=2ZchIr4Wq7NwtAjjB-mxHP9ITD6-r45jEq4Zooso0gc,210
9
9
  dbt_common/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- dbt_common/record.py,sha256=og-9SZhRINqW6jnqLdf3CTVKvUPdKldi52oFaa2-QRE,12658
11
- dbt_common/semver.py,sha256=NNG0CVJosfwSVQ8WKKGtK_qzinbEy-OEn_jih36Y0Co,14364
10
+ dbt_common/record.py,sha256=vItvHEF2yl_NbvuaIXYHo-q6v0LUpCxR2twcTMVCeQ0,12698
11
+ dbt_common/semver.py,sha256=Znewz6tc_NBpXr4mZf20bK_RayPL4ODrnxDbkUZrrRo,15034
12
12
  dbt_common/tests.py,sha256=6lC_JuRtoYO6cbAF8-R5aTM4HtQiM_EH8X5m_97duGY,315
13
13
  dbt_common/ui.py,sha256=rc2TEM29raBFc_LXcg901pMDD07C2ohwp9qzkE-7pBY,2567
14
14
  dbt_common/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  dbt_common/clients/_jinja_blocks.py,sha256=xoJK9Y0F93U2PKfT_3SJbBopCGYCtl7LiwKuylXnrEE,12947
16
16
  dbt_common/clients/agate_helper.py,sha256=anKKgKV5PSnFRuFeBwRMdHK3JCaQoUqB2ZXHD0su0Wo,9123
17
- dbt_common/clients/jinja.py,sha256=yB7fv_Y5LKnj-3BKl3KCFDQYSFEEvn5YCyyu0vBsFR8,18495
17
+ dbt_common/clients/jinja.py,sha256=-eDrUnhH3nxOD0xu81jlweJ_iJqIWdJpYSHZBB27xXo,19682
18
18
  dbt_common/clients/system.py,sha256=aoUBtOuXVmkOyj6IhhJ3Y4a7JFzPO2F_zKyOtz3xy44,23932
19
19
  dbt_common/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  dbt_common/contracts/constraints.py,sha256=_f1q3Rkcg2UwA7zI5XBbUMXnPUg6pw17UC7l1HyhyQM,1352
21
21
  dbt_common/contracts/metadata.py,sha256=K_M06Rue0wmrQhFP_mq3uvQszq10CIt93oGiAVgbRfE,1293
22
22
  dbt_common/contracts/util.py,sha256=_-vtcI6ZGmYVgrlxOw4M3YuH34Ncx-oKdKg7TV0pV78,916
23
23
  dbt_common/contracts/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- dbt_common/contracts/config/base.py,sha256=JR9a7FdboXugexqXmab82TabKyRoRW8OPGn2_vVlS6g,8492
24
+ dbt_common/contracts/config/base.py,sha256=vLkmnwWUGazIpUuUYqdnTrpBmFLJQ9hantsIv7T0GoU,12315
25
25
  dbt_common/contracts/config/materialization.py,sha256=rahC72qZ0-jB8oPwxyPooZXc5NJ-smg74g2HnGOMj34,256
26
26
  dbt_common/contracts/config/metadata.py,sha256=X47-tEA8q2ZfSMcYv0godUwTSVjt8NI77tD4NqdgM0c,1877
27
27
  dbt_common/contracts/config/properties.py,sha256=gWt6xsP4rVOqRKhmagiUhWnDynzD9mykfMYMTviwpEU,2281
@@ -37,16 +37,16 @@ dbt_common/events/functions.py,sha256=K-R-FBTeO03U51gtMBu1EUcNsIAsgw_e5spWxLJ44V
37
37
  dbt_common/events/helpers.py,sha256=CfsWwNDjsLJkPIgOtAfuLEnZ3rGUKeYsH8aDtCW12OA,410
38
38
  dbt_common/events/interfaces.py,sha256=hEDeDoB0FW2RYHVZBG7gebEt_mUVBzkn1yPubpaxs-s,147
39
39
  dbt_common/events/logger.py,sha256=mAUNLZlIIOl3T2u7KOe8FF_deTNNe1CRJqmkPw4YH1U,6728
40
- dbt_common/events/types.proto,sha256=VflTmP9HUsatIi7xC3GXk2eJHsrS5041m5qpA7idU6c,2335
41
- dbt_common/events/types.py,sha256=aQ9TSsOyVBq2LMdMQQVktGww0qzH4PpR4AHArMQWtT8,5049
42
- dbt_common/events/types_pb2.py,sha256=0kIhc1xWqhF3DtJhaAdN_8AjxzxkFcVzE53Dd5mdS5Q,7277
40
+ dbt_common/events/types.proto,sha256=Ujl0O-X-pat8vlo2C0TMH1LZqa8EP_9f8k2TjbFuCV8,2276
41
+ dbt_common/events/types.py,sha256=MXCmG7qaj7hLbDZjjazjWftPTfoLjhNPATPMirO0DvU,4475
42
+ dbt_common/events/types_pb2.py,sha256=oFjR6pFqz3_Nk8wWIrVB9y6inNTxnj-CSGr2g8dnFz4,7167
43
43
  dbt_common/exceptions/__init__.py,sha256=X_Uw7BxOzXev_9JMYfs5Cm-_i_Qf2PJim8_-dDJI7Y8,361
44
44
  dbt_common/exceptions/base.py,sha256=d6lsA8sLqR6_BERowm91Mrs1ZwrEOeT8WQKWg4nPSPA,7750
45
45
  dbt_common/exceptions/cache.py,sha256=0z4fBcdNZMAR41YbPRo2GN0__xAMaYs8Uc-t3hjmVio,2532
46
46
  dbt_common/exceptions/connection.py,sha256=rXLJXUdLhyXP3CUUyiqWN2DDO5-0Pn1ChX3OIR7pxKk,176
47
47
  dbt_common/exceptions/contracts.py,sha256=i2PKRqda1Pq_Sro9FA22W7FTGklhBAGl6__nimR5_qI,527
48
48
  dbt_common/exceptions/events.py,sha256=j83szhbqmK3ITZR_xwA2dYTNaPcGF_lN_kQar6dQgjQ,317
49
- dbt_common/exceptions/jinja.py,sha256=PzVUB1MFf8x81bQHTwFIGw3PyrGZzWYw04eotI4CqtI,3124
49
+ dbt_common/exceptions/jinja.py,sha256=EfqWKLePqPIfzFjn1-Sn_lEp3fttzhzwogo0I-McAdc,3321
50
50
  dbt_common/exceptions/macros.py,sha256=2nujJrtpWHnhBwcyhcOmeVaEzILh3W9gtyP6vVpkA0o,3301
51
51
  dbt_common/exceptions/system.py,sha256=scoKnSx2frTFCrfk2cH0g-z3MuzE-SEBXFC9P-jzB2s,1603
52
52
  dbt_common/utils/__init__.py,sha256=8PNb_A9zm2YfYMa0GsM-pAyJy3Iu0FUtWKvCs8kFhD0,549
@@ -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.8.0.dist-info/METADATA,sha256=9YS6_dZQSWe_FuiBUu-lYqVdhptGjdU-na84EExK72g,5298
61
- dbt_common-1.8.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
62
- dbt_common-1.8.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
63
- dbt_common-1.8.0.dist-info/RECORD,,
60
+ dbt_common-1.9.0.dist-info/METADATA,sha256=gJ4sX5mtKWkJP66WbImh-5UrFsb5Mo3KQkoGkzbbsAQ,5298
61
+ dbt_common-1.9.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
62
+ dbt_common-1.9.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
63
+ dbt_common-1.9.0.dist-info/RECORD,,