def runTests(cfg, args): dirs = args.dirs if not dirs: dirs = collectSubmissionDirs(cfg) dirs = sorted(dirs) if args.startAt: l = dirs dirs = [] for x in l: if shell.basename(x) >= args.startAt: dirs.append(x) else: print(f'Skipping {x} as requested') for d in dirs: assignments = cfg.assignments if args.assignments: assignments = [] for a in cfg.assignments: if a.id in args.assignments: assignments.append(a) if not assignments: print(f'No assignments found or selected!') for i, a in enumerate(assignments): interactiveLoop(cfg, args, d, a) if i > 0: print()
def copyIntoStudentDir(assignment: Assignment, studentDir: str): for src in assignment.itemsToCopy: target = shell.pjoin(studentDir, shell.basename(src)) if not fileSystemItemEquals(src, target): print(f'Copying {src} to {studentDir} ...') moveToBackup(target) shell.cp(src, studentDir)
def forEach(cfg: Config, args, action): dirs = args.dirs if not dirs: dirs = collectSubmissionDirs(cfg) dirs = sorted(dirs) verbose(f"Submission directories: {dirs}") if args.startAt: l = dirs dirs = [] for x in l: if shell.basename(x) >= args.startAt: dirs.append(x) else: print(f'Skipping {x} as requested') for d in dirs: assignments = cfg.assignments if args.assignments: assignments = [] for a in cfg.assignments: if str(a.id) in args.assignments: assignments.append(a) if not assignments: print(f'No assignments found or selected!') action(d, assignments) return dirs
def suffixFromTestfile(assignment: Assignment, testFile: str): (testName, _) = shell.splitExt(shell.basename(testFile)) try: suffix = utils.stringAfterLastOccurrenceOf(testName, str(assignment.id) + '_') except ValueError: suffix = testName return suffix
def withFilenames(config, what, action): submissionDirs = collectSubmissionDirs(config) for d in submissionDirs: student = shell.basename(d) verbose(f'{what} filenames for student {student}') for k, assList in config.assignmentsGroupedByKind.items(): ass = assList[0] files = set([ shell.basename(f) for f in shell.ls(d, ass.submissionFileGlob) ]) expected = set([ shell.basename(f) for a in assList if (f := a.getMainFile(student)) is not None ]) missing = expected - files superfluous = files - expected verbose( f'{what} filenames for student {student} and kind {k}. files={files}, expected={expected}, missing={missing}, superflous={superfluous}' ) action(student, k, d, missing, superfluous)
def prettyStudent(cfg, studentDir): try: (name, matrikel) = parseSubmissionDir(cfg, studentDir) return f'{name} ({matrikel})' except ValueError: x = shell.basename(studentDir) if not x: x = studentDir x = stripLeadingSlash(x) x = stripTrailingSlash(x) return x
def prettyStudent(cfg, studentDir): x = shell.basename(studentDir) suf = cfg.submissionDirSuffix if x.endswith(suf): x = x[:-len(suf)] i = x.rindex('_') if i > 0 and i < len(x) - 1: name = x[:i] matrikel = x[i + 1:] return f'{name} ({matrikel})' else: return x
def moveToBackup(path): if not shell.exists(path): return for i in range(1000): backupName = shell.pjoin(shell.dirname(path), '.' + shell.basename(path) + ".bak") if i > 0: backupName = backupName + "." + str(i) if not shell.exists(backupName): shell.mv(path, backupName) return raise ValueError(f"too many backups for {path}")
def checkFilenames(config): submissionDirs = collectSubmissionDirs(config) for d in submissionDirs: student = shell.basename(d) files = set([ shell.basename(f) for f in shell.ls(d, config.submissionFileGlob) ]) expected = set(config.assignments) missing = expected - files superfluous = files - expected if len(missing) > 0: if len(superfluous) > 0: warn( f'{student} misses assignments {missing} but has the following extra files: {superfluous}' ) else: verbose( f'{student} misses assignments {missing} and there are no extra files.' ) else: verbose(f'{student} has all assignments')
def getAllPythonModulesFromDirectory(directory): '''!Returns a list of all .py files in the given directory, stripped of directory prefix and .py suffix (suitable for use in __init__.py files) @param directory string @returns [string, ...]''' mustBeString(directory) shell.assertFileExists(directory, "directory") modules_list = glob.glob(directory + "/*.py") init_file = os.path.join(directory, "__init__.py") modules_list = filter((lambda s: s != init_file), modules_list) module_names = [ shell.basename(module, ".py") for module in modules_list ] return module_names
def getAllPythonModulesFromDirectory(directory): '''!Returns a list of all .py files in the given directory, stripped of directory prefix and .py suffix (suitable for use in __init__.py files) @param directory string @returns [string, ...]''' mustBeString(directory) shell.assertFileExists(directory, "directory") modules_list = glob.glob(directory + "/*.py") init_file = os.path.join(directory, "__init__.py") modules_list = filter((lambda s: s != init_file), modules_list) module_names = [shell.basename(module, ".py") for module in modules_list] return module_names
def fixFilenames(config): submissionDirs = collectSubmissionDirs(config) for d in submissionDirs: student = shell.basename(d) files = set([ shell.basename(f) for f in shell.ls(d, config.submissionFileGlob) ]) expected = set(config.assignments) missing = expected - files superfluous = files - expected for m in missing: candidates = [] for s in superfluous: if s.endswith(m) or len(superfluous) == 1: candidates.append(s) if len(candidates) > 1: print( f'Cannot fix name of assignment {m} for {student} because there is more than one matching file' ) elif len(candidates) == 1: c = candidates[0] # Windows shell.run(['mv', '-i', shell.pjoin(d, c), shell.pjoin(d, m)])
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 fun(c): fixFilenames(c) studDir = shell.pjoin(c.baseDir, student) existingFiles = [shell.basename(p) for p in shell.ls(studDir)] self.assertEqual(sorted(expectedFiles), sorted(existingFiles))
def collectSubmissionFiles(config, d): files = shell.ls(d, config.submissionFileGlob) expected = set(config.assignments) return sorted([f for f in files if shell.basename(f) in expected])