def export(): # type: () -> flask.Response ''' Export hidebound data. Returns: Response: Flask Response instance. ''' global DATABASE global CONFIG if DATABASE is None: return server_tools.get_initialization_error() try: DATABASE.export() except Exception as error: return server_tools.error_to_response(error) return flask.Response( response=json.dumps(dict( message='Hidebound data exported.', config=CONFIG, )), mimetype='application/json' )
def test_error_to_response(self): error = TypeError('foo') result = server_tools.error_to_response(error) self.assertEqual(result.mimetype, 'application/json') self.assertEqual(result.json['error'], 'TypeError') self.assertEqual(result.json['args'], ['foo']) self.assertEqual(result.json['message'], 'TypeError(\n foo\n)') self.assertEqual(result.json['code'], 500)
def handle_data_error(error): # type: (DataError) -> flask.Response ''' Handles errors raise by config validation. Args: error (DataError): Config validation error. Returns: Response: DataError response. ''' return server_tools.error_to_response(error)
def search(): # type: () -> flask.Response ''' Search database with a given SQL query. Returns: Response: Flask Response instance. ''' global DATABASE global CONFIG params = flask.request.get_json() grp = False try: params = json.loads(params) query = params['query'] if 'group_by_asset' in params.keys(): grp = params['group_by_asset'] assert(isinstance(grp, bool)) except (JSONDecodeError, TypeError, KeyError, AssertionError): return server_tools.get_search_error() if DATABASE is None: return server_tools.get_initialization_error() if DATABASE.data is None: return server_tools.get_update_error() response = None try: response = DATABASE.search(query, group_by_asset=grp) except Exception as e: return server_tools.error_to_response(e) response.asset_valid = response.asset_valid.astype(bool) response = response.replace({np.nan: None}).to_dict(orient='records') response = {'response': response} return flask.Response( response=json.dumps(response), mimetype='application/json' )
def read(): # type: () -> flask.Response ''' Read database. Returns: Response: Flask Response instance. ''' global DATABASE global CONFIG if DATABASE is None: return server_tools.get_initialization_error() params = flask.request.get_json() grp = False if params is not None: try: params = json.loads(params) grp = params['group_by_asset'] assert(isinstance(grp, bool)) except (JSONDecodeError, TypeError, KeyError, AssertionError): return server_tools.get_read_error() response = {} # type: Any try: response = DATABASE.read(group_by_asset=grp) except Exception as error: if isinstance(error, RuntimeError): return server_tools.get_update_error() return server_tools.error_to_response(error) response = response.replace({np.nan: None}).to_dict(orient='records') response = {'response': response} return flask.Response( response=json.dumps(response), mimetype='application/json' )
def on_event(*inputs): # type: (Tuple[Any, ...]) -> Dict[str, Any] ''' Update Hidebound database instance, and updates store with input data. Args: inputs (tuple): Input elements. Returns: dict: Store data. ''' APP.logger.debug(f'on_event called with inputs: {str(inputs)[:50]}') store = inputs[-1] or {} # type: Any config = store.get('config', api.CONFIG) # type: Dict conf = json.dumps(config) context = dash.callback_context inputs_ = {} for item in context.inputs_list: key = item['id'] val = None if 'value' in item.keys(): val = item['value'] inputs_[key] = val # convert search dropdown to boolean grp = False if inputs_['dropdown'] == 'asset': grp = True inputs_['dropdown'] = grp input_id = context.triggered[0]['prop_id'].split('.')[0] if input_id == 'init-button': APP.server.test_client().post('/api/initialize', json=conf) elif input_id == 'update-button': if api.DATABASE is None: APP.server.test_client().post('/api/initialize', json=conf) APP.server.test_client().post('/api/update') params = json.dumps({'group_by_asset': grp}) response = APP.server.test_client().post('/api/read', json=params).json store['/api/read'] = response elif input_id == 'create-button': APP.server.test_client().post('/api/create') elif input_id == 'export-button': response = APP.server.test_client().post('/api/export') code = response.status_code if code < 200 or code >= 300: store['/api/read'] = response.json elif input_id == 'delete-button': APP.server.test_client().post('/api/delete') elif input_id == 'search-button': query = json.dumps({ 'query': inputs_['query'], 'group_by_asset': inputs_['dropdown'] }) response = APP.server.test_client().post('/api/search', json=query).json store['/api/read'] = response store['query'] = inputs_['query'] elif input_id == 'upload': temp = 'invalid' # type: Any try: upload = inputs_['upload'] # type: Any temp = server_tools.parse_json_file_content(upload) Config(temp).validate() store['config'] = temp store['config_error'] = None except Exception as error: response = server_tools.error_to_response(error) store['config'] = temp store['config_error'] = server_tools.error_to_response(error).json elif input_id == 'write-button': try: config = store['config'] Config(config).validate() with open(CONFIG_PATH, 'w') as f: # type: ignore json.dump(config, f, indent=4, sort_keys=True) store['config_error'] = None except Exception as error: store['config_error'] = server_tools.error_to_response(error).json return store