Skip to content

Commit e4e83db

Browse files
committed
First version python-usvm api usage
1 parent 7b73002 commit e4e83db

30 files changed

Lines changed: 1040 additions & 529 deletions

File tree

utbot-cli-python/src/main/kotlin/org/utbot/cli/language/python/PythonGenerateTestsCommand.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,19 +280,17 @@ class PythonGenerateTestsCommand : CliktCommand(
280280
)
281281

282282
logger.info("Loading information about Python types...")
283-
val (mypyStorage, _) = processor.sourceCodeAnalyze()
283+
val (mypyStorage, mypyReport) = processor.sourceCodeAnalyze()
284284

285285
logger.info("Generating tests...")
286-
var testSets = processor.testGenerate(mypyStorage)
286+
var testSets = processor.testGenerate(mypyStorage, mypyReport)
287287
if (testSets.isEmpty()) return
288288
if (doNotGenerateRegressionSuite) {
289289
testSets = testSets.map { testSet ->
290290
PythonTestSet(
291291
testSet.method,
292292
testSet.executions.filterNot { it.result is UtExecutionSuccess },
293293
testSet.errors,
294-
testSet.mypyReport,
295-
testSet.classId,
296294
testSet.executionsNumber
297295
)
298296
}

utbot-intellij-python/src/main/kotlin/org/utbot/intellij/plugin/python/PythonDialogProcessor.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ object PythonDialogProcessor {
287287

288288
localUpdateIndicator(ProgressRange.ANALYZE, "Analyze module ${model.currentPythonModule}", 0.5)
289289

290-
val (mypyStorage, _) = processor.sourceCodeAnalyze()
290+
val (mypyStorage, mypyReport) = processor.sourceCodeAnalyze()
291291

292292
localUpdateIndicator(ProgressRange.ANALYZE, "Analyze module ${model.currentPythonModule}", 1.0)
293293

@@ -300,7 +300,7 @@ object PythonDialogProcessor {
300300
model.timeout,
301301
)
302302
try {
303-
val testSets = processor.testGenerate(mypyStorage)
303+
val testSets = processor.testGenerate(mypyStorage, mypyReport)
304304
timerHandler.cancel(true)
305305
if (testSets.isEmpty()) return@forEachIndexed
306306

utbot-python-executor/src/main/python/utbot_executor/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ $ python -m utbot_executor <hostname> <port> <logfile> [<loglevel DEBUG | INFO |
2929
"argumentsIds": ["1", "2"],
3030
"kwargumentsIds": ["4", "5"],
3131
"serializedMemory": "string",
32+
"memoryMode": "REDUCE",
3233
"filepath": ["/home/user/my_project/my_module/submod1.py"],
3334
"coverageId": "1"
3435
}
@@ -41,6 +42,7 @@ $ python -m utbot_executor <hostname> <port> <logfile> [<loglevel DEBUG | INFO |
4142
* `argumentsIds` - list of argument's ids
4243
* `kwargumentsIds` - list of keyword argument's ids
4344
* `serializedMemory` - serialized memory throw `deep_serialization` algorithm
45+
* `memoryMode` - serialization mode (`PICKLE`, `REDUCE`)
4446
* `filepath` - path to the tested function's containing file
4547
* `coverageId` - special id witch will be used for sending information about covered lines
4648

utbot-python-executor/src/main/python/utbot_executor/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "utbot-executor"
3-
version = "1.8.0"
3+
version = "1.9.0.dev9"
44
description = ""
55
authors = ["Vyacheslav Tamarin <vyacheslav.tamarin@yandex.ru>"]
66
readme = "README.md"

utbot-python-executor/src/main/python/utbot_executor/tests/test_deep_serialization.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import datetime
44
import importlib.metadata
55
import json
6+
import pickle
67
import re
78
import sys
89
import typing
@@ -47,6 +48,7 @@ def template_test_assert(obj: typing.Any, imports: typing.List[str]):
4748
({},),
4849
((1, 2, 3),),
4950
(tuple(),),
51+
(pickle.dumps(((2, [1, 2]), {})),),
5052
],
5153
)
5254
def test_primitives(obj: typing.Any):

utbot-python-executor/src/main/python/utbot_executor/utbot_executor/deep_serialization/json_converter.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import copy
22
import importlib
33
import json
4+
import pickle
45
import sys
56
from typing import Dict, Iterable, Union
67
from utbot_executor.deep_serialization.memory_objects import (
@@ -51,7 +52,7 @@ def default(self, o):
5152
return json.JSONEncoder.default(self, o)
5253

5354

54-
def as_repr_object(dct: Dict) -> Union[MemoryObject, Dict]:
55+
def as_reduce_object(dct: Dict) -> Union[MemoryObject, Dict]:
5556
if "strategy" in dct:
5657
obj: MemoryObject
5758
if dct["strategy"] == "repr":
@@ -97,7 +98,7 @@ def as_repr_object(dct: Dict) -> Union[MemoryObject, Dict]:
9798

9899

99100
def deserialize_memory_objects(memory_dump: str) -> MemoryDump:
100-
parsed_data = json.loads(memory_dump, object_hook=as_repr_object)
101+
parsed_data = json.loads(memory_dump, object_hook=as_reduce_object)
101102
return MemoryDump(parsed_data["objects"])
102103

103104

utbot-python-executor/src/main/python/utbot_executor/utbot_executor/example/example.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def test_execution():
1717
'/home/vyacheslav/Projects/utbot_executor/utbot_executor/tests/my_func.py',
1818
'0x1'
1919
)
20-
response = executor.run_function(request)
20+
response = executor.run_reduce_function(request)
2121

2222
assert isinstance(response, ExecutionSuccessResponse)
2323

utbot-python-executor/src/main/python/utbot_executor/utbot_executor/executor.py

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import inspect
55
import logging
66
import pathlib
7+
import pickle
78
import sys
89
import traceback
910
import types
@@ -15,7 +16,8 @@
1516
from utbot_executor.deep_serialization.memory_objects import MemoryDump, PythonSerializer
1617
from utbot_executor.deep_serialization.utils import PythonId, getattr_by_path
1718
from utbot_executor.memory_compressor import compress_memory
18-
from utbot_executor.parser import ExecutionRequest, ExecutionResponse, ExecutionFailResponse, ExecutionSuccessResponse
19+
from utbot_executor.parser import ExecutionRequest, ExecutionResponse, ExecutionFailResponse, ExecutionSuccessResponse, \
20+
MemoryMode
1921
from utbot_executor.ut_tracer import UtTracer, UtCoverageSender
2022
from utbot_executor.utils import (
2123
suppress_stdout as __suppress_stdout,
@@ -71,6 +73,13 @@ def add_imports(imports: Iterable[str]):
7173
logging.debug("Submodule #%d: OK", i)
7274

7375
def run_function(self, request: ExecutionRequest) -> ExecutionResponse:
76+
match request.memory_mode:
77+
case MemoryMode.PICKLE:
78+
return self.run_pickle_function(request)
79+
case MemoryMode.REDUCE:
80+
return self.run_reduce_function(request)
81+
82+
def run_reduce_function(self, request: ExecutionRequest) -> ExecutionResponse:
7483
logging.debug("Prepare to run function `%s`", request.function_name)
7584
try:
7685
memory_dump = deserialize_memory_objects(request.serialized_memory)
@@ -143,6 +152,64 @@ def run_function(self, request: ExecutionRequest) -> ExecutionResponse:
143152
logging.debug("Value have been calculated: %s", value)
144153
return value
145154

155+
def run_pickle_function(self, request: ExecutionRequest) -> ExecutionResponse:
156+
logging.debug("Prepare to run function `%s`", request.function_name)
157+
try:
158+
logging.debug("Imports: %s", request.imports)
159+
logging.debug("Syspaths: %s", request.syspaths)
160+
self.add_syspaths(request.syspaths)
161+
self.add_imports(request.imports)
162+
except Exception as _:
163+
logging.debug("Error \n%s", traceback.format_exc())
164+
return ExecutionFailResponse("fail", traceback.format_exc())
165+
logging.debug("Imports have been added")
166+
167+
try:
168+
function = getattr_by_path(
169+
importlib.import_module(request.function_module),
170+
request.function_name
171+
)
172+
if not isinstance(function, types.FunctionType):
173+
return ExecutionFailResponse(
174+
"fail",
175+
f"Invalid function path {request.function_module}.{request.function_name}"
176+
)
177+
logging.debug("Function initialized")
178+
args, kwargs = pickle.loads(eval(request.serialized_memory))
179+
logging.debug("Arguments: %s", args)
180+
logging.debug("Kwarguments: %s", kwargs)
181+
except Exception as _:
182+
logging.debug("Error \n%s", traceback.format_exc())
183+
return ExecutionFailResponse("fail", traceback.format_exc())
184+
logging.debug("Arguments have been created")
185+
186+
try:
187+
_coverage_sender = UtCoverageSender(
188+
request.coverage_id,
189+
self.coverage_hostname,
190+
self.coverage_port,
191+
send_coverage=self.send_coverage,
192+
)
193+
194+
value = _run_calculate_function_value(
195+
function,
196+
list(args),
197+
kwargs,
198+
request.filepath,
199+
"",
200+
tracer=UtTracer(
201+
pathlib.Path(request.filepath),
202+
[sys.prefix, sys.exec_prefix],
203+
_coverage_sender,
204+
self.trace_mode,
205+
),
206+
)
207+
except Exception as _:
208+
logging.debug("Error \n%s", traceback.format_exc())
209+
return ExecutionFailResponse("fail", traceback.format_exc())
210+
logging.debug("Value have been calculated: %s", value)
211+
return value
212+
146213

147214
def _serialize_state(
148215
args: List[Any],

utbot-python-executor/src/main/python/utbot_executor/utbot_executor/parser.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import dataclasses
2+
import enum
23
import json
3-
from typing import Dict, List, Union, Tuple
4+
from typing import Dict, List, Union, Tuple, Literal
5+
6+
7+
class MemoryMode(enum.StrEnum):
8+
PICKLE = "PICKLE"
9+
REDUCE = "REDUCE"
410

511

612
@dataclasses.dataclass
@@ -12,6 +18,7 @@ class ExecutionRequest:
1218
arguments_ids: List[str]
1319
kwarguments_ids: Dict[str, str]
1420
serialized_memory: str
21+
memory_mode: MemoryMode
1522
filepath: str
1623
coverage_id: str
1724

@@ -41,7 +48,7 @@ class ExecutionFailResponse(ExecutionResponse):
4148
exception: str
4249

4350

44-
def as_execution_result(dct: Dict) -> Union[ExecutionRequest, Dict]:
51+
def as_execution_request(dct: Dict) -> Union[ExecutionRequest, Dict]:
4552
if set(dct.keys()) == {
4653
'functionName',
4754
'functionModule',
@@ -50,6 +57,7 @@ def as_execution_result(dct: Dict) -> Union[ExecutionRequest, Dict]:
5057
'argumentsIds',
5158
'kwargumentsIds',
5259
'serializedMemory',
60+
'memoryMode',
5361
'filepath',
5462
'coverageId',
5563
}:
@@ -61,14 +69,15 @@ def as_execution_result(dct: Dict) -> Union[ExecutionRequest, Dict]:
6169
dct['argumentsIds'],
6270
dct['kwargumentsIds'],
6371
dct['serializedMemory'],
72+
MemoryMode(dct['memoryMode']),
6473
dct['filepath'],
6574
dct['coverageId'],
6675
)
6776
return dct
6877

6978

7079
def parse_request(request: str) -> ExecutionRequest:
71-
return json.loads(request, object_hook=as_execution_result)
80+
return json.loads(request, object_hook=as_execution_request)
7281

7382

7483
class ResponseEncoder(json.JSONEncoder):
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.8.0
1+
1.9.0.dev9

0 commit comments

Comments
 (0)