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([pythonPath, script, pklPath, apiWithValue],cwd=cwd, capture_output=
True, text=
True, encoding=
'utf-8')
329 def validateByStr(fixedAPI,repairDict,targetAPIDefinition,starFlag,twoStarFlag):
330 paraObjLst=
mirrorAPI(fixedAPI,repairDict)
331 posLst,keyLst=
para2Obj(targetAPIDefinition)
332 targetPara=posLst+keyLst
334 for para,nameFlag
in paraObjLst:
336 for it
in targetPara:
338 if para.name==it.name:
342 if para.position==it.position
and para.name==it.name:
348 if nameFlag
and not twoStarFlag:
350 if not nameFlag
and not starFlag:
380 def repairTask(root,callAPI,apiWithValue,projName,runPath,runCommand,repairLst,virtualEnv,errLst,callKey,*,runtimePaths):
384 for repairDict,targetPara
in repairLst:
387 if '*args' in targetPara:
389 if '**' in targetPara:
392 fix(callAPI,repairDict,apiRoot,starFlag,twoStarFlag)
393 fixedAPI=ast.unparse(apiRoot)
394 if validateByStr(fixedAPI,repairDict,targetPara,starFlag,twoStarFlag):
395 if fixedAPI
not in repairCandidates:
396 repairCandidates.append(fixedAPI)
399 if len(repairCandidates)==0:
400 return str(repairCandidates),
'Unknown',
'Unknown'
401 elif len(repairCandidates)==1:
402 fixedAPI=repairCandidates[0]
403 if callAPI.replace(
' ',
'').replace(
'"',
'').replace(
"'",
'')==fixedAPI.replace(
' ',
'').replace(
'"',
'').replace(
"'",
''):
404 return repairCandidates[0],
"Compatible",
"Unknown"
406 return repairCandidates[0],
"Incompatible",
"Unknown"
408 return str(repairCandidates),
"Unknown",
"Unknown"
412 for repairDict,targetPara
in repairLst:
416 if '*args' in targetPara:
418 if '**' in targetPara:
421 fix(callAPI,repairDict,apiRoot,starFlag,twoStarFlag)
422 fixedAPI=ast.unparse(apiRoot)
423 if not validateByStr(fixedAPI,repairDict,targetPara,starFlag,twoStarFlag):
425 elif len(repairLst)==1:
426 repairCandidates.append(fixedAPI)
430 apiRoot=
getAst(apiWithValue,1)
431 fix(apiWithValue,repairDict,apiRoot,starFlag,twoStarFlag)
432 apiWithValueFixed=ast.unparse(apiRoot)
434 result=
validateByRun(callAPI,apiWithValueFixed,projName,virtualEnv,runPath,runCommand,callKey,runtimePaths=runtimePaths)
436 if fixedAPI
not in repairCandidates:
437 repairCandidates.append(fixedAPI)
439 elif result.returncode!=0:
440 errLst.append(f
"{callAPI}, validate error: {result.stderr}\n")
441 failedLst.append(f
"{callAPI}, validate error: {result.stderr}\n")
442 if 'dill' in result.stderr:
444 if fixedAPI
not in repairCandidates:
445 repairCandidates.append(fixedAPI)
446 elif validateByStr(fixedAPI,repairDict,targetPara,starFlag,twoStarFlag):
448 if fixedAPI
not in repairCandidates:
449 repairCandidates.append(fixedAPI)
453 if fixedAPI
not in repairCandidates:
454 repairCandidates.append(fixedAPI)
458 if len(repairCandidates)==0:
459 return str(repairCandidates),
'Unknown' ,
'Unknown'
460 elif len(repairCandidates)==1:
461 fixedAPI=repairCandidates[0]
462 if callAPI.replace(
' ',
'').replace(
'"',
'').replace(
"'",
'')==fixedAPI.replace(
' ',
'').replace(
'"',
'').replace(
"'",
''):
463 return repairCandidates[0],
'Compatible',fixFlag
465 return repairCandidates[0],
'Incompatible',fixFlag
467 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 获取关键字参数的修复操作字典