generator.lkml_update

An updated lkml parser to handle explore queries.

 1"""An updated lkml parser to handle explore queries."""
 2
 3from typing import List, Union
 4
 5from lkml.keys import KEYS_WITH_NAME_FIELDS
 6from lkml.simple import DictParser
 7from lkml.tree import BlockNode, DocumentNode, ListNode, PairNode
 8
 9
10def dump(obj: dict) -> str:
11    """Dump an object as LookML."""
12    parser = UpdatedDictParser()
13    tree: DocumentNode = parser.parse(obj)
14    return str(tree)
15
16
17class UpdatedDictParser(DictParser):
18    """An updated DictParser that properly handles queries."""
19
20    def parse_any(
21        self, key: str, value: Union[str, list, tuple, dict]
22    ) -> Union[
23        List[Union[BlockNode, ListNode, PairNode]], BlockNode, ListNode, PairNode
24    ]:
25        """Dynamically serializes a Python object based on its type.
26
27        Args:
28            key: A LookML field type (e.g. "suggestions" or "hidden")
29            value: A string, tuple, or list to serialize
30        Raises:
31            TypeError: If input value is not of a valid type
32        Returns:
33            A generator of serialized string chunks
34        """
35        if isinstance(value, str):
36            return self.parse_pair(key, value)
37        elif isinstance(value, (list, tuple)):
38            if self.is_plural_key(key) and not self.parent_key == "query":
39                # See https://github.com/joshtemple/lkml/issues/53
40                # We check that the parent is not a query to ensure the
41                # query fields don't get unnested
42                return self.expand_list(key, value)
43            else:
44                return self.parse_list(key, value)
45        elif isinstance(value, dict):
46            if key in KEYS_WITH_NAME_FIELDS or "name" not in value.keys():
47                name = None
48            else:
49                name = value.pop("name")
50            return self.parse_block(key, value, name)
51        else:
52            raise TypeError("Value must be a string, list, tuple, or dict.")
def dump(obj: dict) -> str:
11def dump(obj: dict) -> str:
12    """Dump an object as LookML."""
13    parser = UpdatedDictParser()
14    tree: DocumentNode = parser.parse(obj)
15    return str(tree)

Dump an object as LookML.

class UpdatedDictParser(lkml.simple.DictParser):
18class UpdatedDictParser(DictParser):
19    """An updated DictParser that properly handles queries."""
20
21    def parse_any(
22        self, key: str, value: Union[str, list, tuple, dict]
23    ) -> Union[
24        List[Union[BlockNode, ListNode, PairNode]], BlockNode, ListNode, PairNode
25    ]:
26        """Dynamically serializes a Python object based on its type.
27
28        Args:
29            key: A LookML field type (e.g. "suggestions" or "hidden")
30            value: A string, tuple, or list to serialize
31        Raises:
32            TypeError: If input value is not of a valid type
33        Returns:
34            A generator of serialized string chunks
35        """
36        if isinstance(value, str):
37            return self.parse_pair(key, value)
38        elif isinstance(value, (list, tuple)):
39            if self.is_plural_key(key) and not self.parent_key == "query":
40                # See https://github.com/joshtemple/lkml/issues/53
41                # We check that the parent is not a query to ensure the
42                # query fields don't get unnested
43                return self.expand_list(key, value)
44            else:
45                return self.parse_list(key, value)
46        elif isinstance(value, dict):
47            if key in KEYS_WITH_NAME_FIELDS or "name" not in value.keys():
48                name = None
49            else:
50                name = value.pop("name")
51            return self.parse_block(key, value, name)
52        else:
53            raise TypeError("Value must be a string, list, tuple, or dict.")

An updated DictParser that properly handles queries.

def parse_any( self, key: str, value: Union[str, list, tuple, dict]) -> Union[List[Union[lkml.tree.BlockNode, lkml.tree.ListNode, lkml.tree.PairNode]], lkml.tree.BlockNode, lkml.tree.ListNode, lkml.tree.PairNode]:
21    def parse_any(
22        self, key: str, value: Union[str, list, tuple, dict]
23    ) -> Union[
24        List[Union[BlockNode, ListNode, PairNode]], BlockNode, ListNode, PairNode
25    ]:
26        """Dynamically serializes a Python object based on its type.
27
28        Args:
29            key: A LookML field type (e.g. "suggestions" or "hidden")
30            value: A string, tuple, or list to serialize
31        Raises:
32            TypeError: If input value is not of a valid type
33        Returns:
34            A generator of serialized string chunks
35        """
36        if isinstance(value, str):
37            return self.parse_pair(key, value)
38        elif isinstance(value, (list, tuple)):
39            if self.is_plural_key(key) and not self.parent_key == "query":
40                # See https://github.com/joshtemple/lkml/issues/53
41                # We check that the parent is not a query to ensure the
42                # query fields don't get unnested
43                return self.expand_list(key, value)
44            else:
45                return self.parse_list(key, value)
46        elif isinstance(value, dict):
47            if key in KEYS_WITH_NAME_FIELDS or "name" not in value.keys():
48                name = None
49            else:
50                name = value.pop("name")
51            return self.parse_block(key, value, name)
52        else:
53            raise TypeError("Value must be a string, list, tuple, or dict.")

Dynamically serializes a Python object based on its type.

Args: key: A LookML field type (e.g. "suggestions" or "hidden") value: A string, tuple, or list to serialize Raises: TypeError: If input value is not of a valid type Returns: A generator of serialized string chunks