From dec4e7f136f423fbc741d5734abcb3581a922e6e Mon Sep 17 00:00:00 2001 From: ermisw Date: Fri, 5 May 2023 15:31:09 +0200 Subject: [PATCH] fix --- KeyRequestParser.egg-info/PKG-INFO | 2 +- build/lib/KRParser/krparser.py | 3 +- build/lib/__init__.py | 0 build/lib/helper.py | 46 ---- build/lib/keyrequests.py | 157 -------------- build/lib/krparser.py | 303 --------------------------- build/lib/patterns.py | 96 --------- dist/KeyRequestParser-0.1-py3.10.egg | Bin 15085 -> 0 bytes dist/KeyRequestParser-0.2-py3.10.egg | Bin 29585 -> 0 bytes dist/KeyRequestParser-0.4-py3.10.egg | Bin 0 -> 15308 bytes 10 files changed, 3 insertions(+), 604 deletions(-) delete mode 100644 build/lib/__init__.py delete mode 100644 build/lib/helper.py delete mode 100644 build/lib/keyrequests.py delete mode 100644 build/lib/krparser.py delete mode 100644 build/lib/patterns.py delete mode 100644 dist/KeyRequestParser-0.1-py3.10.egg delete mode 100644 dist/KeyRequestParser-0.2-py3.10.egg create mode 100644 dist/KeyRequestParser-0.4-py3.10.egg diff --git a/KeyRequestParser.egg-info/PKG-INFO b/KeyRequestParser.egg-info/PKG-INFO index 0ef3826..eb80030 100644 --- a/KeyRequestParser.egg-info/PKG-INFO +++ b/KeyRequestParser.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: KeyRequestParser -Version: 0.2 +Version: 0.4 License: MIT Parses Keyrequests diff --git a/build/lib/KRParser/krparser.py b/build/lib/KRParser/krparser.py index 29c3d0c..7305ba0 100644 --- a/build/lib/KRParser/krparser.py +++ b/build/lib/KRParser/krparser.py @@ -1,6 +1,7 @@ import re -from key_request_parser import patterns, keyrequests, helper +from KRParser import patterns, keyrequests, helper + from enum import Flag, auto import logging diff --git a/build/lib/__init__.py b/build/lib/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/build/lib/helper.py b/build/lib/helper.py deleted file mode 100644 index cace378..0000000 --- a/build/lib/helper.py +++ /dev/null @@ -1,46 +0,0 @@ -import requests -from requests.adapters import HTTPAdapter, Retry - -def get_requestOld(url, headers, params): - #try: - response = requests.get(url, headers=headers, params=params, verify=False) - response.raise_for_status() - # except requests.exceptions.HTTPError as errh: - # return "An Http Error occurred:" + repr(errh) - # except requests.exceptions.ConnectionError as errc: - # return "An Error Connecting to the API occurred:" + repr(errc) - # except requests.exceptions.Timeout as errt: - # return "A Timeout Error occurred:" + repr(errt) - # except requests.exceptions.RequestException as err: - # return "An Unknown Error occurred" + repr(err) - - return response - -def get_request(url, headers, params): - #try: - session = requests.Session() - retry = Retry(connect=3, backoff_factor=10) - adapter = HTTPAdapter(max_retries=retry) - session.mount('http://', adapter) - session.mount('https://', adapter) - - #response = requests.get(url, headers=headers, params=params, verify=False) - response = session.get(url,headers=headers, params=params, verify=False) - - response.raise_for_status() - # except requests.exceptions.HTTPError as errh: - # return "An Http Error occurred:" + repr(errh) - # except requests.exceptions.ConnectionError as errc: - # return "An Error Connecting to the API occurred:" + repr(errc) - # except requests.exceptions.Timeout as errt: - # return "A Timeout Error occurred:" + repr(errt) - # except requests.exceptions.RequestException as err: - # return "An Unknown Error occurred" + repr(err) - - return response - -def contains(list, filter): - for x in list: - if filter(x): - return True - return False \ No newline at end of file diff --git a/build/lib/keyrequests.py b/build/lib/keyrequests.py deleted file mode 100644 index a877da3..0000000 --- a/build/lib/keyrequests.py +++ /dev/null @@ -1,157 +0,0 @@ -try: - # Python 3 - from collections.abc import MutableSequence -except ImportError: - # Python 2.7 - from collections import MutableSequence - -class KeyRequestGroup(MutableSequence): - """A container for manipulating lists of hosts""" - def __init__(self, data=None): - """Initialize the class""" - super(KeyRequestGroup, self).__init__() - if (data is not None): - self._list = list(data) - else: - self._list = list() - - def __repr__(self): - return "<{0} {1}>".format(self.__class__.__name__, self._list) - - def __len__(self): - """List length""" - return len(self._list) - - def __getitem__(self, ii): - """Get a list item""" - if isinstance(ii, slice): - return self.__class__(self._list[ii]) - else: - return self._list[ii] - - def __delitem__(self, ii): - """Delete an item""" - del self._list[ii] - - def __setitem__(self, ii, val): - # optional: self._acl_check(val) - self._list[ii] = val - - def __str__(self): - return str(self._list) - - def createExistsQuery(self, val): - - query="type(service_method)" - - val['services'] = list(map(lambda x: x.replace("~","") , val['services'])) - val['methods'] = list(map(lambda x: x.replace("~","") , val['methods'])) - #case Service Names exists - if len(val["services"]) > 0: - if val["services"][0].startswith("SERVICE-"): - query+=",fromRelationship.isServiceMethodOfService(type(\"SERVICE\"),entityId(\""+'","'.join(val["services"])+"\"))" - else: - query+=",fromRelationship.isServiceMethodOfService(type(\"SERVICE\"),entityName.in(\""+'","'.join(val["services"])+"\"))" - - if len(val["methods"]) > 0: - if val["methods"][0].startswith("SERVICE_METHOD-"): - query+=",entityId(\""+'","'.join(val["methods"])+"\")" - else: - query+=",entityName.in(\""+'","'.join(val["methods"])+"\")" - - val["existsQuery"]= query - - # def createServiceResolveQuery(self, val): - # query="type(SERVICE)" - # val['services'] = list(map(lambda x: x.replace("~","") , val['services'])) - - # if len(val["services"]) > 0: - # if val["services"][0].startswith("SERVICE-"): - # query+=",entityId(\""+'","'.join(val["services"])+"\")" - # else: - # query+=",entityName.in(\""+'","'.join(val["services"])+"\")" - - # val["resolveServiceQuery"]= query - - - def insert(self, ii, val): - self.createExistsQuery(val) - - self._list.insert(ii, val) - - - - def append(self, val): - - for g in val: - - if len(self._list) == 0: - #self._list.insert(ii, val) - self.insert(len(self._list), g) - return - - for group in self._list: - if len(set(group["services"]) - set(g["services"])) > 0 or len(set(group["methods"]) - set(g["methods"])) > 0: - self.insert(len(self._list), g) - - - -class KR: - - # def getNotExistingKeyRequests(self): - # return [k for k in self.keyRequests if k['exists']==False] - - # def hasNotExistingKeyRequests(self): - # for k in self.keyRequests: - # if k['exists']==False: - # return True - - # return False - - # def getNoData1WKeyRequests(self): - # return [k for k in self.keyRequests if k['hasData_1W']==False and k['exists']==True] - - # def hasNoData1WKeyRequests(self): - # for k in self.keyRequests: - # if k['hasData_1W']==False and k['exists'] == True: - # return True - - # return False - - def getKeyRequestByHasData(self,label): - return [k for k in self.keyRequests if k['hasData'][label]==False] - - def hasNoData(self,label): - for k in self.keyRequests: - if k['hasData'][label]==False: - return True - - return False - - - - - def checkKeyRequestsHasData(self): - pass - - def mergeServices(self, listServices): - listOfServiceIds=[o["entityId"] for o in self.services] - - for s in listServices: - if s["entityId"] not in listOfServiceIds: - self.services.append(s) - - def __init__(self, - metadata, - matchedGroups: KeyRequestGroup = None): - self.metadata=metadata - - if matchedGroups == None: - self.matchedGroups = KeyRequestGroup() - else: - self.matchedGroups = keyRequests_groups - - self.keyRequests=[] - self.services=[] - - diff --git a/build/lib/krparser.py b/build/lib/krparser.py deleted file mode 100644 index 29c3d0c..0000000 --- a/build/lib/krparser.py +++ /dev/null @@ -1,303 +0,0 @@ -import re - -from key_request_parser import patterns, keyrequests, helper - -from enum import Flag, auto -import logging -import threading -import concurrent.futures -import time -from jsonmerge import merge - - - -class KROption(Flag): - VALIDATE_EXISTS = auto() - VALIDATE_HASDATA = auto() - RESOLVEKEYREQUETS = auto() - RESOLVESERVICES = auto() - -class KRParser: - #threadLimiter = threading.BoundedSemaphore(3) - patterns=[patterns.Pattern1(), patterns.Pattern2(), patterns.Pattern3(), patterns.Pattern5(), patterns.Pattern4() ] - lock = threading.Lock() - - def normalize(self,x): - #tmp=x.replace("~","") - tmp=x.replace("\n","") - #tmp=tmp.replace("\"/","\"") - #tmp=tmp.replace("\"/","") -_>was active - #tmp=tmp.replace("/\"","\"") - tmp=tmp.replace("/\"","") - tmp=tmp.replace("\"","") - tmp=tmp.replace("\t","") - - tmp=re.sub("([\s]*)\)", ")", tmp) - - - - tmp=re.sub("\([\s\n\r]*", "(", tmp) - tmp=re.sub("\,[\s\n\r]*", ",", tmp) - tmp=re.sub("\)[\s\n\r]*,", "),", tmp) - tmp=re.sub("in[\s\n\r]*\(", "in(", tmp) - - return tmp - - - def applyPatterns(self,subject): - groups=None - for p in self.patterns: - groups=p.parseServicesAndMethods(subject) - - if len(groups) > 0: - break - - return groups - - - def checkKeyRequetsHasData(self,kr, tfrom, DTAPIURL, DTAPIToken): - - DTAPIURL = DTAPIURL + "/api/v2/entities" - - headers = { - 'Content-Type': 'application/json', - 'Authorization': 'Api-Token ' + DTAPIToken - } - - for gid, group in enumerate(kr.matchedGroups): - params={"entitySelector": group["existsQuery"], "from":tfrom["tfrom"], "fields": "fromRelationships"} - response = helper.get_request(DTAPIURL, headers, params) - entities = (response.json())['entities'] - - if len(entities) > 0: - y=0 - for method in kr.keyRequests: - if method["groupId"] == gid: - found = [x for x in entities if x[method["comparer"]] == method[method["comparer"]]] - - if len(found) > 0: - method["hasData"][tfrom["label"]]=True - #method["displayName"]=found[0]["displayName"] - #method["entityId"]=found[0]["entityId"] - #method["services"]=found[0]["fromRelationships"]["isServiceMethodOfService"] - - # for idx,o in enumerate(method["services"]): - # tmpS=[p for p in kr.services if p["entityId"]==o["id"]] - # if len(tmpS)>0: - # method["services"][idx]=tmpS[0] - - else: - method["hasData"][tfrom["label"]]=False - - def resolveServices(self,services, DTAPIURL, DTAPIToken): - #DTAPIURL = DTAPIURL + "/api/v2/entities" - - headers = { - 'Content-Type': 'application/json', - 'Authorization': 'Api-Token ' + DTAPIToken - } - - for gid, service in enumerate(services): - query="type(SERVICE),entityId("+service["id"]+")" - - params=merge(self.serviceLookupParams,{"entitySelector": query}) - #params={"entitySelector": query,"from":"now-2y", "fields":"tags"} - response = helper.get_request(DTAPIURL, headers, params) - entities = (response.json())['entities'] - - if len(entities)>0: - services[gid]=entities[0] - - def resolveKeyRequests(self,kr, DTAPIURL, DTAPIToken, options): - DTAPIURL = DTAPIURL + "/api/v2/entities" - - headers = { - 'Content-Type': 'application/json', - 'Authorization': 'Api-Token ' + DTAPIToken - } - - - for gid, k in enumerate(kr.keyRequests): - try: - query="type(service_method)" - group=kr.matchedGroups[k["groupId"]] - - if len(group["services"])> 0: - if group["services"][0].startswith("SERVICE-"): - query+=",fromRelationship.isServiceMethodOfService(type(\"SERVICE\"),entityId(\""+'","'.join(group["services"])+"\"))" - else: - query+=",fromRelationship.isServiceMethodOfService(type(\"SERVICE\"),entityName.in(\""+'","'.join(group["services"])+"\"))" - - if k["comparer"]=="entityId": - query+=",entityId("+k["entityId"]+")" - else: - query+=",entityName.in(\""+k["displayName"]+"\")" - - params={"entitySelector": query, "from":"now-1y","fields": "fromRelationships"} - response = helper.get_request(DTAPIURL, headers, params) - entities = (response.json())['entities'] - - # if len(entities) > 1: - # kr.keyRequests[gid]['foundCount']=len(entities) - # print("Multiple keyrequest found: ") - - if len(entities)> 0: - kr.keyRequests[gid]["found"]=True - kr.keyRequests[gid]['foundCount']=len(entities) - kr.keyRequests[gid]["displayName"]=entities[0]["displayName"] - kr.keyRequests[gid]["entityId"]=entities[0]["entityId"] - - if "isServiceMethodOfService" in entities[0]["fromRelationships"]: - kr.keyRequests[gid]["services"]=entities[0]["fromRelationships"]["isServiceMethodOfService"] - - if KROption.RESOLVESERVICES in options and len( kr.keyRequests[gid]["services"])>0: - self.resolveServices(kr.keyRequests[gid]["services"], DTAPIURL, DTAPIToken) - - except Exception as err: - kr.keyRequests[gid]["exception"]="resolveKeyRequests failed: "+repr(err) - - - - #kr.mergeServices(entities) - - - def getKeyRequestsByServices(self, services): - #type(SERVICE_METHOD),fromRelationship.isServiceMethodOfService(type("SERVICE"),entityName.in("btc-user-composite-service - PROD")) - DTAPIURL = self.DTAPIURL + "/api/v2/entities" - headers = { - 'Content-Type': 'application/json', - 'Authorization': 'Api-Token ' + self.DTAPIToken - } - - if len(services) > 0: - if services[0].startswith("SERVICE-"): - query="type(service_method),fromRelationship.isServiceMethodOfService(type(\"SERVICE\"),entityId(\""+'","'.join(services)+"\"))" - else: - query="type(service_method),fromRelationship.isServiceMethodOfService(type(\"SERVICE\"),entityName.in(\""+'","'.join(services)+"\"))" - - params={"entitySelector": query} - response = helper.get_request(DTAPIURL, headers, params) - entities = (response.json())['entities'] - - return entities - - - def process(self, kr): - - for gid, group in enumerate(kr.matchedGroups): - - if len(group["services"]) > 0 and len(group["methods"])==0: - tmp_methods=self.getKeyRequestsByServices(group["services"]) - - for m in tmp_methods: - tmp={"displayName": None,"comparer": "entityId", "entityId":m["entityId"], "groupId":gid, "hasData":{}, "services":[], "found":False, "foundCount":0, "exception":""} #"exists":None, 'hasData_1W':None, - kr.keyRequests.append(tmp) - - for method in group["methods"]: - if method.startswith('SERVICE_METHOD-'): - tmp={"displayName": None,"comparer": "entityId", "entityId":method, "groupId":gid, "hasData":{}, "services":[], "found":False, "foundCount":0, "exception":""} #"exists":None, 'hasData_1W':None, - else: - tmp={"displayName":method,"comparer": "displayName", "entityId":None, "groupId":gid, "hasData":{}, "services":[], "found":False, "foundCount":0, "exception":""} #"exists":None, 'hasData_1W':None, - - kr.keyRequests.append(tmp) - - - - # for service in group["services"]: - # if service.startswith('SERVICE-'): - # tmp={"displayName": None,"comparer": "entityId", "entityId":service, "groupId":gid, "hasData":{}, "keyReuqests":[], "found":False, "foundCount":0, "exception":""} #"exists":None, 'hasData_1W':None, - # else: - # tmp={"displayName":service,"comparer": "displayName", "entityId":None, "groupId":gid, "hasData":{}, "keyReuqests":[], "found":False, "foundCount":0, "exception":""} #"exists":None, 'hasData_1W':None, - - # kr.services.append(tmp) - - - if self.options: - if KROption.RESOLVEKEYREQUETS in self.options: - self.resolveKeyRequests(kr,self.DTAPIURL, self.DTAPIToken, self.options) - - if KROption.VALIDATE_HASDATA in self.options: - self.checkKeyRequetsHasData(kr,{"label":"1W", "tfrom":"now-1w"},self.DTAPIURL, self.DTAPIToken) - self.checkKeyRequetsHasData(kr,{"label":"1M", "tfrom":"now-1M"},self.DTAPIURL, self.DTAPIToken) - # elif KROption.RESOLVEKEYREQUETS in self.options: - # self.checkKeyRequetsHasData(kr, {"label":"1W", "tfrom":"now-1w"},self.DTAPIURL, self.DTAPIToken) - # if KROption.RESOLVESERVICES in self.options: - # self.resolveServices(kr,self.DTAPIURL, self.DTAPIToken) - - return kr - - - def parseBySLO(self,index,row): - #normalize - print(index) - - try: - normFilter=self.normalize(row['filter']) - normExpresseion=self.normalize(row['metricExpression']) - - tmp_KR = keyrequests.KR({"sloName":row["name"], "env":row["env"], "metricExpression": normExpresseion, "filter": normFilter, "matchedGroups": None}) - - - #SLO with Filter - if normFilter.upper().startswith("TYPE(SERVICE_METHOD),") or normFilter.upper().startswith("TYPE(SERVICE),"): - subject=normFilter - else: - subject=normExpresseion - - groups=self.applyPatterns(subject) - - tmp_KR.matchedGroups.append(groups) - # for g in groups: - # #if g["methods"] != None and len(g["methods"]) > 0: - # tmp_KR.matchedGroups.append(g) - - #self.process(tmp_KR) - kr=self.process(tmp_KR) - with self.lock: - self.krs.append(kr) - - except Exception as err: - print(repr(err)) - #return self.process(tmp_KR) - - def parseBySLO_Threaded(self, slosF): - self.krs=[] - #i=1 - # threads = list() - # for index, row in slosF.iterrows(): - # logging.info("Main : create and start thread %d.", index) - # x = threading.Thread(target=self.parseBySLO, args=(row,)) - # threads.append(x) - # x.start() - - # #krs.append(krp.parseBySLO(row)) - - # for index, thread in enumerate(threads): - # logging.info("Main : before joining thread %d.", index) - # thread.join() - # logging.info("Main : thread %d done", index) - - # #resultSlos.extend(krs) - - - with concurrent.futures.ThreadPoolExecutor(10) as executor: - for index, row in slosF.iterrows(): - # if i % 25 == 0: - # time.sleep(0) - #args={index:index, } - executor.submit(self.parseBySLO, index,row) - # print(str(i)+"\n") - # i=i+1 - # x = threading.Thread(target=self.parseBySLO, args=(row,)) - # threads.append(x) - # x.start() - - return self.krs - - - def __init__(self, options: KROption=None ,serviceLookupParams={}, DTAPIURL=None, DTAPIToken=None ): - self.DTAPIURL= DTAPIURL - self.DTAPIToken=DTAPIToken - self.options=options - self.serviceLookupParams=merge({"from":"now-2y"},serviceLookupParams) - self.krs=[] \ No newline at end of file diff --git a/build/lib/patterns.py b/build/lib/patterns.py deleted file mode 100644 index ebd280b..0000000 --- a/build/lib/patterns.py +++ /dev/null @@ -1,96 +0,0 @@ -import re -import urllib - -class Pattern1: - - - def parseServicesAndMethods(self, metricExpression): - - #result = re.findall(r"type\(\"?service_method\"?\)[\s\n\r]*,[\s\n\r]*fromRelationship[\s\n\r]*\.[\s\n\r]*isServiceMethodOfService[\s\n\r]*\([\s\n\r]*type\(\"?service\"?\)[\s\n\r]*,[\s\n\r]*entityName[\s\n\r]*[\.]*[\s\n\r]*[in]*[\s\n\r]*\([\s\n\r]*([A-Z0-9\:\<\>\_\$\.\s\-\,\(\),\[\]\\\\/*]*)[\s\n\r]*\)[\s\n\r]*\)[\s\n\r]*,[\s\n\r]*entityName[\s\n\r]*[\.]*[\s\n\r]*[in]*[\s\n\r]*\([\s\n\r]*([A-Z0-9\:\<\>\_\$\.\s\-\,\(\),\[\]\\\\/*]*)\)[\s\n\r]*\)[\s\n\r]*\)[\s\n\r]*\)[\s\n\r]*\)[\s\n\r]*[\)]*", metricExpression,flags=re.IGNORECASE|re.X|re.MULTILINE) - #result = re.findall(r"type\(\"?service_method\"?\)[\s\n\r]*,[\s\n\r]*fromRelationship[\s\n\r]*\.[\s\n\r]*isServiceMethodOfService[\s\n\r]*\([\s\n\r]*type\(\"?service\"?\)[\s\n\r]*,[\s\n\r]*entityName[\s\n\r]*[\.]*[\s\n\r]*[in]*[\s\n\r]*\([\s\n\r]*([\"]*[^.*]*[\"]*)[\s\n\r]*\)[\s\n\r]*\)[\s\n\r]*\,[\s\n\r]*entityName[\s\n\r]*\.[in]*[\s\n\r]*\([\s\n\r]*([\"]*[^.*\)]*)", metricExpression,flags=re.IGNORECASE|re.X|re.MULTILINE) - - #result = re.findall(r"type\(\"?service_method\"?\)[\s\n\r]*,[\s\n\r]*fromRelationship[\s\n\r]*\.[\s\n\r]*isServiceMethodOfService[\s\n\r]*\([\s\n\r]*type\(\"?service\"?\)[\s\n\r]*,[\s\n\r]*entityName[\s\n\r]*[\.]*[\s\n\r]*[in]*[\s\n\r]*\([\s\n\r]*(\"[^.*]*\")[\s\n\r]*\)[\s\n\r]*\)[\s\n\r]*\,[\s\n\r]*entityName[\s\n\r]*\.[in]*[\s\n\r]*\([\s\n\r]*(\"[^.*]*)\)\"", metricExpression,flags=re.IGNORECASE|re.X|re.MULTILINE) - - #Endoce - metricExpression=re.sub(r'~([A-Z0-9\:\<\>\_\$\.\s\-\,\(\),\[\]\\\\/*]*)~', lambda m: str(urllib.parse.quote_plus(m.group(1))), metricExpression, flags=re.IGNORECASE|re.X|re.MULTILINE) - result = re.findall(r"type\(\"?service_method\"?\),fromRelationship\.isServiceMethodOfService\(type\(\"?service\"?\),entityName[\.]*[in]*\(([^\)]*)\)\)\,entityName[\.]*[in]*\(([^\)]*)\)", metricExpression,flags=re.IGNORECASE|re.X|re.MULTILINE) - #result = re.findall(r"type\(\"?service_method\"?\)[\s\n\r]*,[\s\n\r]*fromRelationship[\s\n\r]*\.[\s\n\r]*isServiceMethodOfService[\s\n\r]*\([\s\n\r]*type\(\"?service\"?\)[\s\n\r]*,[\s\n\r]*entityName[\s\n\r]*[\.]*[\s\n\r]*[in]*[\s\n\r]*\([\s\n\r]*([^\)]*)\)[\s\n\r]*\)[\s\n\r]*\,[\s\n\r]*entityName[\s\n\r]*[\.]*[\s\n\r]*[in]*\([\s\n\r]*([^\)]*)[\s\n\r]*\)", metricExpression,flags=re.IGNORECASE|re.X|re.MULTILINE) - #services=[] - #methods=[] - groups=[] - if result: - for r in result: - services=[s.strip() for s in urllib.parse.unquote_plus(r[0]).split(",")] - methods=[s.strip() for s in urllib.parse.unquote_plus(r[1]).split(",")] - groups.append({"services":services, "methods":methods}) - #return services, methods - return groups - -class Pattern2: - - def parseServicesAndMethods(self, metricExpression): - metricExpression=re.sub(r'~([A-Z0-9\:\<\>\_\$\.\s\-\,\(\),\[\]\\\\/*]*)~', lambda m: str(urllib.parse.quote_plus(m.group(1))), metricExpression, flags=re.IGNORECASE|re.X|re.MULTILINE) - result = re.findall(r"type\(\"?service_method\"?\),fromRelationship\.isServiceMethodOfService\(type\([~]*service[~]*\),entityName[\.]*[in]*\(([^\)]*)\),tag\(([^\)]*)\)\),entityName[\.]*[in]*\(([^\)]*)\)", metricExpression,flags=re.IGNORECASE|re.X|re.MULTILINE) - # services=[] - # methods=[] - groups=[] - if result: - for r in result: - services=[s.strip() for s in urllib.parse.unquote_plus(r[0]).split(",")] - methods=[s.strip() for s in urllib.parse.unquote_plus(r[2]).split(",")] - groups.append({"services":services, "methods":methods}) - - return groups - - - -class Pattern3: - - def parseServicesAndMethods(self, metricExpression): - metricExpression=re.sub(r'~([A-Z0-9\:\<\>\_\$\.\s\-\,\(\),\[\]\\\\/*]*)~', lambda m: str(urllib.parse.quote_plus(m.group(1))), metricExpression, flags=re.IGNORECASE|re.X|re.MULTILINE) - result = re.findall(r"type\(\"?service_method\"?\)[\s\n\r]*,[\s\n\r]*entityId[\s\n\r]*[\s\n\r]*\([\s\n\r]*[\s\n\r]*([^\)]*)[\s\n\r]*\)", metricExpression,flags=re.IGNORECASE|re.X|re.MULTILINE) - # services=[] - # methods=[] - groups=[] - if result: - for r in result: - methods=[s.strip() for s in urllib.parse.unquote_plus(r).split(",")] - groups.append({"services":[], "methods":methods}) - - return groups - -class Pattern4: - - def parseServicesAndMethods(self, metricExpression): - metricExpression=re.sub(r'~([A-Z0-9\:\<\>\_\$\.\s\-\,\(\),\[\]\\\\/*]*)~', lambda m: str(urllib.parse.quote_plus(m.group(1))), metricExpression, flags=re.IGNORECASE|re.X|re.MULTILINE) - result = re.findall(r"type\(\"?service\"?\)[\s\n\r]*,[\s\n\r]*[entityName|entityId].*[equals|in]*\(([^\)]*)\)", metricExpression,flags=re.IGNORECASE|re.X|re.MULTILINE) - - groups=[] - if result: - for r in result: - if not r: - #methods=[s.strip() for s in r.split(",")] - services=[s.strip() for s in urllib.parse.unquote_plus(r).split(",")] - groups.append({"services":services, "methods":[]}) - - return groups - -class Pattern5: - - def parseServicesAndMethods(self, metricExpression): - - #Endoce - metricExpression=re.sub(r'~([A-Z0-9\:\<\>\_\$\.\s\-\,\(\),\[\]\\\\/*]*)~', lambda m: str(urllib.parse.quote_plus(m.group(1))), metricExpression, flags=re.IGNORECASE|re.X|re.MULTILINE) - result = re.findall(r"type\(\"?service_method\"?\),fromRelationship\.isServiceMethodOfService\(type\(\"?service\"?\),entityName[\.]*[in]*\(([^\)]*)\)\)", metricExpression,flags=re.IGNORECASE|re.X|re.MULTILINE) - #result = re.findall(r"type\(\"?service_method\"?\)[\s\n\r]*,[\s\n\r]*fromRelationship[\s\n\r]*\.[\s\n\r]*isServiceMethodOfService[\s\n\r]*\([\s\n\r]*type\(\"?service\"?\)[\s\n\r]*,[\s\n\r]*entityName[\s\n\r]*[\.]*[\s\n\r]*[in]*[\s\n\r]*\([\s\n\r]*([^\)]*)\)[\s\n\r]*\)[\s\n\r]*\,[\s\n\r]*entityName[\s\n\r]*[\.]*[\s\n\r]*[in]*\([\s\n\r]*([^\)]*)[\s\n\r]*\)", metricExpression,flags=re.IGNORECASE|re.X|re.MULTILINE) - #services=[] - #methods=[] - groups=[] - if result: - for r in result: - if not r: - services=[s.strip() for s in urllib.parse.unquote_plus(r).split(",")] - #methods=[s.strip() for s in urllib.parse.unquote_plus(r[1]).split(",")] - groups.append({"services":services, "methods":[]}) - #return services, methods - return groups \ No newline at end of file diff --git a/dist/KeyRequestParser-0.1-py3.10.egg b/dist/KeyRequestParser-0.1-py3.10.egg deleted file mode 100644 index e96c9f148824eb604e26b9afbcd6220bebc746ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15085 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 literal 0 HcmV?d00001