-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvm_runner.py
96 lines (83 loc) · 2.78 KB
/
vm_runner.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import io
import sys
import traceback
import types
import typing as tp
import dis
from contextlib import contextmanager
def compile_code(text_code: types.CodeType | str) -> types.CodeType:
"""
This is utility function with primary purpose to convert string code to code type.
Secondary purpose - print byte code for text_code and all nested text_code
:param text_code: text code for compiling
:return: compiled code
"""
if isinstance(text_code, str):
print("Text code:\n{}\n".format(text_code))
print("Disassembled code:\n")
dis.dis(text_code)
print("\n")
code = compile(text_code, '<stdin>', 'exec')
else:
code = text_code
for const in code.co_consts:
if isinstance(const, types.CodeType):
compile_code(const)
print("Disassembled code co params:\n")
print(
"Co consts: {}\nCo freevars: {}\nCo flags: {}\n"
"Co cellvars: {}\nCo kwonlyargcount: {}\nCo names: {}\n"
"Co nlocals: {}\nCo varnames: {}\nCo stacksize: {}\n"
"Co name: {}\nCo lnotab: {}\nCo argcount: {}\n".format(
code.co_consts, code.co_freevars,
code.co_flags,
code.co_cellvars,
code.co_kwonlyargcount,
code.co_names,
code.co_nlocals,
code.co_varnames,
code.co_stacksize,
code.co_name,
list(code.co_lnotab),
code.co_argcount)
)
return code
@contextmanager
def redirected(out: tp.TextIO = sys.stdout, err: tp.TextIO = sys.stderr) -> tp.Iterator[None]:
"""
Context manage for capturing standart outputs
:param out: input text stream
:param err: output text stream
"""
saved_stdout = sys.stdout
saved_stderr = sys.stderr
try:
sys.stdout = out
sys.stderr = err
yield
finally:
sys.stdout = saved_stdout
sys.stderr = saved_stderr
def execute(code: types.CodeType,
func: tp.Callable[..., None],
*args: tp.Any) -> tuple[str, str, type[BaseException] | None]:
"""
Capture all output from function execution
:param code: code object to calculate
:param func: functions which
:param args: any number of arguments appropriate for function call
:return: tuple of function execution output
"""
stdout = io.StringIO()
stderr = io.StringIO()
exc_type, exc_value, exc_traceback = None, None, None
with redirected(out=stdout, err=stderr):
try:
func(code, *args)
except Exception:
exc_type, exc_value, exc_traceback = sys.exc_info()
if exc_value:
traceback.print_exception(exc_type, exc_value, exc_traceback, file=sys.stderr)
out = stdout.getvalue()
err = stderr.getvalue()
return out, err, exc_type