19 from Tool.tool
import getAst,getFileName,getParameter,getLastAPIParameter,resolvePythonExecutable
21 from Change.changeAnalyze
import para2Obj
40 print(f
"mapPos error, repairDict:{dic}")
69 for key
in dic.keys():
72 print(f
"findName error:{pos}")
86 paraStr=paraStr.replace(
' ',
'')
91 for i
in range(len(lst)):
98 if '(' not in para[0:pos]
and "'" not in para[0:pos]
and '"' not in para[0:pos]:
100 parameter.name=para[0:pos]
108 for k,subDict
in dic.items():
109 if 'posChange' in subDict:
110 if subDict[
'posChange']==parameter.position:
115 for k,subDict
in dic.items():
116 if parameter.position==k[1]:
117 if 'rename' in subDict:
118 parameter.name=subDict[
'rename']
119 elif 'replace' in subDict:
120 pos=subDict[
'replace'].find(
'=')
121 parameter.name=subDict[
'replace'][0:pos]
127 paraObjLst.append((parameter,1))
129 paraObjLst.append((parameter,0))
142 def fix(callAPI,repairDict,node,starFlag,twoStarFlag):
143 for n
in ast.iter_child_nodes(node):
144 fix(callAPI,repairDict,n,starFlag,twoStarFlag)
146 if isinstance(node,ast.Call):
148 callState=ast.unparse(node).replace(
' ',
'').replace(
'"',
'').replace(
"'",
'')
149 if callState==callAPI.replace(
' ',
'').replace(
'"',
'').replace(
"'",
''):
158 opDict=
mapPos(index,repairDict)
159 for op,v
in opDict.items():
164 insertParas.append((index,-1,para))
169 insertParas.append((index,-1,para))
173 insertParas.append((index,-1,para))
177 paraNode = ast.keyword(arg=v,value=ast.Name(id=s))
178 newKeyLst.append(paraNode)
182 insertParas.append((index,-1,ast.Name(id=v.split(
'=')[-1])))
185 insertParas.append((v,index,para))
188 insertParas.append((index,-1,para))
194 insertParas.sort(key=
lambda it:it[0])
195 for pos,moveFlag,para
in insertParas:
196 if pos<=len(newPosLst):
197 newPosLst.insert(pos,para)
202 paraName=
findName(moveFlag,repairDict)
205 paraNode=ast.keyword(arg=paraName,value=ast.Name(id=s))
206 newKeyLst.append(paraNode)
210 if 'self' == posLst[0].id
or 'cls' == posLst[0].id:
211 newPosLst.insert(0,posLst[0])
212 except Exception
as e:
220 for op,v
in opDict.items():
225 newKeyLst.append(para)
230 newKeyLst.append(para)
234 newKeyLst.append(para)
248 newKeyLst.append(para)
251 if op==
'pos2key' or op==
'key2pos':
252 newKeyLst.append(para)
256 newKeyLst.append(para)
262 node.keywords=newKeyLst
278 def validateByRun(callAPI,apiWithValue,projName,virtualEnv,runPath,runCommand,callKey,*,runtimePaths):
281 copyRoot=runtimePaths[
'copy_root']
282 dynamicRoot=runtimePaths[
'dynamic_root']
286 'new_'+pklName[:-4]+
'__object.pkl',
287 'new_'+pklName[:-4]+
'__expr.pkl',
289 pklName[:-4]+
'__object.pkl',
290 pklName[:-4]+
'__expr.pkl',
294 for candidateName
in pklCandidates:
295 candidatePath=os.path.join(copyRoot,
'pkl',candidateName)
296 if os.path.exists(candidatePath):
297 pklPath=candidatePath
306 if runPath
and runPath
not in runCommand:
307 cwd = os.path.join(dynamicRoot, projName, runPath)
308 script =
'verifySingle.py'
310 cwd = os.path.join(dynamicRoot, projName)
311 script = os.path.join(runPath,
'verifySingle.py')
313 cwd = os.path.join(dynamicRoot, projName)
314 script =
'verifySingle.py'
315 result = subprocess.run(
316 [pythonPath, script, pklPath, apiWithValue],
317 cwd=cwd, capture_output=
True, text=
True, encoding=
'utf-8'
332 def validateByStr(fixedAPI,repairDict,targetAPIDefinition,starFlag,twoStarFlag):
333 paraObjLst=
mirrorAPI(fixedAPI,repairDict)
334 posLst,keyLst=
para2Obj(targetAPIDefinition)
335 targetPara=posLst+keyLst
337 for para,nameFlag
in paraObjLst:
339 for it
in targetPara:
341 if para.name==it.name:
345 if para.position==it.position
and para.name==it.name:
351 if nameFlag
and not twoStarFlag:
353 if not nameFlag
and not starFlag:
383 def repairTask(root,callAPI,apiWithValue,projName,runPath,runCommand,repairLst,virtualEnv,errLst,callKey,*,runtimePaths):
387 for repairDict,targetPara
in repairLst:
390 if '*args' in targetPara:
392 if '**' in targetPara:
395 fix(callAPI,repairDict,apiRoot,starFlag,twoStarFlag)
396 fixedAPI=ast.unparse(apiRoot)
397 if validateByStr(fixedAPI,repairDict,targetPara,starFlag,twoStarFlag):
398 if fixedAPI
not in repairCandidates:
399 repairCandidates.append(fixedAPI)
402 if len(repairCandidates)==0:
403 return str(repairCandidates),
'Unknown',
'Unknown'
404 elif len(repairCandidates)==1:
405 fixedAPI=repairCandidates[0]
406 if callAPI.replace(
' ',
'').replace(
'"',
'').replace(
"'",
'')==fixedAPI.replace(
' ',
'').replace(
'"',
'').replace(
"'",
''):
407 return repairCandidates[0],
"Compatible",
"Unknown"
409 return repairCandidates[0],
"Incompatible",
"Unknown"
411 return str(repairCandidates),
"Unknown",
"Unknown"
415 for repairDict,targetPara
in repairLst:
419 if '*args' in targetPara:
421 if '**' in targetPara:
424 fix(callAPI,repairDict,apiRoot,starFlag,twoStarFlag)
425 fixedAPI=ast.unparse(apiRoot)
426 if not validateByStr(fixedAPI,repairDict,targetPara,starFlag,twoStarFlag):
428 elif len(repairLst)==1:
429 repairCandidates.append(fixedAPI)
433 apiRoot=
getAst(apiWithValue,1)
434 fix(apiWithValue,repairDict,apiRoot,starFlag,twoStarFlag)
435 apiWithValueFixed=ast.unparse(apiRoot)
437 result=
validateByRun(callAPI,apiWithValueFixed,projName,virtualEnv,runPath,runCommand,callKey,runtimePaths=runtimePaths)
439 if fixedAPI
not in repairCandidates:
440 repairCandidates.append(fixedAPI)
442 elif result.returncode!=0:
443 errLst.append(f
"{callAPI}, validate error: {result.stderr}\n")
444 failedLst.append(f
"{callAPI}, validate error: {result.stderr}\n")
445 if 'dill' in result.stderr:
447 if fixedAPI
not in repairCandidates:
448 repairCandidates.append(fixedAPI)
449 elif validateByStr(fixedAPI,repairDict,targetPara,starFlag,twoStarFlag):
451 if fixedAPI
not in repairCandidates:
452 repairCandidates.append(fixedAPI)
456 if fixedAPI
not in repairCandidates:
457 repairCandidates.append(fixedAPI)
461 if len(repairCandidates)==0:
462 return str(repairCandidates),
'Unknown' ,
'Unknown'
463 elif len(repairCandidates)==1:
464 fixedAPI=repairCandidates[0]
465 if callAPI.replace(
' ',
'').replace(
'"',
'').replace(
"'",
'')==fixedAPI.replace(
' ',
'').replace(
'"',
'').replace(
"'",
''):
466 return repairCandidates[0],
'Compatible',fixFlag
468 return repairCandidates[0],
'Incompatible',fixFlag
470 return str(repairCandidates),
'Unknown',
'Unknown'
def para2Obj(paraStr)
Convert parameter string to positional and keyword parameter objects 将参数字符串转换为位置和关键字参数对象
def mirrorAPI(fixedAPI, dic)
Create mirror for the fixed API by adding all parameter names 给修复后API的参数填上参数名
def mapPos(pos, dic)
Get repair operation dictionary of positional parameter 获取位置参数的修复操作字典
def repairTask(root, callAPI, apiWithValue, projName, runPath, runCommand, repairLst, virtualEnv, errLst, callKey, *runtimePaths)
Task of repairing parameter compatibility issues 参数兼容性问题修复任务
def fix(callAPI, repairDict, node, starFlag, twoStarFlag)
Perform parameter repair operations through AST 通过AST执行参数修复操作
def findName(pos, dic)
Find parameter name by its position 通过位置查找参数名
def validateByRun(callAPI, apiWithValue, projName, virtualEnv, runPath, runCommand, callKey, *runtimePaths)
Dynamic validation 动态验证
def validateByStr(fixedAPI, repairDict, targetAPIDefinition, starFlag, twoStarFlag)
Static validation 静态验证
def mapName(name, dic)
Get repair operation dictionary of keyword parameter 获取关键字参数的修复操作字典