Edit on GitHub

# sqlglot.serde

View Source

     1from __future__ import annotations
     2
     3import typing as t
     4
     5from sqlglot import expressions as exp
     6
     7if t.TYPE_CHECKING:
     8    JSON = t.Union[dict, list, str, float, int, bool, None]
     9    Node = t.Union[t.List["Node"], exp.DataType.Type, exp.Expression, JSON]
    10
    11
    12def dump(node: Node) -> JSON:
    13    """
    14    Recursively dump an AST into a JSON-serializable dict.
    15    """
    16    if isinstance(node, list):
    17        return [dump(i) for i in node]
    18    if isinstance(node, exp.DataType.Type):
    19        return {
    20            "class": "DataType.Type",
    21            "value": node.value,
    22        }
    23    if isinstance(node, exp.Expression):
    24        klass = node.__class__.__qualname__
    25        if node.__class__.__module__ != exp.__name__:
    26            klass = f"{node.__module__}.{klass}"
    27        obj: t.Dict = {
    28            "class": klass,
    29            "args": {k: dump(v) for k, v in node.args.items() if v is not None and v != []},
    30        }
    31        if node.type:
    32            obj["type"] = dump(node.type)
    33        if node.comments:
    34            obj["comments"] = node.comments
    35        if node._meta is not None:
    36            obj["meta"] = node._meta
    37
    38        return obj
    39    return node
    40
    41
    42def load(obj: JSON) -> Node:
    43    """
    44    Recursively load a dict (as returned by `dump`) into an AST.
    45    """
    46    if isinstance(obj, list):
    47        return [load(i) for i in obj]
    48    if isinstance(obj, dict):
    49        class_name = obj["class"]
    50
    51        if class_name == "DataType.Type":
    52            return exp.DataType.Type(obj["value"])
    53
    54        if "." in class_name:
    55            module_path, class_name = class_name.rsplit(".", maxsplit=1)
    56            module = __import__(module_path, fromlist=[class_name])
    57        else:
    58            module = exp
    59
    60        klass = getattr(module, class_name)
    61
    62        expression = klass(**{k: load(v) for k, v in obj["args"].items()})
    63        expression.type = t.cast(exp.DataType, load(obj.get("type")))
    64        expression.comments = obj.get("comments")
    65        expression._meta = obj.get("meta")
    66
    67        return expression
    68    return obj

def dump( node: Union[List[ForwardRef('Node')], sqlglot.expressions.DataType.Type, sqlglot.expressions.Expression, dict, list, str, float, int, bool, NoneType]) -> Union[dict, list, str, float, int, bool, NoneType]: View Source

    13def dump(node: Node) -> JSON:
    14    """
    15    Recursively dump an AST into a JSON-serializable dict.
    16    """
    17    if isinstance(node, list):
    18        return [dump(i) for i in node]
    19    if isinstance(node, exp.DataType.Type):
    20        return {
    21            "class": "DataType.Type",
    22            "value": node.value,
    23        }
    24    if isinstance(node, exp.Expression):
    25        klass = node.__class__.__qualname__
    26        if node.__class__.__module__ != exp.__name__:
    27            klass = f"{node.__module__}.{klass}"
    28        obj: t.Dict = {
    29            "class": klass,
    30            "args": {k: dump(v) for k, v in node.args.items() if v is not None and v != []},
    31        }
    32        if node.type:
    33            obj["type"] = dump(node.type)
    34        if node.comments:
    35            obj["comments"] = node.comments
    36        if node._meta is not None:
    37            obj["meta"] = node._meta
    38
    39        return obj
    40    return node

Recursively dump an AST into a JSON-serializable dict.

def load( obj: Union[dict, list, str, float, int, bool, NoneType]) -> Union[List[ForwardRef('Node')], sqlglot.expressions.DataType.Type, sqlglot.expressions.Expression, dict, list, str, float, int, bool, NoneType]: View Source

    43def load(obj: JSON) -> Node:
    44    """
    45    Recursively load a dict (as returned by `dump`) into an AST.
    46    """
    47    if isinstance(obj, list):
    48        return [load(i) for i in obj]
    49    if isinstance(obj, dict):
    50        class_name = obj["class"]
    51
    52        if class_name == "DataType.Type":
    53            return exp.DataType.Type(obj["value"])
    54
    55        if "." in class_name:
    56            module_path, class_name = class_name.rsplit(".", maxsplit=1)
    57            module = __import__(module_path, fromlist=[class_name])
    58        else:
    59            module = exp
    60
    61        klass = getattr(module, class_name)
    62
    63        expression = klass(**{k: load(v) for k, v in obj["args"].items()})
    64        expression.type = t.cast(exp.DataType, load(obj.get("type")))
    65        expression.comments = obj.get("comments")
    66        expression._meta = obj.get("meta")
    67
    68        return expression
    69    return obj

Recursively load a dict (as returned by `dump`) into an AST.