f50aa23023cbc478df90deaded10321b75349e8b
chmalee
  Tue May 14 15:35:06 2019 -0700
Fixup python client before adding to userapps, refs #18869

diff --git src/hg/hubApi/tests/pythonClient.py src/hg/hubApi/tests/pythonClient.py
index 2cf4d3c..48d6713 100755
--- src/hg/hubApi/tests/pythonClient.py
+++ src/hg/hubApi/tests/pythonClient.py
@@ -1,166 +1,147 @@
 #!/bin/env python
 
 """
 This code is inspired by the Ensembl python client
 https://github.com/Ensembl/ensembl-rest/wiki/Example-Python-Client
 """
 import argparse
 import json
 import sys
+from collections import OrderedDict
 
 # support python2 and 3
 try:
     from urllib.parse import urlparse, urlencode
     from urllib.request import urlopen, Request
     from urllib.error import HTTPError
 except ImportError:
     from urlparse import urlparse
     from urllib import urlencode
     from urllib2 import urlopen, Request, HTTPError
 
-serverName = "https://api-test.gi.ucsc.edu"
-endpoints = ["/list/publicHubs", "/list/ucscGenomes", "/list/hubGenomes",
-    "/list/tracks", "/list/chromosomes", "/getData/sequence", "/getData/track"]
-parameterList = ["hubUrl", "genome", "db", "track", "chrom", "start", "end",
-    "maxItemsOutput", "trackLeavesOnly"]
+serverName = "https://api.genome.ucsc.edu"
 
 def parseCommandLine():
     parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
-        description="Test accessing UCSC Genome Browser API",
+        description="Command line utility for UCSC Genome Browser API access",
         epilog="Example usage:\npythonClient.py \"/getData/track\" "
-        "\"track=gold;db=hg38;chrom=chrM;maxItemsOutput=2\"")
-    parser.add_argument("endpoint", nargs='?',
+        "\"track=gold;genome=hg38;chrom=chrM;maxItemsOutput=2\"")
+    parser.add_argument("endpoint", nargs='?', default="",
         help="Endpoint string like \"/list/tracks\" or \"/getData/track/\"", type=str)
-    parser.add_argument("parameters", nargs='?',
+    parser.add_argument("parameters", nargs='?', default="",
         help="Parameters to endpoints. semi-colon separated key=value formatted string, "
-        "like \"db=hg38;chrom=chrM;maxItemsOutput=2\"",type=str)
-    parser.add_argument("-test0", action="store_true", default=False,
-        help="Run special test")
+        "like \"genome=hg38;chrom=chrM;maxItemsOutput=2\"",type=str)
     parser.add_argument("-p", "--pretty-print", action="store_true", default=False,
         help="Print json response with newlines")
-    parser.add_argument("--show-endpoints", action="store_true", default=False,
-        help="List the supported endpoints")
-    parser.add_argument("--show-arguments", action="store_true", default=False,
-        help="List the supported arguments")
     parser.add_argument("--debug", action="store_true", default=False,
-        help="Print final URL of the request.")
+        help="Print final URL of the request")
+    parser.add_argument("-test0", action="store_true", default=False,
+        help="Run special test")
+    parser.add_argument("-getDnaExample", action="store_true", default=False,
+        help="Show example query for fetching Human GRCh38(hg38) DNA sequence")
     return parser
 
 def tryJsonRequest(requestUrl):
     """
     Wrap call to urlopen in try/except and exit on an HTTP error.
     Returns json response if request is good.
     """
     data = None
     try:
         request = Request(requestUrl)
         response = urlopen(request)
         content = response.read()
         if content:
-            data = json.loads(content)
+            data = json.loads(content, object_pairs_hook=OrderedDict)
     except HTTPError as e:
         if e.code == 400: # does this work for other status codes?
-            msg = json.loads(e.read())
+            msg = json.loads(e.read(), object_pairs_hook=OrderedDict)
             sys.stderr.write("Error: %s\n" % msg["error"])
             sys.exit(1)
         else:
             sys.stderr.write("Request %s failed with HTTP status %s\nreason:%s\n" %
                 (requestUrl, e.code, e.reason))
         sys.exit(1)
     return data
 
+def runGetDnaExample(prettyPrint=False):
+    """
+    Run test of getting short DNA sequence from the hg38 assembly and exit.
+    """
+    req = serverName + "/getData/sequence?genome=hg38;chrom=chr1;start=11110531;end=11110538"
+    data = tryJsonRequest(req)
+    if data:
+        print("Example request for obtaining DNA sequence:\n%s" % req)
+        if prettyPrint:
+            print(json.dumps(data, indent=4, separators=(" , "," : ")))
+        else:
+            print(json.dumps(data))
+    sys.exit(0)
+
 def runTest0(prettyPrint=False):
     """
     Run test of getting public hub data for "Plants" and print UCSC info
-    for the hg38 db and exit
+    for the hg38 genome and exit
     """
     hubRequest =  serverName + "/list/publicHubs"
     hg38Request = serverName + "/list/ucscGenomes"
 
     # do plants hub test first
     data = tryJsonRequest(hubRequest)
     if data:
         plantData = None
         for obj in data['publicHubs']:
             if obj['shortLabel'] == 'Plants':
                 plantData = obj
         if plantData is not None:
             print("Plants public hub data")
             if prettyPrint:
                 print(json.dumps(plantData,indent=4, separators=(",",":")))
             else:
                 print(json.dumps(plantData))
 
     # now do ucsc hg38 test
     data = tryJsonRequest(hg38Request)
     if data:
         hg38Data = None
         if data['ucscGenomes']['hg38']:
             hg38Data = data['ucscGenomes']['hg38']
         if hg38Data is not None:
             print("hg38/Human information")
             if prettyPrint:
                 print(json.dumps(hg38Data,indent=4, separators=(",",":")))
             else:
                 print(json.dumps(hg38Data))
     sys.exit(0)
 
 def main():
     cmd = parseCommandLine()
     args = cmd.parse_args()
     req =  serverName
 
     if len(sys.argv) == 1:
         cmd.print_help()
         sys.exit(0)
 
     # run special test
     if args.test0:
         runTest0(args.pretty_print)
 
-    # check for the show arguments first and exit early
-    if args.show_endpoints:
-        print("Currently supported endpoints:\n\t%s" % ("\n\t".join(endpoints)))
-        sys.exit(0)
-    if args.show_arguments:
-        print("Currently supported parameters to endpoint functions:\n\t%s" %
-            ("\n\t".join(parameterList)))
-        sys.exit(0)
+    if args.getDnaExample:
+        runGetDnaExample(args.pretty_print)
 
-    # check endpoints
-    if args.endpoint:
-        if args.endpoint not in endpoints:
-            sys.stderr.write("Error: Endpoint '%s' not supported.\n"
-                "Currently supported endpoints are:\n\t%s\n\n" %
-                (args.endpoint, "\n\t".join(endpoints)))
-            cmd.print_help()
-            sys.exit(1)
-        req += args.endpoint
-
-    # check params formatted correctly
-    if args.parameters:
-        params = args.parameters.split(";")
-        for param in params:
-            arg = param.split("=")[0]
-            if arg == param or arg not in parameterList:
-                sys.stderr.write("Unsupported parameter '%s'. "
-                    "Currently supported parameters to endpoints:\n\t%s\n"
-                    "Please format parameters as arg=val.\n\n" %
-                    (arg, "\n\t".join(parameterList)))
-                cmd.print_help()
-                sys.exit(1)
-        req += "?" + args.parameters
+    req += args.endpoint + "?" + args.parameters
 
     # make http request and print the output
     data = None
     if args.debug:
         print("request URL: %s\n" % req)
     data = tryJsonRequest(req)
     if data:
         if args.pretty_print:
             print(json.dumps(data, indent=4, separators=(",",":")))
         else:
             print(json.dumps(data))
 
 if __name__ == "__main__":
     main()