Skip to content

Commit

Permalink
Add behavior flags to jinja context (#306)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikealfare authored Sep 12, 2024
1 parent efed8a9 commit 97a6687
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 4 deletions.
9 changes: 5 additions & 4 deletions dbt/adapters/base/impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
BaseConnectionManager,
Connection,
)
from dbt.adapters.base.meta import AdapterMeta, available
from dbt.adapters.base.meta import AdapterMeta, available, available_property
from dbt.adapters.base.relation import (
BaseRelation,
ComponentName,
Expand Down Expand Up @@ -272,7 +272,8 @@ def __init__(self, config, mp_context: SpawnContext) -> None:
self.connections = self.ConnectionManager(config, mp_context)
self._macro_resolver: Optional[MacroResolverProtocol] = None
self._macro_context_generator: Optional[MacroContextGeneratorCallable] = None
self.behavior = [] # this will be updated to include global behavior flags once they exist
# this will be updated to include global behavior flags once they exist
self.behavior = [] # type: ignore

###
# Methods to set / access a macro resolver
Expand All @@ -293,11 +294,11 @@ def set_macro_context_generator(
) -> None:
self._macro_context_generator = macro_context_generator

@property
@available_property
def behavior(self) -> Behavior:
return self._behavior

@behavior.setter
@behavior.setter # type: ignore
def behavior(self, flags: List[BehaviorFlag]) -> None:
flags.extend(self._behavior_flags)
try:
Expand Down
19 changes: 19 additions & 0 deletions dbt/adapters/base/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,25 @@ def parse_list(self, func: Callable) -> Callable:
available = _Available()


class available_property(property):
"""
This supports making dynamic properties (`@property`) available in the jinja context.
We use `@available` to make methods available in the jinja context, but this mechanism relies on the method being callable.
Intuitively, we should be able to use both `@available` and `@property` to create a dynamic property that's available in the jinja context.
Using the `@property` decorator as the inner decorator supplies `@available` with something that is not callable.
Instead of returning the method, `@property` returns the value itself, not the method that is called to create the value.
Using the `@available` decorator as the inner decorator adds `_is_available_ = True` to the function.
However, when the `@property` decorator executes, it returns a `property` object which does not have the `_is_available_` attribute.
This decorator solves this problem by simply adding `_is_available_ = True` as an attribute on the `property` built-in.
"""

_is_available_ = True


class AdapterMeta(abc.ABCMeta):
_available_: FrozenSet[str]
_parse_replacements_: Dict[str, Callable]
Expand Down

0 comments on commit 97a6687

Please sign in to comment.