Skip to content

Commit 9368049

Browse files
committed
fix explore parsing
1 parent 0f4d4a3 commit 9368049

File tree

1 file changed

+95
-69
lines changed

1 file changed

+95
-69
lines changed

lkml2cube/parser/explores.py

Lines changed: 95 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
import re
32
import traceback
43
import typer
@@ -7,46 +6,51 @@
76

87
from lkml2cube.parser.views import parse_view
98

10-
snake_case = r'\{([a-zA-Z]+(?:_[a-zA-Z]+)*\.[a-zA-Z]+(?:_[a-zA-Z]+)*)\}'
9+
snake_case = r"\{([a-zA-Z]+(?:_[a-zA-Z]+)*\.[a-zA-Z]+(?:_[a-zA-Z]+)*)\}"
10+
1111

1212
def snakify(s):
13-
return '_'.join(
14-
re.sub('([A-Z][a-z]+)', r' \1',
15-
re.sub('([A-Z]+)', r' \1',
16-
s.replace('-', ' '))).split()
13+
return "_".join(
14+
re.sub(
15+
"([A-Z][a-z]+)", r" \1", re.sub("([A-Z]+)", r" \1", s.replace("-", " "))
16+
).split()
1717
).lower()
1818

19+
1920
def build_cube_name_look_up(cube_def):
20-
if 'cube_name_look_up' in cube_def:
21+
if "cube_name_look_up" in cube_def:
2122
return
2223
cube_name_look_up = {}
23-
for cube_element in cube_def['cubes']:
24-
cube_name_look_up[cube_element['name']] = cube_element
25-
cube_def['cube_name_look_up'] = cube_name_look_up
24+
for cube_element in cube_def["cubes"]:
25+
cube_name_look_up[cube_element["name"]] = cube_element
26+
cube_def["cube_name_look_up"] = cube_name_look_up
27+
2628

2729
def get_cube_from_cube_def(cube_def, cube_name):
28-
if 'cube_name_look_up' not in cube_def:
30+
if "cube_name_look_up" not in cube_def:
2931
build_cube_name_look_up(cube_def)
30-
if cube_name in cube_def['cube_name_look_up']:
31-
return cube_def['cube_name_look_up'][cube_name]
32+
if cube_name in cube_def["cube_name_look_up"]:
33+
return cube_def["cube_name_look_up"][cube_name]
3234
return None
3335

36+
3437
def get_cube_names_from_join_condition(join_condition):
35-
return [cube.split('.')[0] for cube in re.findall(snake_case, join_condition)]
38+
return [cube.split(".")[0] for cube in re.findall(snake_case, join_condition)]
39+
3640

3741
def traverse_graph(join_paths, cube_left, cube_right):
3842
# Create a queue for BFS
3943
queue = []
4044
queue.append([cube_left])
4145

4246
while queue:
43-
#Dequeue a vertex from queue
47+
# Dequeue a vertex from queue
4448
tmp_path = queue.pop(0)
4549
# If this adjacent node is the destination node,
4650
# then return true
47-
last_node = tmp_path[len(tmp_path)-1]
51+
last_node = tmp_path[len(tmp_path) - 1]
4852
if last_node == cube_right:
49-
return '.'.join(tmp_path)
53+
return ".".join(tmp_path)
5054
# Else, continue to do BFS
5155
if last_node in join_paths:
5256
for cube in join_paths[last_node]:
@@ -55,106 +59,128 @@ def traverse_graph(join_paths, cube_left, cube_right):
5559
new_path = tmp_path + [cube]
5660
queue.append(new_path)
5761

58-
typer.echo(f'Cubes are not reachable: {cube_left}, {cube_right}')
59-
return '.'.join(cube_left, cube_right)
62+
typer.echo(f"Cubes are not reachable: {cube_left}, {cube_right}")
63+
return ".".join(cube_left, cube_right)
6064

6165

6266
def generate_cube_joins(cube_def, lookml_model):
63-
for explore in lookml_model['explores']:
64-
if 'joins' not in explore:
67+
if "explores" not in lookml_model or not lookml_model["explores"]:
68+
return cube_def
69+
for explore in lookml_model["explores"]:
70+
if "joins" not in explore:
6571
continue
6672

67-
for join_element in explore['joins']:
73+
for join_element in explore["joins"]:
6874
try:
69-
cube_right = join_element['name']
70-
71-
joined_cubes = [cube for cube in get_cube_names_from_join_condition(join_element['sql_on']) if cube != cube_right]
75+
cube_right = join_element["name"]
76+
77+
joined_cubes = [
78+
cube
79+
for cube in get_cube_names_from_join_condition(
80+
join_element["sql_on"]
81+
)
82+
if cube != cube_right
83+
]
7284
if joined_cubes:
73-
if 'from' in join_element:
85+
if "from" in join_element:
7486
cube = {
75-
'name': cube_right,
76-
'extends': join_element['from'],
77-
'shown': False,
87+
"name": cube_right,
88+
"extends": join_element["from"],
89+
"shown": False,
7890
}
79-
cube_def['cubes'].append(cube)
91+
cube_def["cubes"].append(cube)
8092
else:
8193
cube = get_cube_from_cube_def(cube_def, cube_right)
8294
if not cube:
83-
typer.echo(f'Cube referenced in explores not found: {join_element["name"]}')
95+
typer.echo(
96+
f'Cube referenced in explores not found: {join_element["name"]}'
97+
)
8498
continue
8599

86-
join_condition = join_element['sql_on']
100+
join_condition = join_element["sql_on"]
87101

88-
if 'joins' not in cube:
89-
cube['joins'] = []
102+
if "joins" not in cube:
103+
cube["joins"] = []
90104

91-
cube['joins'].append({
92-
'name': joined_cubes[0],
93-
'sql': join_condition,
94-
'relationship': join_element['relationship']
95-
})
105+
cube["joins"].append(
106+
{
107+
"name": joined_cubes[0],
108+
"sql": join_condition,
109+
"relationship": join_element["relationship"],
110+
}
111+
)
96112
except Exception:
97-
typer.echo(f'Error while parsing explore: {pformat(explore)}')
113+
typer.echo(f"Error while parsing explore: {pformat(explore)}")
98114
typer.echo(traceback.format_exc())
99115

100116
return cube_def
101117

118+
102119
def generate_cube_views(cube_def, lookml_model):
103-
if 'views' not in cube_def:
104-
cube_def['views'] = []
105-
for explore in lookml_model['explores']:
120+
if "views" not in cube_def:
121+
cube_def["views"] = []
122+
if "explores" not in lookml_model or not lookml_model["explores"]:
123+
return cube_def
124+
for explore in lookml_model["explores"]:
106125
try:
107-
central_cube = explore['name']
108-
view_name = snakify(explore['label'])
126+
central_cube = explore["name"]
127+
label = explore.get("label", explore.get("view_label", explore["name"]))
128+
view_name = snakify(label)
109129
view = {
110-
'name': view_name,
111-
'description': explore['label'],
112-
'cubes': [{
113-
'join_path': central_cube,
114-
'includes': "*",
115-
'alias': view_name
116-
}]
130+
"name": view_name,
131+
"description": label,
132+
"cubes": [
133+
{"join_path": central_cube, "includes": "*", "alias": view_name}
134+
],
117135
}
118136

119-
if 'joins' not in explore:
120-
cube_def['views'].append(view)
137+
if "joins" not in explore or not explore["joins"]:
138+
cube_def["views"].append(view)
121139
continue
122140
# Create Graph
123141
join_paths = {}
124-
for join_element in explore['joins']:
125-
cube_right = join_element['name']
126-
cube_left = [cube for cube in get_cube_names_from_join_condition(join_element['sql_on']) if cube != cube_right][0]
142+
for join_element in explore["joins"]:
143+
cube_right = join_element["name"]
144+
cube_left = [
145+
cube
146+
for cube in get_cube_names_from_join_condition(
147+
join_element["sql_on"]
148+
)
149+
if cube != cube_right
150+
][0]
127151

128152
if cube_left in join_paths:
129153
join_paths[cube_left].append(cube_right)
130154
else:
131155
join_paths[cube_left] = [cube_right]
132156
# traverse graph
133-
for join_element in explore['joins']:
134-
cube_right = join_element['name']
157+
for join_element in explore["joins"]:
158+
cube_right = join_element["name"]
135159
join_path = {
136-
'join_path': traverse_graph(join_paths, central_cube, cube_right),
137-
'includes': "*",
138-
'alias': cube_right
160+
"join_path": traverse_graph(join_paths, central_cube, cube_right),
161+
"includes": "*",
162+
"alias": cube_right,
139163
}
140-
view['cubes'].append(join_path)
141-
164+
view["cubes"].append(join_path)
165+
142166
# End
143-
cube_def['views'].append(view)
167+
cube_def["views"].append(view)
144168

145169
except Exception:
146-
typer.echo(f'Error while parsing explore: {pformat(explore)}')
170+
typer.echo(f"Error while parsing explore: {pformat(explore)}")
147171
typer.echo(traceback.format_exc())
148172
return cube_def
149173

150174

151175
def parse_explores(lookml_model):
152176
# First we read all possible lookml views.
153177
cube_def = parse_view(lookml_model, raise_when_views_not_present=False)
154-
if 'explores' not in lookml_model:
155-
raise Exception('LookML explores are needed to generate Cube Views, no explore found in path.')
178+
if "explores" not in lookml_model:
179+
raise Exception(
180+
"LookML explores are needed to generate Cube Views, no explore found in path."
181+
)
156182
cube_def = generate_cube_joins(cube_def, lookml_model)
157183

158184
cube_def = generate_cube_views(cube_def, lookml_model)
159185

160-
return cube_def
186+
return cube_def

0 commit comments

Comments
 (0)