-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathrunCode.py
More file actions
111 lines (102 loc) · 3.96 KB
/
runCode.py
File metadata and controls
111 lines (102 loc) · 3.96 KB
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
106
107
108
109
110
111
import sys
import os
import importlib
import runpy
from dataclasses import dataclass
# local imports
from constants import *
import stacktrace
import instrument
from myLogging import *
from exceptionHandler import handleCurrentException
import utils
class Lib:
def __init__(self, mod, properlyImported):
self.properlyImported = properlyImported
if not properlyImported:
self.initModule = mod['initModule']
self.resetTestCount = mod['resetTestCount']
self.printTestResults = mod['printTestResults']
self.dict = mod
else:
self.initModule = mod.initModule
self.resetTestCount = mod.resetTestCount
self.printTestResults = mod.printTestResults
d = {}
self.dict = d
for name in dir(mod):
if name and name[0] != '_':
d[name] = getattr(mod, name)
@dataclass
class RunSetup:
def __init__(self, pathDir: str, args: list[str]):
self.pathDir = pathDir
self.args = args
self.sysPathInserted = False
self.oldArgs = sys.argv
def __enter__(self):
if self.pathDir not in sys.path:
sys.path.insert(0, self.pathDir)
self.sysPathInserted = True
sys.argv = self.args
self.originalProfile = sys.getprofile()
stacktrace.installProfileHook()
def __exit__(self, exc_type, value, traceback):
sys.setprofile(self.originalProfile)
if self.sysPathInserted:
sys.path.remove(self.pathDir)
self.sysPathInserted = False
sys.argv = self.oldArgs
def prepareLib(onlyCheckRunnable, enableTypeChecking):
libDefs = None
mod = 'wypp'
verbose('Attempting to import ' + mod)
wypp = importlib.import_module(mod)
libDefs = Lib(wypp, True)
verbose(f'Successfully imported module {mod} from file {wypp.__file__}')
libDefs.initModule(enableChecks=not onlyCheckRunnable,
enableTypeChecking=enableTypeChecking,
quiet=onlyCheckRunnable)
return libDefs
def runCode(fileToRun, globals, doTypecheck=True, extraDirs=None) -> dict:
if not extraDirs:
extraDirs = []
modName = os.path.basename(os.path.splitext(fileToRun)[0])
with instrument.setupFinder(os.path.dirname(fileToRun), modName, extraDirs, doTypecheck):
sys.dont_write_bytecode = True
res = runpy.run_module(modName, init_globals=globals, run_name='__wypp__', alter_sys=False)
return res
def runStudentCode(fileToRun, globals, onlyCheckRunnable, doTypecheck=True, extraDirs=None) -> dict:
doRun = lambda: runCode(fileToRun, globals, doTypecheck=doTypecheck, extraDirs=extraDirs)
if onlyCheckRunnable:
try:
doRun()
except:
printStderr('Loading file %s crashed' % fileToRun)
handleCurrentException()
else:
utils.die(0)
return doRun()
# globals already contain libDefs
def runTestsInFile(testFile, globals, libDefs, doTypecheck=True, extraDirs=[]):
printStderr()
printStderr(f"Running tutor's tests in {testFile}")
libDefs.resetTestCount()
try:
runCode(testFile, globals, doTypecheck=doTypecheck, extraDirs=extraDirs)
except:
handleCurrentException()
return libDefs.dict['printTestResults']('Tutor: ')
# globals already contain libDefs
def performChecks(check, testFile, globals, libDefs, doTypecheck=True, extraDirs=None, loadingFailed=False):
prefix = ''
if check and testFile:
prefix = 'Student: '
testResultsStudent = libDefs.printTestResults(prefix, loadingFailed)
if check:
testResultsInstr = {'total': 0, 'failing': 0}
if testFile:
testResultsInstr = runTestsInFile(testFile, globals, libDefs, doTypecheck=doTypecheck,
extraDirs=extraDirs)
failingSum = testResultsStudent['failing'] + testResultsInstr['failing']
utils.die(0 if failingSum < 1 else 1)