def delete_database(client: AitoClient): """`delete the whole database <https://aito.ai/docs/api/#delete-api-v1-schema>`__ .. note:: requires the client to be setup with the READ-WRITE API key :param client: the AitoClient instance :type client: AitoClient """ client.request(request_obj=aito_requests.DeleteDatabaseSchemaRequest()) LOG.info('database deleted')
def create_database(client: AitoClient, schema: Union[AitoDatabaseSchema, Dict]): """`create a database <https://aito.ai/docs/api/#put-api-v1-schema>`__ using the specified database schema .. note:: requires the client to be setup with the READ-WRITE API key :param client: the AitoClient instance :type client: AitoClient :param schema: the schema of the database :type schema: Dict """ client.request(request_obj=aito_requests.CreateDatabaseSchemaRequest(schema=schema)) LOG.info('database schema created')
def delete_table(client: AitoClient, table_name: str): """`delete the specified table <https://aito.ai/docs/api/#delete-api-v1-schema>`__ .. note:: requires the client to be setup with the READ-WRITE API key :param client: the AitoClient instance :type client: AitoClient :param table_name: the name of the table :type table_name: str """ client.request(request_obj=aito_requests.DeleteTableSchemaRequest(table_name=table_name)) LOG.info(f'table `{table_name}` deleted')
def trigger_file_processing(client: AitoClient, table_name: str, session_id: str): """`Trigger file processing of uploading a file to a table <https://aito.ai/docs/api/#post-api-v1-data-table-file-uuid>`__ :param client: the AitoClient instance :type client: AitoClient :param table_name: the name of the table to be uploaded :type table_name: str :param session_id: The upload session id from :func:`.initiate_upload_file` :type session_id: str """ LOG.debug('triggering file processing...') client.request(request_obj=aito_requests.TriggerFileProcessingRequest(table_name=table_name, session_id=session_id)) LOG.info('triggered file processing')
def create_client_from_parsed_args(parsed_args, check_credentials=True) -> AitoClient: """create client from parsed args with the default aito credentials arguments from add_aito_default_credentials_arguments """ def check_flag_env_var_default_credential(flag_name, env_var_name, credential_key): if parsed_args[flag_name] != '.env': return parsed_args[flag_name] if parse_env_variable(env_var_name): return parse_env_variable(env_var_name) LOG.debug(f"{env_var_name} environment variable not found. Checking credentials file") config = get_credentials_file_config() profile = parsed_args['profile'] if not config.has_section(profile): raise ParseError(f"profile `{profile}` not found. " f"Please edit the credentials file or run `aito configure`") if credential_key not in config[profile]: raise ParseError(f"{credential_key} not found in profile `{profile}`." f"Please edit the credentials file or run `aito configure`") return config[profile][credential_key] instance_url = check_flag_env_var_default_credential('instance_url', 'AITO_INSTANCE_URL', 'instance_url') api_key = check_flag_env_var_default_credential('api_key', 'AITO_API_KEY', 'api_key') client_args = { 'instance_url': instance_url, 'api_key': api_key, 'check_credentials': check_credentials } return AitoClient(**client_args)
def delete_column(client: AitoClient, table_name: str, column_name: str): """`delete a column of a table <https://aito.ai/docs/api/#delete-api-v1-schema-column>`__ .. note:: requires the client to be setup with the READ-WRITE API key :param client: the AitoClient instance :type client: AitoClient :param table_name: the name of the table containing the column :type table_name: str :param column_name: the name of the column :type column_name: str """ client.request(request_obj=aito_requests.DeleteColumnSchemaRequest(table_name=table_name, column_name=column_name)) LOG.info(f'column `{table_name}.{column_name}` deleted')
def parse_and_execute(self, parsed_args: Dict): profile = parsed_args['profile'] existing_instance_url, existing_api_key = get_existing_credentials( profile_name=profile) if existing_instance_url is not None or existing_api_key is not None: if not prompt_confirmation( f'Profile {profile} already exists. Do you want to replace?' ): return 0 input_ret_val = input( 'instance url (i.e: https://instance_name.aito.app): ' if not existing_instance_url else f'instance url [{mask_instance_url(existing_instance_url)}]') new_instance_url = input_ret_val if input_ret_val else existing_instance_url if not new_instance_url: raise ParseError('instance url must not be empty') input_ret_val = input( 'api key [None]' if not existing_instance_url else f'api key [{mask_api_key(existing_api_key)}]') new_api_key = input_ret_val if input_ret_val else existing_api_key if not new_api_key: raise ParseError('api_key must not be empty') try: AitoClient(instance_url=new_instance_url, api_key=new_api_key, check_credentials=True) except Error: raise ParseError('invalid credentials, please try again') write_credentials_file_profile(parsed_args['profile'], new_instance_url, new_api_key)
def poll_file_processing_status(client: AitoClient, table_name: str, session_id: str, polling_time: int = 10): """Polling the `file processing status <https://aito.ai/docs/api/#get-api-v1-data-table-file-uuid>`__ until the processing finished :param client: the AitoClient instance :type client: AitoClient :param table_name: the name of the table to be uploaded :type table_name: str :param session_id: The upload session id from :func:`.initiate_upload_file` :type session_id: str :param polling_time: polling wait time :type polling_time: int """ LOG.debug('polling processing status...') while True: try: processing_progress_resp = client.request( request_obj=aito_requests.GetFileProcessingRequest(table_name=table_name, session_id=session_id) ) status = processing_progress_resp['status'] LOG.debug(f"completed count: {status['completedCount']}, throughput: {status['throughput']}") if processing_progress_resp['errors']['message'] != 'Last 0 failing rows': LOG.error(processing_progress_resp['errors']) if status['finished']: break except Exception as e: LOG.debug(f'failed to get file upload status: {e}') time.sleep(polling_time)
def get_database_schema(client: AitoClient) -> AitoDatabaseSchema: """`get the schema of the database <https://aito.ai/docs/api/#get-api-v1-schema>`__ :param client: the AitoClient instance :type client: AitoClient :return: Aito database schema :rtype: Dict """ res = client.request(request_obj=aito_requests.GetDatabaseSchemaRequest()) return res.schema
def get_version(client: AitoClient) -> str: """get the aito instance version :param client: the AitoClient instance :type client: AitoClient :return: version information in json format :rtype: Dict """ resp = client.request(request_obj=aito_requests.GetVersionRequest()) return resp.version
def create_table(client: AitoClient, table_name: str, schema: Union[AitoTableSchema, Dict]): """`create a table <https://aito.ai/docs/api/#put-api-v1-schema-table>`__ with the specified table name and schema update the table if the table already exists and does not contain any data .. note:: requires the client to be setup with the READ-WRITE API key :param client: the AitoClient instance :type client: AitoClient :param table_name: the name of the table :type table_name: str :param schema: Aito table schema :type schema: an AitoTableSchema object or a Dict, optional """ client.request(request_obj=aito_requests.CreateTableSchemaRequest(table_name=table_name, schema=schema)) LOG.info(f'table `{table_name}` created')
def job_request( client: AitoClient, job_endpoint: Optional[str] = None, query: Optional[Union[List, Dict]] = None, request_obj: Optional[Union[aito_requests.QueryAPIRequest, aito_requests.CreateJobRequest]] = None, polling_time: int = 10 ) -> aito_responses.BaseResponse: """make a request to an Aito API endpoint using `Job <https://aito.ai/docs/api/#post-api-v1-jobs-query>`__ This method should be used for requests that take longer than 30 seconds, e.g: evaluate The following query evaluate the performance of a predict query that uses the name of a product to predict its category >>> response = client.job_request( ... job_endpoint='/api/v1/jobs/_evaluate', ... query={ ... "test": { "$index": { "$mod": [4, 0] } }, ... "evaluate": { ... "from": "products", ... "where": { "name": { "$get": "name" } }, ... "predict": "category" ... } ... } ... ) >>> print(response["accuracy"]) # doctest: +ELLIPSIS 0.72... :param client: the AitoClient instance :type client: AitoClient :param job_endpoint: job end point :type job_endpoint: Optional[str] :param query: the query for the endpoint :type query: Optional[Union[List, Dict]] :param request_obj: a :class:`.CreateJobRequest` or an :class:`.QueryAPIRequest` instance :type request_obj: Optional[Union[aito_requests.QueryAPIRequest, aito_requests.CreateJobRequest]] :param polling_time: polling wait time, defaults to 10 :type polling_time: int :raises RequestError: an error occurred during the execution of the job :return: request JSON content :rtype: Dict """ create_job_req = _create_job_request(job_endpoint=job_endpoint, query=query, request_obj=request_obj) create_job_resp = client.request(request_obj=create_job_req) job_id = create_job_resp.id LOG.debug(f'polling job {job_id} status...') while True: job_status_resp = get_job_status(client, job_id) if job_status_resp.finished: LOG.debug(f'job {job_id} finished') break time.sleep(polling_time) job_result_resp = get_job_result(client, job_id) casted_job_result_resp = create_job_req.result_response_cls(job_result_resp.json) return casted_job_result_resp
def create_column(client: AitoClient, table_name: str, column_name: str, schema: Dict): """`add or replace a column <https://aito.ai/docs/api/#put-api-v1-schema-table-column>`__ .. note:: requires the client to be setup with the READ-WRITE API key :param client: the AitoClient instance :type client: AitoClient :param table_name: the name of the table containing the column :type table_name: str :param column_name: the name of the column :type column_name: str :param schema: the schema of the column :type schema: Dict """ client.request(request_obj=aito_requests.CreateColumnSchemaRequest( table_name=table_name, column_name=column_name, schema=schema) ) LOG.info(f'column `{table_name}.{column_name}` created')
def setUpClass(cls): super().setUpClass() cls.input_folder = cls.input_folder.parent.parent / 'sample_invoice' cls.default_main_parser_args = { 'verbose': False, 'version': False, 'quiet': False, 'driver': '.env', 'server': '.env', 'port': '.env', 'database': '.env', 'username': '******', 'password': '******' } cls.default_client_args = {'profile': 'default', 'api_key': '.env', 'instance_url': '.env'} cls.client = AitoClient(os.environ['AITO_INSTANCE_URL'], os.environ['AITO_API_KEY']) cls.default_table_name = f"invoice_{str(uuid4()).replace('-', '_')}"
def copy_table(client: AitoClient, table_name: str, copy_table_name: str, replace: bool = False): """`copy a table <https://aito.ai/docs/api/#post-api-v1-schema-copy>`__ .. note:: requires the client to be setup with the READ-WRITE API key :param client: the AitoClient instance :type client: AitoClient :param table_name: the name of the table to be copied :type table_name: str :param copy_table_name: the name of the new copy table :type copy_table_name: str :param replace: replace an existing table of which name is the name of the copy table, defaults to False :type replace: bool, optional """ client.request( method='POST', endpoint='/api/v1/schema/_copy', query={'from': table_name, 'copy': copy_table_name, 'replace': replace} )
def rename_table(client: AitoClient, old_name: str, new_name: str, replace: bool = False): """`rename a table <https://aito.ai/docs/api/#post-api-v1-schema-rename>`__ .. note:: requires the client to be setup with the READ-WRITE API key :param client: the AitoClient instance :type client: AitoClient :param old_name: the name of the table to be renamed :type old_name: str :param new_name: the new name of the table :type new_name: str :param replace: replace an existing table of which name is the new name, defaults to False :type replace: bool, optional """ client.request( method='POST', endpoint='/api/v1/schema/_rename', query={'from': old_name, 'rename': new_name, 'replace': replace} )
def get_requests_resp_and_aito_resp(aito_client: AitoClient, request_obj: aito_requests.AitoRequest): """returns the json content from requests lib response and aito response for comparison""" raw_resp_obj = requests.request(method=request_obj.method, url=aito_client.instance_url + request_obj.endpoint, headers=aito_client.headers, json=request_obj.query) raw_resp_json = raw_resp_obj.json() aito_resp = aito_client.request(request_obj=request_obj) return raw_resp_json, aito_resp
def get_job_result(client: AitoClient, job_id: str) -> aito_responses.BaseResponse: """`Get the result of a job <https://aito.ai/docs/api/#get-api-v1-jobs-uuid-result>`__ with the specified job id :param client: the AitoClient instance :type client: AitoClient :param job_id: the id of the job :type job_id: str :return: the job result :rtype: Dict """ resp = client.request(request_obj=aito_requests.GetJobResultRequest(job_id=job_id)) return resp
def get_table_schema(client: AitoClient, table_name: str) -> AitoTableSchema: """`get the schema of the specified table <https://aito.ai/docs/api/#get-api-v1-schema-table>`__ :param client: the AitoClient instance :type client: AitoClient :param table_name: the name of the table :type table_name: str :return: the table schema :rtype: AitoTableSchema """ resp = client.request(request_obj=aito_requests.GetTableSchemaRequest(table_name=table_name)) return resp.schema
def get_job_status(client: AitoClient, job_id: str) -> aito_responses.GetJobStatusResponse: """`Get the status of a job <https://aito.ai/docs/api/#get-api-v1-jobs-uuid>`__ with the specified job id :param client: the AitoClient instance :type client: AitoClient :param job_id: the id of the job session :type job_id: str :return: job status :rtype: Dict """ resp = client.request(request_obj=aito_requests.GetJobStatusRequest(job_id=job_id)) return resp
def initiate_upload_file(client: AitoClient, table_name: str) -> Dict: """`Initial uploading a file to a table <https://aito.ai/docs/api/#post-api-v1-data-table-file>`__ :param client: the AitoClient instance :type client: AitoClient :param table_name: the name of the table to be uploaded :type table_name: str :return: The details to execute the S3 upload and the upload session's id :rtype: Dict """ LOG.debug('initiating file upload...') r = client.request(request_obj=aito_requests.InitiateFileUploadRequest(table_name=table_name)) return r.json
def get_column_schema(client: AitoClient, table_name: str, column_name: str) -> AitoColumnTypeSchema: """`get the schema of the specified column <https://aito.ai/docs/api/#get-api-v1-schema-table-column>`__ :param client: the AitoClient instance :type client: AitoClient :param table_name: the name of the table containing the column :type table_name: str :param column_name: the name of the column :type column_name: str :return: the column schema :rtype: AitoColumnTypeSchema """ resp = client.request(request_obj=aito_requests.GetColumnSchemaRequest(table_name=table_name, column_name=column_name)) return resp.schema
def optimize_table(client: AitoClient, table_name, use_job: bool = True): """`optimize <https://aito.ai/docs/api/#post-api-v1-data-table-optimize>`__ the specified table after uploading the data. By default uses a job for the operation :param client: the AitoClient instance :type client: AitoClient :param table_name: the name of the table :type table_name: str :param use_job: use a job to run the optimize :type use_job: bool """ try: if use_job: job_request(client, job_endpoint=f'/api/v1/jobs/data/{table_name}/optimize', query={}, polling_time=5) else: client.request(method='POST', endpoint=f'/api/v1/data/{table_name}/optimize', query={}) LOG.info(f'table {table_name} optimized') except Exception as e: LOG.error(f'failed to optimize: {e}') traceback.print_tb(e.__traceback__)
def delete_entries(client: AitoClient, query: Dict, use_job: bool = True): """`Delete the entries <https://aito.ai/docs/api/#post-api-v1-data-delete>`__ according to the criteria given in the query :param client: the AitoClient instance :type client: AitoClient :param query: the query to describe the target table and filters for which entries to delete. :type query: Dict :param use_job: use a job to run the optimize :type use_job: bool """ try: if use_job: job_request(client, job_endpoint=f'/api/v1/jobs/data/_delete', query=query, polling_time=5) else: client.request(request_obj=aito_requests.DeleteEntriesRequest(query=query)) LOG.info(f'entries deleted') except Exception as e: LOG.error(f'failed to delete: {e}') traceback.print_tb(e.__traceback__)
def top_recommendation(self): AITO_INSTANCE_URL = 'https://junction-test.aito.app' AITO_API_KEY = '4yaBPf9Kmk9xHNW30jBop7ieEmWMz2eSpmKyWvBi' client = AitoClient(instance_url=AITO_INSTANCE_URL, api_key=AITO_API_KEY) queries = self.request.query_params query_type = queries.get("type", "Mexican") limit = int(queries.get("limit", 0)) user_id = queries.get("userID") wh = { "placeID.cuisine": query_type, } if user_id: like_places = list( map( lambda t: {"placeID": t}, UserLike.objects.exclude(user_id=user_id).values_list( "place__aito_id", flat=True))) if like_places: query = { "from": "ratings", "where": { "$and": like_places }, } res = aito_api.generic_query(client=client, query=query) user_ids = py_.map(res["hits"], "userID") wh["userID"] = {"$and": user_ids} rec_query = { "from": "ratings", "where": wh, "recommend": "placeID", "goal": { "rating": 2 }, } if limit: rec_query['limit'] = int(limit) res = aito_api.recommend(client=client, query=rec_query) return res.json['hits']
def recommend( client: AitoClient, query: Dict, raise_for_status: Optional[bool] = None, use_job: bool = False ) -> Union[aito_responses.RecommendResponse, RequestError]: """send a query to the `Recommend API <https://aito.ai/docs/api/#post-api-v1-recommend>`__ :param client: the AitoClient instance :type client: AitoClient :param query: the recommend query :type query: Dict :param raise_for_status: raise :class:`.RequestError` if the request fails instead of returning the error If set to None, value from Client will be used. Defaults to None :type raise_for_status: Optional[bool] :param use_job: use job fo request that takes longer than 30 seconds, defaults to False :type use_job: bool :return: :class:`.RecommendResponse` or :class:`.RequestError` if an error occurred and not raise_for_status :rtype: Union[RecommendResponse, RequestError] """ req = aito_requests.RecommendRequest(query) if use_job: return job_request(client=client, request_obj=req) return client.request(request_obj=req, raise_for_status=raise_for_status)
def top_recommendation(self): AITO_INSTANCE_URL = 'https://junction-test.aito.app' AITO_API_KEY = '4yaBPf9Kmk9xHNW30jBop7ieEmWMz2eSpmKyWvBi' client = AitoClient(instance_url=AITO_INSTANCE_URL, api_key=AITO_API_KEY) queries = self.request.query_params query_type = queries.get("type", "Mexican") limit = int(queries.get("limit", 0)) rec_query = { "from": "ratings", "where": { "placeID.cuisine": query_type, }, "recommend": "placeID", "goal": {"rating": 2}, } if limit: rec_query['limit'] = int(limit) res = aito_api.recommend(client=client, query=rec_query) return res.json['hits']
def create_job( client: AitoClient, job_endpoint: Optional[str] = None, query: Optional[Union[List, Dict]] = None, request_obj: Optional[Union[aito_requests.QueryAPIRequest, aito_requests.CreateJobRequest]] = None, ) -> aito_responses.CreateJobResponse: """Create a `job <https://aito.ai/docs/api/#post-api-v1-jobs-query>`__ for a query that takes longer than 30 seconds to run :param client: the AitoClient instance :type client: AitoClient :param job_endpoint: the job endpoint :type job_endpoint: Optional[str] :param query: the query for the endpoint :type query: Optional[Union[List, Dict]] :param request_obj: a :class:`.CreateJobRequest` or an :class:`.QueryAPIRequest` instance :type request_obj: Optional[Union[aito_requests.QueryAPIRequest, aito_requests.CreateJobRequest]] :return: job information :rtype: Dict """ create_job_req = _create_job_request(job_endpoint=job_endpoint, query=query, request_obj=request_obj) resp = client.request(request_obj=create_job_req) return resp
def grocery_demo_client(): return AitoClient(get_env_var('AITO_GROCERY_DEMO_INSTANCE_URL'), get_env_var('AITO_GROCERY_DEMO_API_KEY'))
def default_client(): return AitoClient(get_env_var('AITO_INSTANCE_URL'), get_env_var('AITO_API_KEY'))