-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path__main__.py
executable file
·105 lines (88 loc) · 4.18 KB
/
__main__.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
97
98
99
100
101
102
103
104
105
import os
import ast
import subprocess
import uuid
import json
import hashlib
import socket
import psutil
from ipykernel.ipkernel import IPythonKernel
def make_except_safe(code):
code = code.replace('\n', '\n ')
code = 'try:\n ' + code
code = code + '\nexcept: pass\n'
try:
ast.parse(code)
return code
except:
return ''
SCIUNIT_HOME = os.path.expanduser('~/sciunit/')
SCIUNIT_PROJECT_FILE = os.path.join(SCIUNIT_HOME, '.activated')
SCIUNIT_SOCKET_FILE = os.path.join(SCIUNIT_HOME, 'listener.socket')
class SciunitKernel(IPythonKernel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
implementation = super().implementation + ' sciunit'
if (os.path.exists(SCIUNIT_PROJECT_FILE)):
self.project = open(SCIUNIT_PROJECT_FILE).read().strip()
self.project_name = os.path.basename(os.path.normpath(self.project))
if (os.path.exists(os.path.join(self.project, 'kernel'))):
self.recording = False
else:
self.recording = True
open(os.path.join(self.project, 'kernel'), 'w').write(json.dumps([]))
else:
self.project_name = 'Project_' + str(uuid.uuid4())
self.project = os.path.join(SCIUNIT_HOME, self.project_name)
subprocess.run(['sciunit', 'create', self.project_name])
self.recording = True
open(os.path.join(self.project, 'kernel'), 'w').write(json.dumps([]))
self.eid = 1
self.file = os.path.join(self.project, 'run.py')
self.valid = True
files = psutil.Process().open_files()
for file in files:
os.close(file.fd)
criu_path = os.path.join(self.project, 'criu0')
data = ['Dump', os.getpid(), os.getppid(), criu_path, 0]
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
client.connect(SCIUNIT_SOCKET_FILE)
client.sendall(json.dumps(data).encode())
client.close()
def do_execute(self, code, silent, store_history=True, user_expressions=None, allow_stdin=False):
criu_path = os.path.join(self.project, f'criu{self.eid}')
if (os.path.exists(criu_path)): self.recording = False
hashes = json.loads(open(os.path.join(self.project, 'kernel')).read())
if not self.recording and (len(hashes) == self.eid - 1): self.valid = False
data = []
if self.valid:
with open(self.file[1], 'a') as file:
safe_code = make_except_safe(code)
if safe_code:
if self.recording:
print('Recording e{}'.format(self.eid))
open(self.file, 'a').write(safe_code)
subprocess.Popen(['sciunit', 'exec', 'python3', self.file], stdout=subprocess.PIPE).communicate()
hashes.append(hashlib.sha256(safe_code.encode()).hexdigest())
open(os.path.join(self.project, 'kernel'), 'w').write(json.dumps(hashes))
data = ['Dump', os.getpid(), os.getppid(), criu_path, self.eid]
else:
if (hashlib.sha256(safe_code.encode()).hexdigest() != hashes[self.eid - 1]):
print('Invalid, stopped repeating')
self.valid = False
else:
print('Valid, repeating e{}'.format(self.eid))
subprocess.Popen(['sciunit', 'repeat', 'e{}'.format(self.eid)], stdout=subprocess.PIPE).communicate()
data = ['Restore', os.getpid(), os.getppid(), criu_path, self.eid]
self.eid += 1
output = super().do_execute(code, silent, False, user_expressions, allow_stdin)
if data:
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
client.connect(SCIUNIT_SOCKET_FILE)
client.sendall(json.dumps(data).encode())
client.close()
# TODO: Wait without Socket
return output
if __name__ == '__main__':
from ipykernel.kernelapp import IPKernelApp
IPKernelApp.launch_instance(kernel_class=SciunitKernel)