Skip to content

Commit

Permalink
Feature: Add set/zip function to contexts (#5107)
Browse files Browse the repository at this point in the history
* add set function to contexts

* add zip function to contexts

* add changelog

* add try_ equivalents

* remove defaults

* add tests

* update tests
  • Loading branch information
jeremyyeo authored May 13, 2022
1 parent 72c17c4 commit 7e43f36
Show file tree
Hide file tree
Showing 4 changed files with 391 additions and 216 deletions.
7 changes: 7 additions & 0 deletions .changes/unreleased/Features-20220423-231756.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
kind: Features
body: Add set and zip function to contexts
time: 2022-04-23T23:17:56.851793+12:00
custom:
Author: jeremyyeo
Issue: "2345"
PR: "5107"
93 changes: 91 additions & 2 deletions core/dbt/context/base.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import json
import os
from typing import Any, Dict, NoReturn, Optional, Mapping
from typing import Any, Dict, NoReturn, Optional, Mapping, Iterable, Set

from dbt import flags
from dbt import tracking
from dbt.clients.jinja import get_rendered
from dbt.clients.yaml_helper import yaml, safe_load, SafeLoader, Loader, Dumper # noqa: F401
from dbt.contracts.graph.compiled import CompiledResource
from dbt.exceptions import (
raise_compiler_error,
CompilationException,
MacroReturn,
raise_compiler_error,
raise_parsing_error,
disallow_secret_env_var,
)
Expand Down Expand Up @@ -482,6 +483,94 @@ def toyaml(
except (ValueError, yaml.YAMLError):
return default

@contextmember("set")
@staticmethod
def _set(value: Iterable[Any], default: Any = None) -> Optional[Set[Any]]:
"""The `set` context method can be used to convert any iterable
to a sequence of iterable elements that are unique (a set).
:param value: The iterable
:param default: A default value to return if the `value` argument
is not an iterable
Usage:
{% set my_list = [1, 2, 2, 3] %}
{% set my_set = set(my_list) %}
{% do log(my_set) %} {# {1, 2, 3} #}
"""
try:
return set(value)
except TypeError:
return default

@contextmember
@staticmethod
def try_set(value: Iterable[Any]) -> Set[Any]:
"""The `try_set` context method can be used to convert any iterable
to a sequence of iterable elements that are unique (a set). The
difference to the `set` context method is that the `try_set` method
will raise an exception on a TypeError.
:param value: The iterable
:param default: A default value to return if the `value` argument
is not an iterable
Usage:
{% set my_list = [1, 2, 2, 3] %}
{% set my_set = try_set(my_list) %}
{% do log(my_set) %} {# {1, 2, 3} #}
"""
try:
return set(value)
except TypeError as e:
raise CompilationException(e)

@contextmember("zip")
@staticmethod
def _zip(*args: Iterable[Any], default: Any = None) -> Optional[Iterable[Any]]:
"""The `try_zip` context method can be used to used to return
an iterator of tuples, where the i-th tuple contains the i-th
element from each of the argument iterables.
:param *args: Any number of iterables
:param default: A default value to return if `*args` is not
iterable
Usage:
{% set my_list_a = [1, 2] %}
{% set my_list_b = ['alice', 'bob'] %}
{% set my_zip = zip(my_list_a, my_list_b) | list %}
{% do log(my_set) %} {# [(1, 'alice'), (2, 'bob')] #}
"""
try:
return zip(*args)
except TypeError:
return default

@contextmember
@staticmethod
def try_zip(*args: Iterable[Any]) -> Iterable[Any]:
"""The `try_zip` context method can be used to used to return
an iterator of tuples, where the i-th tuple contains the i-th
element from each of the argument iterables. The difference to the
`zip` context method is that the `try_zip` method will raise an
exception on a TypeError.
:param *args: Any number of iterables
:param default: A default value to return if `*args` is not
iterable
Usage:
{% set my_list_a = [1, 2] %}
{% set my_list_b = ['alice', 'bob'] %}
{% set my_zip = try_zip(my_list_a, my_list_b) | list %}
{% do log(my_set) %} {# [(1, 'alice'), (2, 'bob')] #}
"""
try:
return zip(*args)
except TypeError as e:
raise CompilationException(e)

@contextmember
@staticmethod
def log(msg: str, info: bool = False) -> str:
Expand Down
Loading

0 comments on commit 7e43f36

Please sign in to comment.