generator/lkml_update.py (29 lines of code) (raw):

"""An updated lkml parser to handle explore queries.""" from typing import List, Union from lkml.keys import KEYS_WITH_NAME_FIELDS from lkml.simple import DictParser from lkml.tree import BlockNode, DocumentNode, ListNode, PairNode def dump(obj: dict) -> str: """Dump an object as LookML.""" parser = UpdatedDictParser() tree: DocumentNode = parser.parse(obj) return str(tree) class UpdatedDictParser(DictParser): """An updated DictParser that properly handles queries.""" def parse_any( self, key: str, value: Union[str, list, tuple, dict] ) -> Union[ List[Union[BlockNode, ListNode, PairNode]], BlockNode, ListNode, PairNode ]: """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 """ if isinstance(value, str): return self.parse_pair(key, value) elif isinstance(value, (list, tuple)): if self.is_plural_key(key) and not self.parent_key == "query": # See https://github.com/joshtemple/lkml/issues/53 # We check that the parent is not a query to ensure the # query fields don't get unnested return self.expand_list(key, value) else: return self.parse_list(key, value) elif isinstance(value, dict): if key in KEYS_WITH_NAME_FIELDS or "name" not in value.keys(): name = None else: name = value.pop("name") return self.parse_block(key, value, name) else: raise TypeError("Value must be a string, list, tuple, or dict.")