Edit on GitHub

sqlglot.serde

 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]:
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]:
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.