Skip to content
Snippets Groups Projects
Commit 4f19f7fc authored by Tue Herlau's avatar Tue Herlau
Browse files

updates

parent 8cac9d5d
Branches
Tags
No related merge requests found
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
<project version="4"> <project version="4">
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="5c346737-53d8-4e87-88c5-7be2c8e7baeb" name="Default" comment=""> <list default="true" id="5c346737-53d8-4e87-88c5-7be2c8e7baeb" name="Default" comment="">
<change afterPath="$PROJECT_DIR$/Report1_resources_do_not_hand_in.dat" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/MANIFEST.in" beforeDir="false" afterPath="$PROJECT_DIR$/MANIFEST.in" afterDir="false" /> <change beforePath="$PROJECT_DIR$/cs101courseware_example/Report1_resources_do_not_hand_in.dat" beforeDir="false" afterPath="$PROJECT_DIR$/cs101courseware_example/Report1_resources_do_not_hand_in.dat" afterDir="false" />
<change beforePath="$PROJECT_DIR$/setup.py" beforeDir="false" afterPath="$PROJECT_DIR$/setup.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/cs101courseware_example/cs101report1_grade.py" beforeDir="false" afterPath="$PROJECT_DIR$/cs101courseware_example/cs101report1_grade.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cs101courseware_example/cs101report2_grade.py" beforeDir="false" afterPath="$PROJECT_DIR$/cs101courseware_example/cs101report2_grade.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/unitgrade/unitgrade_helpers.py" beforeDir="false" afterPath="$PROJECT_DIR$/unitgrade/unitgrade_helpers.py" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
...@@ -140,7 +141,7 @@ ...@@ -140,7 +141,7 @@
<recent name="C:\Users\tuhe\Documents\unitgrade_private" /> <recent name="C:\Users\tuhe\Documents\unitgrade_private" />
</key> </key>
</component> </component>
<component name="RunManager" selected="Python.deploy_cs101"> <component name="RunManager" selected="Python.cs101report2">
<configuration name="cs101report1" type="PythonConfigurationType" factoryName="Python" nameIsGenerated="true"> <configuration name="cs101report1" type="PythonConfigurationType" factoryName="Python" nameIsGenerated="true">
<module name="unitgrade" /> <module name="unitgrade" />
<option name="INTERPRETER_OPTIONS" value="" /> <option name="INTERPRETER_OPTIONS" value="" />
...@@ -162,7 +163,7 @@ ...@@ -162,7 +163,7 @@
<option name="INPUT_FILE" value="" /> <option name="INPUT_FILE" value="" />
<method v="2" /> <method v="2" />
</configuration> </configuration>
<configuration name="cs101report2_grade" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true"> <configuration name="cs101report2" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="unitgrade" /> <module name="unitgrade" />
<option name="INTERPRETER_OPTIONS" value="" /> <option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" /> <option name="PARENT_ENVS" value="true" />
...@@ -174,7 +175,7 @@ ...@@ -174,7 +175,7 @@
<option name="IS_MODULE_SDK" value="true" /> <option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" /> <option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" /> <option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/../unitgrade_private/cs101courseware/cs101report2_grade.py" /> <option name="SCRIPT_NAME" value="$PROJECT_DIR$/../unitgrade_private/cs101courseware/cs101report2.py" />
<option name="PARAMETERS" value="" /> <option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" /> <option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" /> <option name="EMULATE_TERMINAL" value="false" />
...@@ -269,19 +270,19 @@ ...@@ -269,19 +270,19 @@
</configuration> </configuration>
<list> <list>
<item itemvalue="Python.cs101report1" /> <item itemvalue="Python.cs101report1" />
<item itemvalue="Python.cs101report2_grade" />
<item itemvalue="Python.submission_autograder" /> <item itemvalue="Python.submission_autograder" />
<item itemvalue="Python.shopSmart" /> <item itemvalue="Python.shopSmart" />
<item itemvalue="Python.fruit_project" /> <item itemvalue="Python.fruit_project" />
<item itemvalue="Python.deploy_cs101" /> <item itemvalue="Python.deploy_cs101" />
<item itemvalue="Python.cs101report2" />
</list> </list>
<recent_temporary> <recent_temporary>
<list> <list>
<item itemvalue="Python.cs101report2" />
<item itemvalue="Python.deploy_cs101" /> <item itemvalue="Python.deploy_cs101" />
<item itemvalue="Python.fruit_project" /> <item itemvalue="Python.fruit_project" />
<item itemvalue="Python.shopSmart" /> <item itemvalue="Python.shopSmart" />
<item itemvalue="Python.submission_autograder" /> <item itemvalue="Python.submission_autograder" />
<item itemvalue="Python.cs101report2_grade" />
</list> </list>
</recent_temporary> </recent_temporary>
</component> </component>
...@@ -350,16 +351,16 @@ ...@@ -350,16 +351,16 @@
<line>28</line> <line>28</line>
<option name="timeStamp" value="63" /> <option name="timeStamp" value="63" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/unitgrade/unitgrade.py</url>
<line>145</line>
<option name="timeStamp" value="85" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line"> <line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/unitgrade/unitgrade.py</url> <url>file://$PROJECT_DIR$/unitgrade/unitgrade.py</url>
<line>54</line> <line>54</line>
<option name="timeStamp" value="89" /> <option name="timeStamp" value="89" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/unitgrade/unitgrade_helpers.py</url>
<line>62</line>
<option name="timeStamp" value="90" />
</line-breakpoint>
</breakpoints> </breakpoints>
</breakpoint-manager> </breakpoint-manager>
</component> </component>
......
File deleted
No preview for this file type
This diff is collapsed.
This diff is collapsed.
__version__ = "0.0.5" __version__ = "0.0.6"
import os import os
import compress_pickle import compress_pickle
......
No preview for this file type
No preview for this file type
...@@ -7,9 +7,9 @@ import unittest ...@@ -7,9 +7,9 @@ import unittest
import numpy as np import numpy as np
import os import os
from io import StringIO from io import StringIO
import sys
import collections import collections
import inspect import inspect
import re
myround = lambda x: np.round(x) # required. myround = lambda x: np.round(x) # required.
msum = lambda x: sum(x) msum = lambda x: sum(x)
...@@ -75,6 +75,7 @@ class QItem(unittest.TestCase): ...@@ -75,6 +75,7 @@ class QItem(unittest.TestCase):
testfun = unittest.TestCase.assertEqual testfun = unittest.TestCase.assertEqual
tol = 0 tol = 0
_computed_answer = None # Internal helper to later get results.
def __init__(self, working_directory=None, correct_answer_payload=None, *args, **kwargs): def __init__(self, working_directory=None, correct_answer_payload=None, *args, **kwargs):
self.name = self.__class__.__name__ self.name = self.__class__.__name__
self._correct_answer_payload = correct_answer_payload self._correct_answer_payload = correct_answer_payload
...@@ -115,9 +116,10 @@ class QItem(unittest.TestCase): ...@@ -115,9 +116,10 @@ class QItem(unittest.TestCase):
print(computed) print(computed)
def show_expected_(expected): def show_expected_(expected):
print(">>> Expected output:") print(">>> Expected output (note: may have been processed; read text script):")
print(expected) print(expected)
correct = self._correct_answer_payload
try: try:
if unmute: if unmute:
print("\n") print("\n")
...@@ -125,13 +127,16 @@ class QItem(unittest.TestCase): ...@@ -125,13 +127,16 @@ class QItem(unittest.TestCase):
except Exception as e: except Exception as e:
if not passall: if not passall:
print("\n=================================================================================") print("\n=================================================================================")
print(f"When trying to run test class '{self.name}' your code threw an error:") print(f"When trying to run test class '{self.name}' your code threw an error:", e)
print(e) show_expected_(correct)
print("=================================================================================")
import traceback import traceback
traceback.print_exc() print(traceback.format_exc())
print("=================================================================================")
return (0, possible) return (0, possible)
correct = self._correct_answer_payload
if self._computed_answer is None:
self._computed_answer = computed
if show_expected or show_computed: if show_expected or show_computed:
print("\n") print("\n")
if show_expected: if show_expected:
...@@ -189,6 +194,7 @@ class QPrintItem(QItem): ...@@ -189,6 +194,7 @@ class QPrintItem(QItem):
res = self.compute_answer_print() res = self.compute_answer_print()
s = "\n".join(output) s = "\n".join(output)
numbers = extract_numbers(s) numbers = extract_numbers(s)
self._computed_answer = (res, s, numbers)
return self.process_output(res, s, numbers) return self.process_output(res, s, numbers)
class OrderedClassMembers(type): class OrderedClassMembers(type):
...@@ -215,8 +221,10 @@ class QuestionGroup(metaclass=OrderedClassMembers): ...@@ -215,8 +221,10 @@ class QuestionGroup(metaclass=OrderedClassMembers):
class Report(): class Report():
title = "report title" title = "report title"
version = None
questions = [] questions = []
pack_imports = [] pack_imports = []
individual_imports = []
def __init__(self, strict=False, payload=None): def __init__(self, strict=False, payload=None):
working_directory = os.path.abspath(os.path.dirname(inspect.getfile(type(self)))) working_directory = os.path.abspath(os.path.dirname(inspect.getfile(type(self))))
...@@ -224,7 +232,6 @@ class Report(): ...@@ -224,7 +232,6 @@ class Report():
self.wdir, self.name = setup_dir_by_class(self, working_directory) self.wdir, self.name = setup_dir_by_class(self, working_directory)
self.computed_answers_file = os.path.join(self.wdir, self.name + "_resources_do_not_hand_in.dat") self.computed_answers_file = os.path.join(self.wdir, self.name + "_resources_do_not_hand_in.dat")
self.questions = [(Q(working_directory=self.wdir),w) for Q,w in self.questions] self.questions = [(Q(working_directory=self.wdir),w) for Q,w in self.questions]
# self.strict = strict
if payload is not None: if payload is not None:
self.set_payload(payload, strict=strict) self.set_payload(payload, strict=strict)
else: else:
...@@ -246,10 +253,10 @@ class Report(): ...@@ -246,10 +253,10 @@ class Report():
raise Exception(s) raise Exception(s)
else: else:
print(s) print(s)
else:
item._correct_answer_payload = payloads[q.name][item.name]['payload'] item._correct_answer_payload = payloads[q.name][item.name]['payload']
def extract_numbers(txt): def extract_numbers(txt):
import re
numeric_const_pattern = '[-+]? (?: (?: \d* \. \d+ ) | (?: \d+ \.? ) )(?: [Ee] [+-]? \d+ ) ?' numeric_const_pattern = '[-+]? (?: (?: \d* \. \d+ ) | (?: \d+ \.? ) )(?: [Ee] [+-]? \d+ ) ?'
rx = re.compile(numeric_const_pattern, re.VERBOSE) rx = re.compile(numeric_const_pattern, re.VERBOSE)
all = rx.findall(txt) all = rx.findall(txt)
......
...@@ -18,19 +18,19 @@ import argparse ...@@ -18,19 +18,19 @@ import argparse
parser = argparse.ArgumentParser(description='Evaluate your report.', epilog="""Example: parser = argparse.ArgumentParser(description='Evaluate your report.', epilog="""Example:
To run all tests in a report: To run all tests in a report:
> python report1.py > python assignment1_dp.py
To run only question 2 or question 2.1 To run only question 2 or question 2.1
> python report1.py -q 2 > python assignment1_dp.py -q 2
> python report1.py -q 2.1 > python assignment1_dp.py -q 2.1
Note this scripts does not grade your report. To grade your report, use: Note this scripts does not grade your report. To grade your report, use:
> python report1_grade.py > python report1_grade.py
Finally, note that if your report is part of a module (package), and the report script requires part of that package, the -m option for python may be useful. Finally, note that if your report is part of a module (package), and the report script requires part of that package, the -m option for python may be useful.
As an example, suppose the report file is Documents/course_package/report1.py, and `course_package` is a python package. Change directory to 'Documents/` and execute: As an example, suppose the report file is Documents/course_package/assignment1_dp.py, and `course_package` is a python package. Change directory to 'Documents/` and execute:
> python -m course_package.report1 > python -m course_package.report1
...@@ -48,8 +48,6 @@ parser.add_argument('--passall', action="store_true", help='Automatically pass ...@@ -48,8 +48,6 @@ parser.add_argument('--passall', action="store_true", help='Automatically pass
# const=sum, default=max, # const=sum, default=max,
# help='sum the integers (default: find the max)') # help='sum the integers (default: find the max)')
def evaluate_report_student(report, question=None, qitem=None): def evaluate_report_student(report, question=None, qitem=None):
args = parser.parse_args() args = parser.parse_args()
if question is None and args.q is not None: if question is None and args.q is not None:
...@@ -58,8 +56,8 @@ def evaluate_report_student(report, question=None, qitem=None): ...@@ -58,8 +56,8 @@ def evaluate_report_student(report, question=None, qitem=None):
question, qitem = [int(v) for v in question.split(".")] question, qitem = [int(v) for v in question.split(".")]
else: else:
question = int(question) question = int(question)
if not os.path.isfile(report.computed_answers_file):
# print(args) raise Exception("> Error: The pre-computed answer file", os.path.abspath(report.computed_answers_file), "does not exist. Check your package installation")
results, table_data = evaluate_report(report, question=question, qitem=qitem, verbose=False, passall=args.passall, show_expected=args.showexpected, show_computed=args.showcomputed,unmute=args.unmute) results, table_data = evaluate_report(report, question=question, qitem=qitem, verbose=False, passall=args.passall, show_expected=args.showexpected, show_computed=args.showcomputed,unmute=args.unmute)
if question is None: if question is None:
...@@ -93,11 +91,15 @@ def evaluate_report(report, question=None, qitem=None, passall=False, verbose=Fa ...@@ -93,11 +91,15 @@ def evaluate_report(report, question=None, qitem=None, passall=False, verbose=Fa
print(b + " v" + __version__) print(b + " v" + __version__)
dt_string = now.strftime("%d/%m/%Y %H:%M:%S") dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
print("Started: " + dt_string) print("Started: " + dt_string)
print("Evaluating " + report.title, "(use --help for options)") s = report.title
if report.version is not None:
s += " version " + report.version
print("Evaluating " + s, "(use --help for options)")
print(f"Loaded answers from: ", report.computed_answers_file, "\n") print(f"Loaded answers from: ", report.computed_answers_file, "\n")
table_data = [] table_data = []
nL = 80 nL = 80
score = {} score = {}
for n, (q, w) in enumerate(report.questions): for n, (q, w) in enumerate(report.questions):
q_hidden = issubclass(q.__class__, Hidden) q_hidden = issubclass(q.__class__, Hidden)
...@@ -122,7 +124,7 @@ def evaluate_report(report, question=None, qitem=None, passall=False, verbose=Fa ...@@ -122,7 +124,7 @@ def evaluate_report(report, question=None, qitem=None, passall=False, verbose=Fa
if not hidden: if not hidden:
print(ss, end="") print(ss, end="")
(current, possible) = item.get_points(show_expected=show_expected, show_computed=show_computed,unmute=unmute, passall=passall) (current, possible) = item.get_points(show_expected=show_expected, show_computed=show_computed,unmute=unmute, passall=passall)
q_[j] = {'w': iw, 'possible': possible, 'obtained': current, 'hidden': hidden} q_[j] = {'w': iw, 'possible': possible, 'obtained': current, 'hidden': hidden, 'computed': str(item._computed_answer)}
# q.possible += possible * iw # q.possible += possible * iw
# q.obtained += current * iw # q.obtained += current * iw
if not hidden: if not hidden:
...@@ -135,7 +137,7 @@ def evaluate_report(report, question=None, qitem=None, passall=False, verbose=Fa ...@@ -135,7 +137,7 @@ def evaluate_report(report, question=None, qitem=None, passall=False, verbose=Fa
possible = int(ws @ possible) possible = int(ws @ possible)
obtained = int(ws @ obtained) obtained = int(ws @ obtained)
obtained = int(myround(int((w * obtained) / possible ))) if possible > 0 else 0 obtained = int(myround(int((w * obtained) / possible ))) if possible > 0 else 0
score[n] = {'w': w, 'possible': w, 'obtained': obtained, 'ítems': q_, 'hidden': q_hidden} score[n] = {'w': w, 'possible': w, 'obtained': obtained, 'items': q_, 'hidden': q_hidden}
q.obtained = obtained q.obtained = obtained
q.possible = possible q.possible = possible
......
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment