Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 14:20:48

0001 from __future__ import print_function
0002 import urllib, re, json, socket
0003 
0004 """
0005 Python object that enables connection to RR v3 API.
0006 Errors (not bugs!) and more welcome fixes/suggestions please 
0007 post to https://savannah.cern.ch/projects/cmsrunregistry/
0008 """
0009 
0010 class RRApiError(Exception):
0011     """
0012     API Exception class
0013     """
0014 
0015     def __init__(self, resp):
0016         """
0017         Construct exception by providing response object.
0018         """
0019         if isinstance(resp, str):
0020             self.message = resp
0021         else:
0022             self.url = resp.geturl()
0023             self.code = resp.getcode()
0024             self.stack = None
0025             for line in resp.read().split("\n"):
0026                 if self.stack == None:
0027                     m = re.search("<pre>(.*)", line)
0028                     if m != None:
0029                         self.stack = m.group(1)
0030                         m = re.search("^.+\.([^\.]+: .*)$", self.stack)
0031                         if m != None:
0032                             self.message = m.group(1)
0033                         else:
0034                             self.message = line
0035                 else:
0036                     m = re.search("(.*)</pre>", line)
0037                     if m != None:
0038                         self.stack = self.stack + "\n" + m.group(1)
0039                         break
0040                     else:
0041                         self.stack = self.stack + "\n" + line
0042 
0043     def __str__(self):
0044         """ Get message """
0045         return self.message
0046 
0047 class RRApi:
0048     """
0049     RR API object
0050     """
0051 
0052     def __init__(self, url, debug = False):
0053         """
0054         Construct API object.
0055         url: URL to RRv3 API, i.e. http://localhost:8080/rr_user
0056         debug: should debug messages be printed out? Verbose!
0057         """
0058         self.debug = debug
0059         self.url = re.sub("/*$", "/api/", url)
0060         self.app = self.get(["app"])
0061         self.dprint("app = ", self.app)
0062 
0063     def dprint(self, *args):
0064         """
0065         Print debug information
0066         """
0067         if self.debug: 
0068             print("RRAPI:", end=' ')
0069             for arg in args:
0070                 print(arg, end=' ') 
0071             print()
0072 
0073     def get(self, parts, data = None):
0074         """
0075         General API call (do not use it directly!)
0076         """
0077 
0078         #
0079         # Constructing request path
0080         #
0081 
0082         callurl = self.url + "/".join(urllib.quote(p) for p in parts)
0083 
0084         #
0085         # Constructing data payload
0086         #
0087 
0088         sdata = None
0089         if data != None:
0090             sdata = json.dumps(data)
0091 
0092         #
0093         # Do the query and respond
0094         #
0095 
0096         self.dprint(callurl, "with payload", sdata)
0097 
0098         resp = urllib.urlopen(callurl, sdata)
0099 
0100         has_getcode = "getcode" in dir(resp)
0101         if self.debug: 
0102             if has_getcode:
0103                 self.dprint("Response", resp.getcode(), " ".join(str(resp.info()).split("\r\n")))
0104             else:
0105                 self.dprint("Response", " ".join(str(resp.info()).split("\r\n")))
0106 
0107         if not has_getcode or resp.getcode() == 200:
0108             rdata = resp.read()
0109             if re.search("json", resp.info().gettype()):
0110                 try:
0111                     return json.loads(rdata)
0112                 except TypeError as e:
0113                     self.dprint(e)
0114                     return rdata
0115             else:
0116                 return rdata
0117         else:
0118             raise RRApiError(resp)
0119 
0120     def tags(self):
0121         """
0122         Get version tags (USER app only)
0123         """
0124         if self.app != "user":
0125             raise RRApiError("Tags call is possible only in user app")
0126         return self.get(["tags"])
0127 
0128     def workspaces(self):
0129         """
0130         Get workspaces (all apps)
0131         """
0132         return self.get(["workspaces"])
0133 
0134     def tables(self, workspace):
0135         """
0136         Get tables for workspace (all apps)
0137         """
0138         return self.get([workspace, "tables"])
0139 
0140     def columns(self, workspace, table):
0141         """
0142         Get columns for table for workspace (all apps)
0143         """
0144         return self.get([workspace, table, "columns"])
0145 
0146     def templates(self, workspace, table):
0147         """
0148         Get output templates for table for workspace (all apps)
0149         """
0150         return self.get([workspace, table, "templates"])
0151 
0152     def count(self, workspace, table, filter = None, query = None, tag = None):
0153         """
0154         Get number of rows for table for workspace with filter, query (all apps) or tag (USER app only)
0155         """
0156 
0157         #
0158         # Constructing request path
0159         #
0160 
0161         req = [ workspace, table ]
0162         if tag != None:
0163             if self.app != "user":
0164                 raise RRApiError("Tags are possible only in user app")
0165             else:
0166                 req.append(tag)
0167         req.append("count")
0168 
0169         #
0170         # Constructing filter/query payload
0171         #
0172 
0173         filters = {}
0174         if filter != None:
0175             filters['filter'] = filter
0176         if query != None:
0177             filters['query'] = query
0178 
0179         return int(self.get(req, filters))
0180 
0181     def data(self, workspace, table, template, columns = None, filter = None, query = None, order = None, tag = None):
0182         """
0183         Get data for table for workspace with filter, query (all apps) or tag (USER app only)
0184         """
0185 
0186         #
0187         # Check req parameters
0188         #
0189 
0190         if not isinstance(workspace, str):
0191             raise RRApiError("workspace parameter must be str")
0192 
0193         #
0194         # Constructing request path
0195         #
0196 
0197         req = [ workspace, table, template ]
0198         if columns != None:
0199             req.append(",".join(columns))
0200         else:
0201             req.append("all")
0202         if order != None:
0203             req.append(",".join(order))
0204         else:
0205             req.append("none")
0206         if tag != None:
0207             if self.app != "user":
0208                 raise RRApiError("Tags are possible only in user app")
0209             else:
0210                 req.append(tag)
0211         req.append("data")
0212 
0213         #
0214         # Constructing filter/query payload
0215         #
0216 
0217         filters = {}
0218         if filter != None:
0219             filters['filter'] = filter
0220         if query != None:
0221             filters['query'] = query
0222 
0223         return self.get(req, filters)
0224 
0225     def reports(self, workspace):
0226         """
0227         Get available reports (USER app only)
0228         """
0229         if self.app != "user":
0230             raise RRApiError("Reports available only in user app")
0231         return self.get([workspace, "reports"])
0232     
0233     def report(self, workspace, report):
0234         """
0235         Get report data (USER app only)
0236         """
0237         if self.app != "user":
0238             raise RRApiError("Reports available only in user app")
0239         return self.get([workspace, report, "data"])
0240 
0241 
0242 if __name__ == '__main__':
0243 
0244     print("RR API library.")