Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-11-27 03:17:45

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