Skip to content

Commit 66ca2ca

Browse files
committed
Refactor python code execution
1 parent 2d804a4 commit 66ca2ca

File tree

8 files changed

+273
-250
lines changed

8 files changed

+273
-250
lines changed

utbot-python/src/main/kotlin/org/utbot/python/PythonEngine.kt

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ import org.utbot.fuzzing.Control
1616
import org.utbot.fuzzing.fuzz
1717
import org.utbot.python.code.MemoryDump
1818
import org.utbot.python.code.toPythonTree
19+
import org.utbot.python.evaluation.PythonCodeExecutor
20+
import org.utbot.python.evaluation.PythonCodeExecutorImpl
21+
import org.utbot.python.evaluation.PythonEvaluationError
22+
import org.utbot.python.evaluation.PythonEvaluationSuccess
23+
import org.utbot.python.evaluation.PythonEvaluationTimeout
1924
import org.utbot.python.framework.api.python.PythonTreeModel
2025
import org.utbot.python.fuzzing.PythonFeedback
2126
import org.utbot.python.fuzzing.PythonFuzzedConcreteValue
@@ -30,7 +35,6 @@ import org.utbot.python.utils.camelToSnakeCase
3035
import org.utbot.summary.fuzzer.names.TestSuggestedInfo
3136

3237
private val logger = KotlinLogging.logger {}
33-
const val TIMEOUT: Long = 10
3438

3539
sealed interface FuzzingExecutionFeedback
3640
class ValidExecution(val utFuzzedExecution: UtFuzzedExecution): FuzzingExecutionFeedback
@@ -104,21 +108,23 @@ class PythonEngine(
104108
"builtins.TypeError"
105109
)
106110

107-
if (evaluationResult.isException && (evaluationResult.result.type.name in prohibitedExceptions)) { // wrong type (sometimes mypy fails)
111+
val resultModel = evaluationResult.stateAfter.getById(evaluationResult.resultId).toPythonTree(evaluationResult.stateAfter)
112+
113+
if (evaluationResult.isException && (resultModel.type.name in prohibitedExceptions)) { // wrong type (sometimes mypy fails)
108114
val errorMessage = "Evaluation with prohibited exception. Substituted types: ${
109115
types.joinToString { it.pythonTypeRepresentation() }
110-
}. Exception type: ${evaluationResult.result.type.name}"
116+
}. Exception type: ${resultModel.type.name}"
111117

112118
logger.info(errorMessage)
113119
return TypeErrorFeedback(errorMessage)
114120
}
115121

116122
val executionResult =
117123
if (evaluationResult.isException) {
118-
UtExplicitlyThrownException(Throwable(evaluationResult.result.output.type.toString()), false)
124+
UtExplicitlyThrownException(Throwable(resultModel.type.toString()), false)
119125
}
120126
else {
121-
UtExecutionSuccess(PythonTreeModel(evaluationResult.result.output))
127+
UtExecutionSuccess(PythonTreeModel(resultModel))
122128
}
123129

124130
val testMethodName = suggestExecutionName(methodUnderTestDescription, executionResult)
@@ -138,7 +144,7 @@ class PythonEngine(
138144
return ValidExecution(utFuzzedExecution)
139145
}
140146

141-
private fun constructEvaluationInput(arguments: List<PythonFuzzedValue>, additionalModules: List<String>): EvaluationInput {
147+
private fun constructEvaluationInput(arguments: List<PythonFuzzedValue>, additionalModules: List<String>): PythonCodeExecutor {
142148
val argumentValues = arguments.map { PythonTreeModel(it.tree, it.tree.type) }
143149

144150
val (thisObject, modelList) =
@@ -152,16 +158,15 @@ class PythonEngine(
152158
.map { it.moduleName }
153159
val localAdditionalModules = (additionalModules + argumentModules).toSet()
154160

155-
return EvaluationInput(
161+
return PythonCodeExecutorImpl(
156162
methodUnderTest,
157-
directoriesForSysPath,
163+
FunctionArguments(thisObject, methodUnderTest.thisObjectName, modelList, methodUnderTest.argumentsNames),
164+
argumentValues.map { FuzzedValue(it) },
158165
moduleToImport,
166+
localAdditionalModules,
159167
pythonPath,
168+
directoriesForSysPath,
160169
timeoutForRun,
161-
thisObject,
162-
modelList,
163-
argumentValues.map { FuzzedValue(it) },
164-
localAdditionalModules
165170
)
166171
}
167172

@@ -188,10 +193,10 @@ class PythonEngine(
188193
return@PythonFuzzing PythonFeedback(control = Control.STOP)
189194
}
190195

191-
val evaluationInput = constructEvaluationInput(arguments, additionalModules)
192-
val jobResult = evaluationInput.evaluate()
196+
val codeExecutor = constructEvaluationInput(arguments, additionalModules)
197+
// val jobResult = evaluationInput.evaluate()
193198

194-
when (val evaluationResult = jobResult.evalResult) {
199+
when (val evaluationResult = codeExecutor.run()) {
195200
is PythonEvaluationError -> {
196201
val utError = UtError(
197202
"Error evaluation: ${evaluationResult.status}, ${evaluationResult.message}",
@@ -219,7 +224,7 @@ class PythonEngine(
219224
.zip(methodUnderTest.arguments)
220225
.mapNotNull { it.first.summary?.replace("%var%", it.second.name) }
221226

222-
val hasThisObject = jobResult.thisObject != null
227+
val hasThisObject = codeExecutor.methodArguments.thisObject != null
223228
val result = handleSuccessResult(parameters, evaluationResult, description, hasThisObject, summary)
224229
emit(result)
225230

utbot-python/src/main/kotlin/org/utbot/python/PythonEvaluation.kt

Lines changed: 0 additions & 223 deletions
This file was deleted.

utbot-python/src/main/kotlin/org/utbot/python/UTPythonAPI.kt

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import org.parsers.python.ast.Block
44
import org.utbot.framework.plugin.api.UtError
55
import org.utbot.framework.plugin.api.UtExecution
66
import org.utbot.python.framework.api.python.PythonClassId
7+
import org.utbot.python.framework.api.python.PythonModel
78
import org.utbot.python.framework.api.python.util.pythonAnyClassId
89
import org.utbot.python.newtyping.*
910
import org.utbot.python.typing.MypyAnnotations
@@ -33,9 +34,7 @@ class PythonMethod(
3334
TODO: Now we think that all class methods has `self` argument! We should support `@property` decorator
3435
*/
3536
val hasThisArgument: Boolean
36-
get() {
37-
return containingPythonClassId != null
38-
}
37+
get() = containingPythonClassId != null
3938

4039
val arguments: List<PythonArgument>
4140
get() {
@@ -44,6 +43,12 @@ class PythonMethod(
4443
PythonArgument(it.second, it.first.pythonTypeRepresentation())
4544
}
4645
}
46+
47+
val thisObjectName: String?
48+
get() = if (hasThisArgument) arguments[0].name else null
49+
50+
val argumentsNames: List<String>
51+
get() = arguments.map { it.name }.drop(if (hasThisArgument) 1 else 0)
4752
}
4853

4954
data class PythonTestSet(
@@ -52,4 +57,13 @@ data class PythonTestSet(
5257
val errors: List<UtError>,
5358
val mypyReport: List<MypyAnnotations.MypyReportLine>,
5459
val classId: PythonClassId? = null,
55-
)
60+
)
61+
62+
data class FunctionArguments(
63+
val thisObject: PythonModel?,
64+
val thisObjectName: String?,
65+
val arguments: List<PythonModel>,
66+
val names: List<String?>,
67+
) {
68+
val allArguments: List<PythonModel> = (listOf(thisObject) + arguments).filterNotNull()
69+
}

0 commit comments

Comments
 (0)