forked from dbt-labs/dbt-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
collect-dbt-contexts.py
115 lines (88 loc) · 2.82 KB
/
collect-dbt-contexts.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env python
import inspect
import json
from dataclasses import dataclass
from typing import List, Optional, Iterable, Union, Dict, Any
from dbt.dataclass_schema import dbtClassMixin
from dbt.context.base import BaseContext
from dbt.context.target import TargetContext
from dbt.context.providers import ModelContext, MacroContext
CONTEXTS_MAP = {
"base": BaseContext,
"target": TargetContext,
"model": ModelContext,
"macro": MacroContext,
}
@dataclass
class ContextValue(dbtClassMixin):
name: str
value: str # a type description
doc: Optional[str]
@dataclass
class MethodArgument(dbtClassMixin):
name: str
value: str # a type description
@dataclass
class ContextMethod(dbtClassMixin):
name: str
args: List[MethodArgument]
result: str # a type description
doc: Optional[str]
@dataclass
class Unknown(dbtClassMixin):
name: str
value: str
doc: Optional[str]
ContextMember = Union[ContextValue, ContextMethod, Unknown]
def _get_args(func: inspect.Signature) -> Iterable[MethodArgument]:
found_first = False
for argname, arg in func.parameters.items():
if found_first is False and argname in {"self", "cls"}:
continue
if found_first is False:
found_first = True
yield MethodArgument(
name=argname,
value=inspect.formatannotation(arg.annotation),
)
def collect(cls):
values = []
for name, v in cls._context_members_.items():
attrname = cls._context_attrs_[name]
attrdef = getattr(cls, attrname)
doc = getattr(attrdef, "__doc__")
if inspect.isfunction(attrdef):
sig = inspect.signature(attrdef)
result = inspect.formatannotation(sig.return_annotation)
sig_good_part = ContextMethod(
name=name,
args=list(_get_args(sig)),
result=result,
doc=doc,
)
elif isinstance(attrdef, property):
sig = inspect.signature(attrdef.fget)
sig_txt = inspect.formatannotation(sig.return_annotation)
sig_good_part = ContextValue(name=name, value=sig_txt, doc=doc)
else:
sig_good_part = Unknown(name=name, value=repr(attrdef), doc=doc)
values.append(sig_good_part)
return values
@dataclass
class ContextCatalog(dbtClassMixin):
base: List[ContextMember]
target: List[ContextMember]
model: List[ContextMember]
macro: List[ContextMember]
schema: Dict[str, Any]
def main():
catalog = ContextCatalog(
base=collect(BaseContext),
target=collect(TargetContext),
model=collect(ModelContext),
macro=collect(MacroContext),
schema=ContextCatalog.json_schema(),
)
print(json.dumps(catalog.to_dict()))
if __name__ == "__main__":
main()