Skip to content

Commit b013305

Browse files
committed
async support (cont.)
1 parent 7997143 commit b013305

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed

metabase_api/metabase_api_async.py

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ async def search(self, q, item_type=None):
112112

113113
return res
114114

115+
116+
115117
async def get_card_data(self, card_name=None, card_id=None, collection_name=None, collection_id=None,
116118
data_format='json', parameters=None, format_rows=False):
117119
'''
@@ -156,3 +158,172 @@ async def get_card_data(self, card_name=None, card_id=None, collection_name=None
156158
if data_format == 'csv':
157159
text = res.text if hasattr(res, 'text') else await res.text()
158160
return text.replace('null', '')
161+
162+
163+
164+
async def clone_card(self, card_id,
165+
source_table_id=None, target_table_id=None,
166+
source_table_name=None, target_table_name=None,
167+
new_card_name=None, new_card_collection_id=None,
168+
ignore_these_filters=None, return_card=False):
169+
"""
170+
Async version of clone_card.
171+
"""
172+
if not source_table_id:
173+
if not source_table_name:
174+
raise ValueError('Either the name or id of the source table needs to be provided.')
175+
else:
176+
source_table_id = await self.get_item_id('table', source_table_name)
177+
178+
if not target_table_id:
179+
if not target_table_name:
180+
raise ValueError('Either the name or id of the target table needs to be provided.')
181+
else:
182+
target_table_id = await self.get_item_id('table', target_table_name)
183+
184+
if ignore_these_filters:
185+
assert type(ignore_these_filters) == list
186+
187+
card_info = await self.get_item_info('card', card_id)
188+
target_table_col_name_id_mapping = await self.get_columns_name_id(table_id=target_table_id)
189+
source_table_col_id_name_mapping = await self.get_columns_name_id(table_id=source_table_id, column_id_name=True)
190+
191+
if card_info['dataset_query']['type'] == 'native':
192+
filters_data = card_info['dataset_query']['native']['template-tags']
193+
if not source_table_name:
194+
source_table_name = await self.get_item_name('table', source_table_id)
195+
if not target_table_name:
196+
target_table_name = await self.get_item_name('table', target_table_id)
197+
card_info['dataset_query']['native']['query'] = card_info['dataset_query']['native']['query'].replace(source_table_name, target_table_name)
198+
for filter_variable_name, data in filters_data.items():
199+
if ignore_these_filters is not None and filter_variable_name in ignore_these_filters:
200+
continue
201+
column_id = data['dimension'][1]
202+
column_name = source_table_col_id_name_mapping[column_id]
203+
target_col_id = target_table_col_name_id_mapping[column_name]
204+
card_info['dataset_query']['native']['template-tags'][filter_variable_name]['dimension'][1] = target_col_id
205+
206+
elif card_info['dataset_query']['type'] == 'query':
207+
query_data = card_info['dataset_query']['query']
208+
query_data['source-table'] = target_table_id
209+
query_data_str = str(query_data)
210+
import re
211+
res = re.findall(r"\['field', .*?\]", query_data_str)
212+
source_column_IDs = [ eval(i)[1] for i in res ]
213+
for source_col_id in source_column_IDs:
214+
source_col_name = source_table_col_id_name_mapping[source_col_id]
215+
target_col_id = target_table_col_name_id_mapping[source_col_name]
216+
query_data_str = query_data_str.replace("['field', {}, ".format(source_col_id), "['field', {}, ".format(target_col_id))
217+
card_info['dataset_query']['query'] = eval(query_data_str)
218+
219+
new_card_json = {}
220+
for key in ['dataset_query', 'display', 'visualization_settings']:
221+
new_card_json[key] = card_info[key]
222+
223+
if new_card_name:
224+
new_card_json['name'] = new_card_name
225+
else:
226+
new_card_json['name'] = card_info['name']
227+
228+
if new_card_collection_id:
229+
new_card_json['collection_id'] = new_card_collection_id
230+
else:
231+
new_card_json['collection_id'] = card_info['collection_id']
232+
233+
if return_card:
234+
return await self.create_card(custom_json=new_card_json, verbose=True, return_card=return_card)
235+
else:
236+
await self.create_card(custom_json=new_card_json, verbose=True)
237+
238+
239+
240+
async def move_to_archive(self, item_type, item_name=None, item_id=None,
241+
collection_name=None, collection_id=None, table_id=None, verbose=False):
242+
'''
243+
Async version of move_to_archive.
244+
'''
245+
assert item_type in ['card', 'dashboard', 'collection', 'pulse', 'segment']
246+
247+
if not item_id:
248+
if not item_name:
249+
raise ValueError('Either the name or id of the {} must be provided.'.format(item_type))
250+
if item_type == 'collection':
251+
item_id = await self.get_item_id('collection', item_name)
252+
elif item_type == 'segment':
253+
item_id = await self.get_item_id('segment', item_name, table_id=table_id)
254+
else:
255+
item_id = await self.get_item_id(item_type, item_name, collection_id, collection_name)
256+
257+
if item_type == 'segment':
258+
res = await self.put('/api/{}/{}'.format(item_type, item_id), json={'archived':True, 'revision_message':'archived!'})
259+
else:
260+
res = await self.put('/api/{}/{}'.format(item_type, item_id), json={'archived':True})
261+
262+
if res in [200, 202]:
263+
await self.verbose_print(verbose, 'Successfully Archived.')
264+
else:
265+
print('Archiving Failed.')
266+
267+
return res
268+
269+
270+
271+
async def delete_item(self, item_type, item_name=None, item_id=None,
272+
collection_name=None, collection_id=None, verbose=False):
273+
'''
274+
Async version of delete_item.
275+
'''
276+
assert item_type in ['card', 'dashboard', 'pulse']
277+
if not item_id:
278+
if not item_name:
279+
raise ValueError('Either the name or id of the {} must be provided.'.format(item_type))
280+
item_id = await self.get_item_id(item_type, item_name, collection_id, collection_name)
281+
282+
return await self.delete('/api/{}/{}'.format(item_type, item_id))
283+
284+
285+
286+
async def update_column(self, params, column_id=None, column_name=None,
287+
table_id=None, table_name=None, db_id=None, db_name=None):
288+
'''
289+
Async version of update_column.
290+
'''
291+
assert type(params) == dict
292+
293+
if not column_id:
294+
if not column_name:
295+
raise ValueError('Either the name or id of the column needs to be provided.')
296+
297+
if not table_id:
298+
if not table_name:
299+
raise ValueError('When column_id is not given, either the name or id of the table needs to be provided.')
300+
table_id = await self.get_item_id('table', table_name, db_id=db_id, db_name=db_name)
301+
302+
columns_name_id_mapping = await self.get_columns_name_id(table_name=table_name, table_id=table_id, db_name=db_name, db_id=db_id)
303+
column_id = columns_name_id_mapping.get(column_name)
304+
if column_id is None:
305+
raise ValueError('There is no column named {} in the provided table'.format(column_name))
306+
307+
res_status_code = await self.put('/api/field/{}'.format(column_id), json=params)
308+
if res_status_code != 200:
309+
print('Column Update Failed.')
310+
311+
return res_status_code
312+
313+
314+
315+
async def add_card_to_dashboard(self, card_id, dashboard_id):
316+
params = {
317+
'cardId': card_id
318+
}
319+
await self.post(f'/api/dashboard/{dashboard_id}/cards', json=params)
320+
321+
@staticmethod
322+
async def make_json(raw_json, prettyprint=False):
323+
"""Async version of make_json."""
324+
import json
325+
ret_dict = json.loads(raw_json)
326+
if prettyprint:
327+
import pprint
328+
pprint.pprint(ret_dict)
329+
return ret_dict

0 commit comments

Comments
 (0)