def copyFileIfNotExists(srcDir, path, targetDir): srcPath = shell.pjoin(srcDir, path) if not shell.isFile(srcPath): raise IOError(f'{srcPath} must be a file') tgtPath = shell.pjoin(targetDir, path) if shell.isDir(tgtPath): raise IOError(f'{tgtPath} must not be a directory') shell.mkdir(shell.dirname(tgtPath), createParents=True) if shell.isFile(tgtPath): if not hasSameContent(srcPath, tgtPath): raise IOError(f'Target file {tgtPath} already exists with content different than in {srcPath}') else: shell.cp(srcPath, tgtPath)
def storeTestResultInSpreadsheet(self, studentDir: str, assignment: Assignment, testId: str, suffixes: Union[str, list[str]], result: any): if type(suffixes) == str: suffixes = [suffixes] (name, id) = utils.parseSubmissionDir(self.cfg, studentDir) (path, sheet) = gradeCmd.getSpreadsheet(studentDir, id, assignment) if not shell.isFile(path): print( red(f'No spreadsheet at {path}, continuing without storing results' )) return resultColTitle = testId if suffixes: resultColTitle = f'{resultColTitle} {" ".join(suffixes)}' try: spreadsheet.enterData(path, 'ID', [f"Teilnehmer/in{id}", id], resultColTitle, result, sheetName=sheet) print( f'Stored test result "{result}" for "{name}" ({id}) in column "{resultColTitle}" at {path}' ) except ValueError as e: print(f"ERROR storing test result in spreadsheet: {e}")
def runTestScriptIfExisting(assignment: Assignment, kind: TestKind, captureStdout=True, stderrToStdout=True): if kind == testKindStudent: scriptBase = "../run-student-tests" else: scriptBase = "../run-tests" exts = [".sh", ".py", ""] for e in exts: script = scriptBase + e if shell.isFile(script): print(blue(f"Running test script {script}")) cmdList = [script, str(assignment.id)] timeout = [] if assignment.timeout: timeout = [ 'timeout', '--signal', 'KILL', str(assignment.timeout) ] args = assignment.scriptArgs return shell.run(timeout + cmdList + args, onError='ignore', captureStdout=captureStdout, stderrToStdout=stderrToStdout) return None
def fixStudentCode(f): """ Add "module Main where", remove old module line if existing. Returns the filename of the rewritten file (if necessary). """ if not f or not shell.isFile(f): return f newLines = [] foundWeirdModLine = False foundModuleLine = False for l in open(f).readlines(): m = moduleRe.match(l) if m: return f else: newLines.append(l.rstrip()) if l.strip().startswith('module'): foundWeirdModLine = True if foundWeirdModLine and not foundModuleLine: print(f'Could not patch student file {f}: weird module line detected') return f insertMainModule(newLines) newName = shell.removeExt(f) + '_fixed.hs' open(newName, 'w').write('\n'.join(newLines)) return newName
def mkConfig(baseDir, configDict): if not shell.isdir(baseDir): abort('Base directory {baseDir} does not exist') yamlPath = shell.pjoin(baseDir, 'check.yml') if not shell.isFile(yamlPath): abort(f'Config file {yamlPath} not found') s = utils.readFile(yamlPath) return mkConfigFromString(baseDir, configDict, s)
def mkConfig(baseDir, configDict): if not shell.isdir(baseDir): abort('Base directory {baseDir} does not exist') yamlPath = shell.pjoin(baseDir, 'check.yml') if not shell.isFile(yamlPath): abort(f'Config file {yamlPath} not found') s = utils.readFile(yamlPath) ymlDict = yaml.load(s, Loader=yaml.FullLoader) return Config.parse(baseDir, configDict, ymlDict)
def findModuleName(f): """ Extracts the module name from the given file. """ if not shell.isFile(f): return None for l in open(f).readlines(): m = moduleRe.match(l) if m: modName = m.group(1) return modName return None
def copyTemplate(studentDir: str, studentId: str, path: str, copy: bool): (b, e) = shell.splitExt(shell.basename(path)) for t in ['_TEMPLATE_', 'TEMPLATE_', '_TEMPLATE', 'TEMPLATE']: b = b.replace(t, '') b = b + '_' + studentId newPath = shell.pjoin(studentDir, b) + e if not shell.isFile(newPath): if copy: note(f"Copying template {path} to {newPath}") shell.cp(path, newPath) spreadsheet.replaceData(newPath, 'ID', 'STUDENT_ID', studentId) else: return None return newPath
def action(d): self.assertTrue(shell.isFile(d + "/A/K/x.txt")) self.assertTrue(shell.isFile(d + "/A/K/X/x.txt")) self.assertTrue(shell.isFile(d + "/A/K/Y/x.txt")) self.assertTrue(shell.isFile(d + "/C/x.txt")) self.assertFalse(shell.isFile(d + "/B/x.txt")) self.assertFalse(shell.isFile(d + "/A/L/x.txt")) self.assertFalse(shell.isDir(d + "/B")) self.assertFalse(shell.isDir(d + "/A/L"))
def _runJavaTest(ctx, studentDir: str, codeDir: str, assignment: Assignment, testId: str, testDir: str, filter: Optional[str], hasTests: bool, isStudent: bool): cfg = ctx.cfg if filter is None: filter = '*' gradleProps = { 'testFilter': filter, 'testDir': testDir, 'studentDir': codeDir } gradlePropArgs = [] for k, v in gradleProps.items(): gradlePropArgs.append(f'-P{k}={v}') print() print(blue(f"Starting test {testId}")) with shell.workingDir(cfg.baseDir): if not shell.isFile('build.gradle'): abort(f'No build.gradle file in {cfg.baseDir}, aborting') if not hasTests: gradleCmd = 'compileJava' else: gradleCmd = 'test' cmd = [cfg.gradlePath] + gradlePropArgs + [gradleCmd, '--rerun-tasks'] print(f'Executing {" ".join(cmd)}') logFileName = shell.pjoin(studentDir, f'OUTPUT_{testId}.txt') with shell.createTee([shell.TEE_STDOUT, logFileName]) as tee: result = shell.run(cmd, onError='ignore', stderrToStdout=True, captureStdout=tee) output = open(logFileName, 'r').read() if result.exitcode == 0: print(green(f'Test {testId} OK')) else: print(red(f'Test {testId} FAILED, see above')) result = Result.parseResult(output) prefix = 'S' if isStudent else '' ctx.storeTestResultInSpreadsheet(studentDir, assignment, testId, [prefix + 'C'], 0 if result.compileError else 1) if hasTests: ctx.storeTestResultInSpreadsheet(studentDir, assignment, testId, [prefix + 'T'], result.ratio())
def runJavaTests(cfg: Config, args: TestArgs, studentDir: str, assignment: Assignment): gradleProps = { 'testFilter': assignment.getValue('test-filter'), 'testDir': cfg.testDir, 'studentDir': studentDir } gradlePropArgs = [] for k, v in gradleProps.items(): gradlePropArgs.append(f'-P{k}={v}') print() with shell.workingDir(cfg.baseDir): if not shell.isFile('build.gradle'): abort(f'No build.gradle file in {cfg.baseDir}, aborting') cmd = [cfg.gradlePath] + gradlePropArgs + ['test', '--rerun-tasks'] print(f'Executing {" ".join(cmd)}') result = shell.run(cmd, onError='ignore') if result.exitcode == 0: print(green(f'Tests for {assignment.id} OK')) else: print(red(f'Tests for {assignment.id} FAILED, see above'))
def assertExists(path): if not shell.isFile(path): d = shell.dirname(path) files = shell.ls(d, '*') abort(f'File {path} does not exist, existing files: {files}')
def assertExists(path): if not shell.isFile(path): abort(f'File {path} does not exist')