""" Common methods used by the API sample scripts. """ import json import logging import sys from urllib.error import HTTPError from urllib.request import ( Request, urlopen, ) log = logging.getLogger(__name__) def make_url(api_key, url, args=None): """ Adds the API Key to the URL if it's not already there. """ if args is None: args = [] argsep = "&" if "?" not in url: argsep = "?" if "?key=" not in url and "&key=" not in url: args.insert(0, ("key", api_key)) return url + argsep + "&".join("=".join(t) for t in args) def get(api_key, url): """ Do the actual GET. """ url = make_url(api_key, url) try: return json.loads(urlopen(url).read()) except ValueError as e: print(f"URL did not return JSON data: {e}") sys.exit(1) def post(api_key, url, data): """ Do the actual POST. """ url = make_url(api_key, url) req = Request(url, headers={"Content-Type": "application/json"}, data=json.dumps(data)) return json.loads(urlopen(req).read()) def put(api_key, url, data): """ Do the actual PUT """ url = make_url(api_key, url) req = Request(url, headers={"Content-Type": "application/json"}, data=json.dumps(data)) req.get_method = lambda: "PUT" return json.loads(urlopen(req).read()) def __del(api_key, url, data): """ Do the actual DELETE """ url = make_url(api_key, url) req = Request(url, headers={"Content-Type": "application/json"}, data=json.dumps(data)) req.get_method = lambda: "DELETE" return json.loads(urlopen(req).read()) def display(api_key, url, return_formatted=True): """ Sends an API GET request and acts as a generic formatter for the JSON response. """ try: r = get(api_key, url) except HTTPError as e: print(e) print(e.read(1024)) # Only return the first 1K of errors. sys.exit(1) if not return_formatted: return r elif isinstance(r, list): # Response is a collection as defined in the REST style. print("Collection Members") print("------------------") for n, i in enumerate(r): if isinstance(i, str): print(f" {i}") else: # All collection members should have a name in the response. # url is optional if "url" in i: print("#{}: {}".format(n + 1, i.pop("url"))) if "name" in i: print(f" name: {i.pop('name')}") try: for k, v in i.items(): print(f" {k}: {v}") except AttributeError: for item in i: print(item) print("") print(f"{len(r)} element(s) in collection") elif isinstance(r, dict): # Response is an element as defined in the REST style. print("Member Information") print("------------------") for k, v in r.items(): print(f"{k}: {v}") elif isinstance(r, str): print(r) else: print(f"response is unknown type: {type(r)}") def submit(api_key, url, data, return_formatted=True): """ Sends an API POST request and acts as a generic formatter for the JSON response. 'data' will become the JSON payload read by Galaxy. """ try: r = post(api_key, url, data) except HTTPError as e: if return_formatted: print(e) print(e.read(1024)) sys.exit(1) else: return "Error. " + str(e.read(1024)) if not return_formatted: return r print("Response") print("--------") if isinstance(r, list): # Currently the only implemented responses are lists of dicts, because # submission creates some number of collection elements. for i in r: if isinstance(i, dict): if "url" in i: print(i.pop("url")) else: print("----") if "name" in i: print(f" name: {i.pop('name')}") for k, v in i.items(): print(f" {k}: {v}") else: print(i) else: print(r) def update(api_key, url, data, return_formatted=True): """ Sends an API PUT request and acts as a generic formatter for the JSON response. 'data' will become the JSON payload read by Galaxy. """ try: r = put(api_key, url, data) except HTTPError as e: if return_formatted: print(e) print(e.read(1024)) sys.exit(1) else: return "Error. " + str(e.read(1024)) if not return_formatted: return r print("Response") print("--------") print(r) def delete(api_key, url, data, return_formatted=True): """ Sends an API DELETE request and acts as a generic formatter for the JSON response. 'data' will become the JSON payload read by Galaxy. """ try: r = __del(api_key, url, data) except HTTPError as e: if return_formatted: print(e) print(e.read(1024)) sys.exit(1) else: return "Error. " + str(e.read(1024)) if not return_formatted: return r print("Response") print("--------") print(r)