def test_get_request_exception(self, mock_request): mock_request.return_value = MockReturnValue(status=500) mock_request.side_effect = Exception("Custom error") with pytest.raises(utils.APIError) as e: utils.get_request(url) assert re.match("Custom error", str(e.value))
def get_asset_subtree(asset_id="", depth=None, **kwargs): """Returns assets with provided assetId. Args: asset_id (str): The asset id of the top asset to get. depth (int): Get subassets this many levels below the top asset. Keyword Arguments: limit (int): The maximum nuber of assets to be returned. cursor (str): Cursor to use for paging through results. api_key (str): Your api-key. project (str): Project name. Returns: v04.dto.AssetResponse: A data object containing the requested assets with several getter methods with different output formats. """ api_key, project = config.get_config_variables(kwargs.get("api_key"), kwargs.get("project")) url = config.get_base_url( api_version=0.4) + "/projects/{}/assets/{}".format(project, asset_id) params = { "depth": depth, "limit": kwargs.get("limit", constants.LIMIT), "cursor": kwargs.get("cursor") } headers = {"api-key": api_key, "accept": "application/json"} res = utils.get_request(url, params=params, headers=headers, cookies=config.get_cookies()) return AssetResponse(res.json())
def get_row(database_name: str = None, table_name: str = None, row_key: str = None, api_key=None, project=None): """Returns a RawResponse Object containing a list of rows. Args: database_name (str): The database name to retrieve rows from. table_name (str): The table name to retrieve rows from. row_key (str): The key of the row to fetch. api_key (str): Your api-key. project (str): Project name. Returns: v04.dto.RawResponse: A data object containing the requested data with several getter methods with different output formats. """ api_key, project = config.get_config_variables(api_key, project) url = config.get_base_url(api_version=0.4) + "/projects/{}/raw/{}/{}/{}".format( project, database_name, table_name, row_key ) params = dict() headers = {"api-key": api_key, "content-type": "*/*", "accept": "application/json"} res = _utils.get_request(url=url, params=params, headers=headers, cookies=config.get_cookies()) return RawResponse(res.json())
def get_tables(database_name: str = None, limit: int = None, cursor: str = None, api_key=None, project=None): """Returns a RawObject containing a list of tables in a raw database. Args: database_name (str): The database name to retrieve tables from. limit (int): A limit on the amount of results to return. cursor (str): A cursor can be provided to navigate through pages of results. api_key (str): Your api-key. project (str): Project name. Returns: v04.dto.RawResponse: A data object containing the requested data with several getter methods with different output formats. """ api_key, project = config.get_config_variables(api_key, project) url = config.get_base_url(api_version=0.4) + "/projects/{}/raw/{}".format(project, database_name) params = dict() if not limit: params["limit"] = limit if not cursor: params["cursor"] = cursor headers = {"api-key": api_key, "content-type": "*/*", "accept": "application/json"} res = _utils.get_request(url=url, params=params, headers=headers, cookies=config.get_cookies()) return RawResponse(res.json())
def get_latest(name, **kwargs): """Returns a LatestDatapointObject containing the latest datapoint for the given timeseries. Args: name (str): The name of the timeseries to retrieve data for. Keyword Arguments: api_key (str): Your api-key. project (str): Project name. Returns: v05.dto.LatestDatapointsResponse: A data object containing the requested data with several getter methods with different output formats. """ api_key, project = config.get_config_variables(kwargs.get("api_key"), kwargs.get("project")) url = config.get_base_url( api_version=0.5) + "/projects/{}/timeseries/latest/{}".format( project, quote(name, safe="")) headers = {"api-key": api_key, "accept": "application/json"} res = _utils.get_request(url, headers=headers, cookies=config.get_cookies()) return LatestDatapointResponse(res.json())
def download_file(id, get_contents=False, **kwargs): """Get list of files matching query. Args: id (int): Path to file to upload, if omitted a upload link will be returned. get_contents (bool, optional): Boolean to determince whether or not to return file contents as string. Default is False and download url is returned. Keyword Args: api_key (str, optional): Your api-key. project (str, optional): Project name. Returns: str: Download link if get_contents is False else file contents. """ api_key, project = config.get_config_variables(kwargs.get("api_key"), kwargs.get("project")) url = config.get_base_url( api_version=0.4) + "/projects/{}/storage/{}".format(project, id) headers = {"api-key": api_key, "accept": "application/json"} res = _utils.get_request(url=url, headers=headers, cookies=config.get_cookies()) if get_contents: dl_link = res.json()["data"] res = requests.get(dl_link) return res.content return res.json()["data"]
def get_assets(name=None, path=None, description=None, metadata=None, depth=None, fuzziness=None, **kwargs): """Returns assets matching provided description. Args: name (str): The name of the asset(s) to get. path (str): The path of the subtree to search in. description (str): Search query. metadata (dict): The metadata values used to filter the results. depth (int): Get sub assets up oto this many levels below the specified path. fuzziness (int): The degree of fuzziness in the name matching. Keyword Arguments: limit (int): The maximum number of assets to be returned. cursor (str): Cursor to use for paging through results. api_key (str): Your api-key. project (str): Project name. Returns: v05.dto.AssetListResponse: A data object containing the requested assets with several getter methods with different output formats. """ api_key, project = config.get_config_variables(kwargs.get("api_key"), kwargs.get("project")) url = config.get_base_url( api_version=0.5) + "/projects/{}/assets".format(project) params = { "name": name, "description": description, "path": path, "metadata": str(metadata) if metadata else None, "depth": depth, "fuzziness": fuzziness, "cursor": kwargs.get("cursor"), "limit": kwargs.get("limit", constants.LIMIT), } headers = {"api-key": api_key, "accept": "application/json"} res = utils.get_request(url, params=params, headers=headers, cookies=config.get_cookies()) return AssetListResponse(res.json())
def get_event(event_id, **kwargs): """Returns a EventResponse containing an event matching the id. Args: event_id (int): The event id. Keyword Arguments: api_key (str): Your api-key. project (str): Project name. Returns: v05.dto.EventResponse: A data object containing the requested event. """ api_key, project = config.get_config_variables(kwargs.get("api_key"), kwargs.get("project")) url = config.get_base_url(api_version=0.5) + "/projects/{}/events/{}".format(project, event_id) headers = {"api-key": api_key, "content-type": "application/json", "accept": "application/json"} res = _utils.get_request(url, headers=headers, cookies=config.get_cookies()) return EventResponse(res.json())
def get_file_info(id, **kwargs): """Returns information about a file. Args: id (int): Id of the file. Keyword Args: api_key (str, optional): Your api-key. project (str, optional): Project name. Returns: v04.dto.FileInfoResponse: A data object containing the requested file information. """ api_key, project = config.get_config_variables(kwargs.get("api_key"), kwargs.get("project")) url = config.get_base_url( api_version=0.4) + "/projects/{}/storage/{}/info".format(project, id) headers = {"api-key": api_key, "accept": "application/json"} res = _utils.get_request(url, headers=headers) return FileInfoResponse(res.json())
def get_asset(asset_id, **kwargs): """Returns the asset with the provided assetId. Args: asset_id (int): The asset id of the top asset to get. Keyword Arguments: api_key (str): Your api-key. project (str): Project name. Returns: v05.dto.AssetResponse: A data object containing the requested assets with several getter methods with different output formats. """ api_key, project = config.get_config_variables(kwargs.get("api_key"), kwargs.get("project")) url = config.get_base_url( api_version=0.5) + "/projects/{}/assets/{}/subtree".format( project, asset_id) headers = {"api-key": api_key, "accept": "application/json"} res = utils.get_request(url, headers=headers, cookies=config.get_cookies()) return AssetResponse(res.json())
def test_get_request_failed(self, mock_request): mock_request.return_value = MockReturnValue(status=400, json_data={"error": "Client error"}) with pytest.raises(utils.APIError) as e: utils.get_request(url) assert re.match("Client error[\n]X-Request_id", str(e.value)) mock_request.return_value = MockReturnValue(status=500, content="Server error") with pytest.raises(utils.APIError) as e: utils.get_request(url) assert re.match("Server error[\n]X-Request_id", str(e.value)) mock_request.return_value = MockReturnValue(status=500, json_data={"error": "Server error"}) with pytest.raises(utils.APIError) as e: utils.get_request(url) assert re.match("Server error[\n]X-Request_id", str(e.value))
def get_databases(limit: int = None, cursor: str = None, api_key=None, project=None): """Returns a RawObject containing a list of raw databases. Args: limit (int): A limit on the amount of results to return. cursor (str): A cursor can be provided to navigate through pages of results. api_key (str): Your api-key. project (str): Project name. Returns: v05.dto.RawResponse: A data object containing the requested data with several getter methods with different output formats. """ api_key, project = config.get_config_variables(api_key, project) url = config.get_base_url( api_version=0.5) + "/projects/{}/raw".format(project) params = {"limit": limit, "cursor": cursor} headers = { "api-key": api_key, "content-type": "*/*", "accept": "application/json" } res = _utils.get_request(url=url, params=params, headers=headers, cookies=config.get_cookies()) return RawResponse(res.json())
def get_timeseries(prefix=None, description=None, include_metadata=False, asset_id=None, path=None, **kwargs): """Returns a TimeseriesObject containing the requested timeseries. Args: prefix (str): List timeseries with this prefix in the name. description (str): Filter timeseries taht contains this string in its description. include_metadata (bool): Decide if the metadata field should be returned or not. Defaults to False. asset_id (int): Get timeseries related to this asset. path (str): Get timeseries under this asset path branch. Keyword Arguments: limit (int): Number of results to return. api_key (str): Your api-key. project (str): Project name. autopaging (bool): Whether or not to automatically page through results. If set to true, limit will be disregarded. Defaults to False. Returns: v05.dto.TimeSeriesResponse: A data object containing the requested timeseries with several getter methods with different output formats. """ api_key, project = config.get_config_variables(kwargs.get("api_key"), kwargs.get("project")) url = config.get_base_url( api_version=0.5) + "/projects/{}/timeseries".format(project) headers = {"api-key": api_key, "accept": "application/json"} params = { "q": prefix, "description": description, "includeMetadata": include_metadata, "assetId": asset_id, "path": path, "limit": kwargs.get("limit", 10000) if not kwargs.get("autopaging") else 10000, } time_series = [] res = _utils.get_request(url=url, headers=headers, params=params, cookies=config.get_cookies()) time_series.extend(res.json()["data"]["items"]) next_cursor = res.json()["data"].get("nextCursor") while next_cursor and kwargs.get("autopaging"): params["cursor"] = next_cursor res = _utils.get_request(url=url, headers=headers, params=params, cookies=config.get_cookies()) time_series.extend(res.json()["data"]["items"]) next_cursor = res.json()["data"].get("nextCursor") return TimeSeriesResponse({ "data": { "nextCursor": next_cursor, "previousCursor": res.json()["data"].get("previousCursor"), "items": time_series, } })
def test_get_request(self, mock_request): mock_request.return_value = MockReturnValue(json_data=RESPONSE) response = utils.get_request(url) assert response.status_code == 200 assert len(response.json()['data']['items']) == len(RESPONSE)
def _get_datapoints_user_defined_limit(name, aggregates, granularity, start, end, limit, **kwargs): """Returns a DatapointsResponse object with the requested data. No paging or parallelizing is done. Args: name (str): The name of the timeseries to retrieve data for. aggregates (list): The list of aggregate functions you wish to apply to the data. Valid aggregate functions are: 'average/avg, max, min, count, sum, interpolation/int, stepinterpolation/step'. granularity (str): The granularity of the aggregate values. Valid entries are : 'day/d, hour/h, minute/m, second/s', or a multiple of these indicated by a number as a prefix e.g. '12hour'. start (Union[str, int, datetime]): Get datapoints after this time. Format is N[timeunit]-ago where timeunit is w,d,h,m,s. E.g. '2d-ago' will get everything that is up to 2 days old. Can also send time in ms since epoch or a datetime object which will be converted to ms since epoch UTC. end (Union[str, int, datetime]): Get datapoints up to this time. Same format as for start. limit (str): Max number of datapoints to return. Max is 100,000. Keyword Arguments: protobuf (bool): Download the data using the binary protobuf format. Only applicable when getting raw data. Defaults to True. api_key (str): Your api-key. Obligatory in this helper method. project (str): Project name. Obligatory in this helper method. Returns: v05.dto.DatapointsResponse: A data object containing the requested data with several getter methods with different output formats. """ api_key, project = kwargs.get("api_key"), kwargs.get("project") url = config.get_base_url( api_version=0.5) + "/projects/{}/timeseries/data/{}".format( project, quote(name, safe="")) use_protobuf = kwargs.get("protobuf", True) and aggregates is None params = { "aggregates": aggregates, "granularity": granularity, "limit": limit, "start": start, "end": end } headers = { "api-key": api_key, "accept": "application/protobuf" if use_protobuf else "application/json" } res = _utils.get_request(url, params=params, headers=headers) if use_protobuf: ts_data = _api_timeseries_data_v2_pb2.TimeseriesData() ts_data.ParseFromString(res.content) res = [{ "timestamp": p.timestamp, "value": p.value } for p in ts_data.numericData.points] else: res = res.json()["data"]["items"][0]["datapoints"] return DatapointsResponse( {"data": { "items": [{ "name": name, "datapoints": res }] }})
def _get_datapoints_helper(name, aggregates=None, granularity=None, start=None, end=None, **kwargs): """Returns a list of datapoints for the given query. This method will automate paging for the given time period. Args: name (str): The name of the timeseries to retrieve data for. aggregates (list): The list of aggregate functions you wish to apply to the data. Valid aggregate functions are: 'average/avg, max, min, count, sum, interpolation/int, stepinterpolation/step'. granularity (str): The granularity of the aggregate values. Valid entries are : 'day/d, hour/h, minute/m, second/s', or a multiple of these indicated by a number as a prefix e.g. '12hour'. start (Union[str, int, datetime]): Get datapoints after this time. Format is N[timeunit]-ago where timeunit is w,d,h,m,s. E.g. '2d-ago' will get everything that is up to 2 days old. Can also send time in ms since epoch or a datetime object which will be converted to ms since epoch UTC. end (Union[str, int, datetime]): Get datapoints up to this time. Same format as for start. Keyword Arguments: protobuf (bool): Download the data using the binary protobuf format. Only applicable when getting raw data. Defaults to True. api_key (str): Your api-key. Obligatory in this helper method. project (str): Project name. Obligatory in this helper method. Returns: list of datapoints: A list containing datapoint dicts. """ api_key, project = kwargs.get("api_key"), kwargs.get("project") url = config.get_base_url( api_version=0.5) + "/projects/{}/timeseries/data/{}".format( project, quote(name, safe="")) use_protobuf = kwargs.get("protobuf", True) and aggregates is None limit = _constants.LIMIT if aggregates is None else _constants.LIMIT_AGG params = { "aggregates": aggregates, "granularity": granularity, "limit": limit, "start": start, "end": end } headers = { "api-key": api_key, "accept": "application/protobuf" if use_protobuf else "application/json" } datapoints = [] while (not datapoints or len(datapoints[-1]) == limit) and params["end"] > params["start"]: res = _utils.get_request(url, params=params, headers=headers) if use_protobuf: ts_data = _api_timeseries_data_v2_pb2.TimeseriesData() ts_data.ParseFromString(res.content) res = [{ "timestamp": p.timestamp, "value": p.value } for p in ts_data.numericData.points] else: res = res.json()["data"]["items"][0]["datapoints"] if not res: break datapoints.append(res) latest_timestamp = int(datapoints[-1][-1]["timestamp"]) params["start"] = latest_timestamp + ( _utils.granularity_to_ms(granularity) if granularity else 1) dps = [] [dps.extend(el) for el in datapoints] return dps
def list_files(name=None, directory=None, file_type=None, source=None, **kwargs): """Get list of files matching query. Args: name (str, optional): List all files with this name. directory (str, optional): Directory to list files from. source (str, optional): List files coming from this source. file_type (str, optional): Type of files to list. Keyword Args: api_key (str, optional): Your api-key. project (str, optional): Project name. tag_id (list): Returns all files associated with this tagId. sort (str): Sort descending or ascending. 'ASC' or 'DESC'. limit (int): Number of results to return. autopaging (bool): Whether or not to automatically page through results. If set to true, limit will be disregarded. Defaults to False. Returns: v04.dto.FileListResponse: A data object containing the requested files information. """ api_key, project = config.get_config_variables(kwargs.get("api_key"), kwargs.get("project")) url = config.get_base_url( api_version=0.4) + "/projects/{}/storage".format(project) headers = {"api-key": api_key, "accept": "application/json"} params = { "tagId": kwargs.get("tag_id", None), "dir": directory, "name": name, "type": file_type, "source": source, "isUploaded": kwargs.get("is_uploaded", None), "sort": kwargs.get("sort", None), "limit": kwargs.get("limit", 100) if not kwargs.get("autopaging") else 10000, } file_list = [] res = _utils.get_request(url=url, headers=headers, params=params, cookies=config.get_cookies()) file_list.extend(res.json()["data"]["items"]) next_cursor = res.json()["data"].get("nextCursor", None) while next_cursor and kwargs.get("autopaging"): params["cursor"] = next_cursor res = _utils.get_request(url=url, headers=headers, params=params, cookies=config.get_cookies()) file_list.extend(res.json()["data"]["items"]) next_cursor = res.json()["data"].get("nextCursor", None) return FileListResponse({ "data": { "nextCursor": next_cursor, "previousCursor": res.json()["data"].get("previousCursor"), "items": file_list, } })
def get_events(type=None, sub_type=None, asset_id=None, **kwargs): """Returns an EventListReponse object containing events matching the query. Args: type (str): Type (class) of event, e.g. 'failure'. sub_type (str): Sub-type of event, e.g. 'electrical'. asset_id (str): Return events associated with this assetId. Keyword Arguments: sort (str): Sort descending or ascending. Default 'ASC'. cursor (str): Cursor to use for paging through results. limit (int): Return up to this many results. Maximum is 10000. Default is 25. has_description (bool): Return only events that have a textual description. Default null. False gives only those without description. min_start_time (string): Only return events from after this time. max_start_time (string): Only return events form before this time. api_key (str): Your api-key. project (str): Project name. autopaging (bool): Whether or not to automatically page through results. If set to true, limit will be disregarded. Defaults to False. Returns: v05.dto.EventListResponse: A data object containing the requested event. """ api_key, project = config.get_config_variables(kwargs.get("api_key"), kwargs.get("project")) url = config.get_base_url(api_version=0.5) + "/projects/{}/events".format(project) headers = {"api-key": api_key, "content-type": "application/json", "accept": "application/json"} if asset_id: params = { "assetId": asset_id, "sort": kwargs.get("sort"), "cursor": kwargs.get("cursor"), "limit": kwargs.get("limit", 25) if not kwargs.get("autopaging") else _constants.LIMIT_AGG, } else: params = { "type": type, "subtype": sub_type, "assetId": asset_id, "sort": kwargs.get("sort"), "cursor": kwargs.get("cursor"), "limit": kwargs.get("limit", 25) if not kwargs.get("autopaging") else _constants.LIMIT_AGG, "hasDescription": kwargs.get("has_description"), "minStartTime": kwargs.get("min_start_time"), "maxStartTime": kwargs.get("max_start_time"), } res = _utils.get_request(url, headers=headers, params=params, cookies=config.get_cookies()) events = [] events.extend(res.json()["data"]["items"]) next_cursor = res.json()["data"].get("nextCursor") while next_cursor and kwargs.get("autopaging"): params["cursor"] = next_cursor res = _utils.get_request(url=url, headers=headers, params=params, cookies=config.get_cookies()) events.extend(res.json()["data"]["items"]) next_cursor = res.json()["data"].get("nextCursor") return EventListResponse( { "data": { "nextCursor": next_cursor, "previousCursor": res.json()["data"].get("previousCursor"), "items": events, } } )