#!/usr/bin/env python # -*- coding: utf-8 -*- import argparse import logging import git import os import importlib import collections import csv logger = logging.getLogger('Homeworks') logger.setLevel(logging.DEBUG) fm = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch = logging.StreamHandler() ch.setFormatter(fm) logger.addHandler(ch) def arg_parse(): parser = argparse.ArgumentParser(description='Framework for checking homeworks.') parser.add_argument('-i', '--ids', type=str, help='path to a file with student ids.') return parser.parse_args() def get_ids(path): ids = [] with open(path) as _file: for line in _file: ids.append(line.strip().split(' ')[::2]) return ids def clone_repo(username, repo_name): repo = "https://git.wmi.amu.edu.pl/{}/{}.git".format(username, repo_name) dest = "./Python2017-{}".format(username) if os.path.exists(dest): logger.debug("{}: repo exests.".format(username)) else: try: git.Repo.clone_from(repo, dest) except git.GitCommandError: logger.info("Repository '{}' does not exist".format(repo)) return False return True def check_tasks(username, repo_name, tasks): logger.debug("Marking user: {}".format(username)) scores = collections.defaultdict(dict) for lab in tasks: path = os.path.realpath("./Python2017-{}/{}".format(username, lab)) for task, fun in tasks[lab]: task_file = path + "/{}". format(task) logger.debug(task_file) package = 'Python2017-{}.{}.{}'.format(username, lab, task) lib = importlib.import_module(package) tested_fun = getattr(lib, fun) tests = getattr(lib, 'tests') try: test_result = tests(tested_fun) except Exception: test_result = "FAILED" if test_result == 'TESTS PASSED': scores[lab][task] = 1 else: scores[lab][task] = 0 return scores def get_fieldnames(tasks): fieldnames = ['ID'] for lab in tasks: for task, _ in tasks[lab]: fieldnames.append('{}:{}'.format(lab, task)) return fieldnames def parse_scores(fieldnames, uname, scores): out = {} for name in fieldnames: if name == 'ID': out[name] = uname continue lab, task = name.split(':') out[name] = scores[lab][task] return out def write_scores(scores, filename, tasks): fieldnames = get_fieldnames(tasks) with open(filename, 'w') as results: writer = csv.DictWriter(results, fieldnames, restval=0) writer.writeheader() for student in scores: writer.writerow(parse_scores(fieldnames, student, scores[student])) def main(): """ main """ options = arg_parse() ids = get_ids(options.ids) logger.info("Liczba studentów: {}".format(len(ids))) scores = {} tasks = { 'labs02' : [ ('task07', 'char_sum'), ('task08', 'sum_div35'), ('task09', 'leet_speak'), ('task10', 'pokemon_speak'), ('task11', 'common_chars') ] } for repo_id in ids: st_uname = repo_id[0] repo_name = repo_id[-1] if clone_repo(st_uname, repo_name): scores[st_uname] = check_tasks(st_uname, repo_name, tasks) write_scores(scores, 'results.csv', tasks) if __name__ == "__main__": main()