From 4e218b3c10fe61f5bc9a83183bd584927e37b1ec Mon Sep 17 00:00:00 2001 From: jwansek Date: Sat, 22 Jan 2022 20:34:02 +0000 Subject: worked on handling and showing exceptions in client clode --- ExampleAssessments/CMP-4009B.yml | 6 +++++- ExampleAssessments/example.yml | 6 +++++- mark.py | 30 +++++++++++++++++++++++++++++- pdLine.png | Bin 0 -> 49362 bytes pdResult.txt | 10 ++++++++++ reflect.py | 25 ++++++++++++++++++++++--- templates/txt.jinja2 | 13 +++++++++++++ 7 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 pdLine.png create mode 100644 pdResult.txt diff --git a/ExampleAssessments/CMP-4009B.yml b/ExampleAssessments/CMP-4009B.yml index c01979b..2e5c564 100644 --- a/ExampleAssessments/CMP-4009B.yml +++ b/ExampleAssessments/CMP-4009B.yml @@ -57,4 +57,8 @@ files: - serviceDue(2) - serviceAt(2) - powerAt(2) - +dependencies: + libraries: + - matplotlib + files: + - ../wsData.txt diff --git a/ExampleAssessments/example.yml b/ExampleAssessments/example.yml index 46cab56..be1609f 100644 --- a/ExampleAssessments/example.yml +++ b/ExampleAssessments/example.yml @@ -36,4 +36,8 @@ files: assert nibbles.speak() == "nyaa~~" - | milton = animals.Dog() - assert milton.move() == "*moves*" \ No newline at end of file + assert milton.move() == "*moves*" +dependencies: + files: + - ../wsData.txt + - ../IncludeDirectory \ No newline at end of file diff --git a/mark.py b/mark.py index 9c0ec6b..2630be1 100644 --- a/mark.py +++ b/mark.py @@ -1,3 +1,4 @@ +from dataclasses import dataclass import jinja_helpers import configparser import argparse @@ -5,10 +6,36 @@ import tempfile import zipfile import reflect import jinja2 +import shutil import yaml import json import os +@dataclass +class FileDependencies: + assessment_struct:dict + + def __enter__(self): + try: + for file_dep in self.assessment_struct["dependencies"]["files"]: + if os.path.isfile(file_dep): + shutil.copy(file_dep, os.path.split(file_dep)[-1]) + else: + shutil.copytree(file_dep, os.path.split(file_dep)[-1]) + # print("%s --> %s" % (file_dep, os.path.join(os.getcwd(), os.path.split(file_dep)[-1]))) + except KeyError: + pass + + def __exit__(self, type, value, traceback): + try: + for file_dep in self.assessment_struct["dependencies"]["files"]: + if os.path.isfile(os.path.split(file_dep)[-1]): + os.remove(os.path.split(file_dep)[-1]) + else: + shutil.rmtree(os.path.split(file_dep)[-1]) + except KeyError: + pass + def main(**kwargs): student_no = os.path.splitext(os.path.split(args["submission"])[-1])[0] @@ -27,7 +54,8 @@ def main(**kwargs): with open(kwargs["assessment"], "r") as f: assessment_struct = yaml.safe_load(f) - output = reflect.gen_reflection_report(submission_files, assessment_struct, student_no, kwargs) + with FileDependencies(assessment_struct): + output = reflect.gen_reflection_report(submission_files, assessment_struct, student_no, kwargs) output_file = kwargs["out"] if kwargs["format"] == "yaml": diff --git a/pdLine.png b/pdLine.png new file mode 100644 index 0000000..bd88e40 Binary files /dev/null and b/pdLine.png differ diff --git a/pdResult.txt b/pdResult.txt new file mode 100644 index 0000000..2ad813e --- /dev/null +++ b/pdResult.txt @@ -0,0 +1,10 @@ +2021-03-19 15:10:21 50.40 7680.0 8856.0 +2012-07-03 12:12:12 60.20 9173.33 10578.0 +2005-12-08 23:30:00 100.05 11910.71 13292.36 +2025-08-29 05:33:00 45.00 6857.14 7907.14 +2031-02-15 16:53:00 20.00 666.67 857.14 +1999-04-14 04:24:00 65.00 9904.76 11421.43 +2045-07-09 20:44:00 56.00 8533.33 9840.0 +2024-11-01 09:05:00 32.00 3504.76 2811.43 +2008-02-21 13:19:00 75.45 11497.14 13257.64 +2014-06-05 14:10:00 80.09 12204.19 14072.96 diff --git a/reflect.py b/reflect.py index c6c7a9f..99e7fd9 100644 --- a/reflect.py +++ b/reflect.py @@ -4,6 +4,7 @@ from functools import reduce from operator import getitem import subprocess import importlib +import traceback import tempfile import inspect import pkgutil @@ -40,6 +41,9 @@ class Reflect: print("Missing library dependency for client module:") print(e) exit() + # except Exception as e: + # print("CRITICAL ERROR IN CLIENT CODE - CANNOT CONTINUE") + # raise ClientCodeException(e) def get_module_doc(self, module_name): """Gets the documentation provided for a module. @@ -196,8 +200,11 @@ class Reflect: with tempfile.TemporaryDirectory() as tmp: junitxmlpath = os.path.join(tmp, "report.xml") - cmd = ["pytest", "-v"] + [os.path.join(self.client_code_path, "test_%s" % f) for f in tests.keys()] + ["--junitxml=%s" % junitxmlpath] - #print(" ".join(cmd)) + test_files = [os.path.join(self.client_code_path, "test_%s" % f) for f in tests.keys()] + cmd = ["pytest", "-v"] + test_files + ["--junitxml=%s" % junitxmlpath] + if test_files == []: + test_results["pytest_report"] = "*** No Tests ***" + return test_results proc = subprocess.Popen(cmd, stdout = subprocess.PIPE) while True: line = proc.stdout.readline() @@ -236,8 +243,20 @@ def gen_reflection_report(client_code_path, assessment_struct, student_no, confi out["files"][i][required_file]["present"] = False continue - reflection.import_module(module_name) + try: + reflection.import_module(module_name) + except Exception as e: + out["files"][i][required_file]["has_exception"] = True + out["files"][i][required_file]["exception"] = {} + out["files"][i][required_file]["exception"]["type"] = str(type(e)) + out["files"][i][required_file]["exception"]["str"] = str(e) + # TODO: work out how to only get the exception stack of the client code + out["files"][i][required_file]["exception"]["traceback"] = ''.join(traceback.format_exception(None, e, e.__traceback__)) + + continue + required_files_features = assessment_struct["files"][i][required_file] + out["files"][i][required_file]["has_exception"] = False out["files"][i][required_file]["documentation"] = reflection.get_module_doc(module_name) if "classes" in required_files_features.keys(): diff --git a/templates/txt.jinja2 b/templates/txt.jinja2 index d6a0c16..0a9cdb5 100644 --- a/templates/txt.jinja2 +++ b/templates/txt.jinja2 @@ -9,6 +9,18 @@ {% for filename, files_contents in flat_files.items() %} = {{ filename + " =" -}} {%- if files_contents["present"] -%} + {%- if files_contents["has_exception"] %} + *** File cannot be run - has compile time exception *** + Please note that this file cannot be analysed or have tests preformed upon it + Exception Type: + {{ files_contents["exception"]["type"] }} + Exception String: + {{ files_contents["exception"]["str"] }} + Full Traceback: +``` +{{ files_contents["exception"]["traceback"] }} +``` + {%- else -%} {% if "classes" in files_contents.keys() %} Classes: {%- set flat_classes = flatten_struct(files_contents["classes"]) -%} @@ -58,6 +70,7 @@ {%- endif %} {%- endfor -%} {%- endif -%} + {%- endif -%} {% else %} *** File not present *** {% endif %} -- cgit v1.2.3