Skip to content
Snippets Groups Projects
Commit 9aa1c904 authored by tuhe's avatar tuhe
Browse files

fix of Cache and unicode

parent cb00db13
Branches
No related tags found
No related merge requests found
Metadata-Version: 2.1
Name: unitgrade
Version: 0.1.30.5
Version: 0.1.30.6
Summary: A student homework/exam evaluation framework build on pythons unittest framework.
Home-page: https://lab.compute.dtu.dk/tuhe/unitgrade
Author: Tue Herlau
......
......@@ -58,7 +58,7 @@ class DummyPipe:
self.type = type
self.std_ = std_out_or_err
self.queue = queue
self.mute = False
self.mute = mute
def write(self, message):
if not self.mute:
......
......@@ -43,7 +43,9 @@ parser.add_argument('--noprogress', action="store_true", help='Disable progres
def evaluate_report_student(report, question=None, qitem=None, unmute=None, passall=None, ignore_missing_file=False,
show_tol_err=False, show_privisional=True, noprogress=None,
generate_artifacts=True):
generate_artifacts=True,
show_errors_in_grade_mode=True # This is included for debugging purpose. Should always be True.
):
args = parser.parse_args()
if noprogress is None:
noprogress = args.noprogress
......@@ -66,7 +68,7 @@ def evaluate_report_student(report, question=None, qitem=None, unmute=None, pass
results, table_data = evaluate_report(report, question=question, show_progress_bar=not unmute and not noprogress, qitem=qitem,
verbose=False, passall=passall, show_expected=args.showexpected, show_computed=args.showcomputed,unmute=unmute,
show_tol_err=show_tol_err,
generate_artifacts=generate_artifacts)
generate_artifacts=generate_artifacts, show_errors_in_grade_mode=show_errors_in_grade_mode)
if question is None and show_privisional:
......@@ -109,7 +111,9 @@ def evaluate_report(report, question=None, qitem=None, passall=False, verbose=Fa
show_progress_bar=True,
show_tol_err=False,
generate_artifacts=True, # Generate the artifact .json files. These are exclusively used by the dashboard.
big_header=True):
big_header=True,
show_errors_in_grade_mode=True # Show test error during grading.
):
from unitgrade.version import __version__
now = datetime.now()
......@@ -152,6 +156,7 @@ def evaluate_report(report, question=None, qitem=None, passall=False, verbose=Fa
UTextResult.number = n
UTextResult.nL = report.nL
UTextResult.unmute = unmute # Hacky as well.
UTextResult.show_errors_in_grade_mode = show_errors_in_grade_mode
UTextResult.setUpClass_time = q._cache.get(((q.__name__, 'setUpClass'), 'time'), 3) if hasattr(q, '_cache') and q._cache is not None else 3
......
......@@ -120,6 +120,9 @@ class Report:
relative_path = os.path.relpath(self._file(), root_dir)
modules = os.path.normpath(relative_path[:-3]).split(os.sep)
relative_path = relative_path.replace("\\", "/")
if relative_path.startswith(".."):
raise Exception("Bad relative path. setup failed. ", root_dir, self._file())
return root_dir, relative_path, modules
def __init__(self, strict=False, payload=None):
......@@ -351,6 +354,16 @@ class UTestCase(unittest.TestCase):
# print("Run called in test framework...", self._generate_artifacts)
if not self._generate_artifacts:
return super().run(result)
print(result)
mute = False
if isinstance(result, UTextResult):
print(result.show_errors_in_grade_mode)
mute = not result.show_errors_in_grade_mode
else:
pass
# print("this' not a text result.")
# print(result.show_errors_in_grade_mode)
from unitgrade.artifacts import StdCapturing
from unitgrade.utils import DKPupDB
self._error_fed_during_run = [] # Initialize this to be empty.
......@@ -362,8 +375,8 @@ class UTestCase(unittest.TestCase):
_stdout = sys.stdout
_stderr = sys.stderr
std_capture = StdCapturing(stdout=sys.stdout, stderr=sys.stderr, db=db, mute=False)
# mute = True
std_capture = StdCapturing(stdout=sys.stdout, stderr=sys.stderr, db=db, mute=mute)
state_ = None
try:
......@@ -376,17 +389,13 @@ class UTestCase(unittest.TestCase):
# db.get('stdout')
# db.get('stderr')
# db.get("history")
result_ = TestCase.run(self, result)
from werkzeug.debug.tbtools import DebugTraceback, _process_traceback
# What could be nice to upload?
# When the files are edited?
# When tests are run?
# how to register it? (report, question, user...)
#
# print(result_._excinfo[0])
actual_errors = []
for test, err in self._error_fed_during_run:
......@@ -467,7 +476,7 @@ class UTestCase(unittest.TestCase):
for ll in data.contexts_by_lineno(file):
l = ll-1
print(l, lines2[l])
# print(l, lines2[l])
if l < len(lines2) and lines2[l].strip() == garb:
print("Got one.")
rel = os.path.relpath(child, root)
......@@ -858,12 +867,19 @@ class NotebookTestCase(UTestCase):
_nb = None
@classmethod
def setUpClass(cls) -> None:
f = cls._cache_file()
# print(f)
file = os.path.dirname(os.path.dirname(f)) + "/" + cls.notebook
# print(f"{f=}, {file=}, {cls.notebook=}")
# print(__file__)
print(os.path.curdir)
# print("cwd", os.getcwd())
with Capturing():
# print(__file__)
f = cls._cache_file()
# print(f)
file = os.path.dirname(os.path.dirname(f)) + "/" + cls.notebook
cls._nb = importnb.Notebook.load_file(file)
cls._nb = importnb.Notebook.load_argv(file + " -nograde")
@property
def nb(self):
......
......@@ -14,6 +14,7 @@ class UTextResult(unittest.TextTestResult):
unmute = False # Whether to redirect stdout.
cc = None
setUpClass_time = 3 # Estimated time to run setUpClass in TestCase. Must be set externally. See key (("ClassName", "setUpClass"), "time") in _cache.
show_errors_in_grade_mode = True
def __init__(self, stream, descriptions, verbosity):
super().__init__(stream, descriptions, verbosity)
......@@ -24,6 +25,19 @@ class UTextResult(unittest.TextTestResult):
self.printErrorList('ERROR', [(test, res['stderr']) for test, res in self.errors])
self.printErrorList('FAIL', [(test, res['stderr']) for test, res in self.failures])
def printErrorList(self, flavour, errors):
if not self.show_errors_in_grade_mode:
return
else:
super().printErrorList(flavour, errors)
#
# for test, err in errors:
# self.stream.writeln(self.separator1)
# self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
# self.stream.writeln(self.separator2)
# self.stream.writeln("%s" % err)
# self.stream.flush()
def addError(self, test, err):
super(unittest.TextTestResult, self).addError(test, err)
err = self.errors[-1][1]
......@@ -42,7 +56,6 @@ class UTextResult(unittest.TextTestResult):
if self.item_title_print is None: # In case the short description is not set either...
self.item_title_print = test.id()
self.cc_terminate(success=False)
def addFailure(self, test, err):
......@@ -111,18 +124,21 @@ class UTextResult(unittest.TextTestResult):
# if self.show_progress_bar or True:
estimated_time = test.__class__._cache.get(((name, test._testMethodName), 'time'), 100) if hasattr(test.__class__, '_cache') else 4
self.cc = ActiveProgress(t=estimated_time, title=self.item_title_print, show_progress_bar=self.show_progress_bar)
# else:
# print(self.item_title_print + ('.' * max(0, self.nL - 4 - len(self.item_title_print))), end="")
self._test = test
# if not self.unmute:
self._stdout = sys.stdout # Redundant. remove later.
from unitgrade.utils import Logger
sys.stdout = Logger(io.StringIO(), write_to_stdout=self.unmute)
if not self.show_errors_in_grade_mode:
# print("Trying to hide the errors....", self.show_errors_in_grade_mode)
self._stderr = sys.stderr
sys.stderr = Logger(io.StringIO(), write_to_stdout=False)
def stopTest(self, test):
# if not self.unmute:
buff = sys.stdout.log
sys.stdout = self._stdout # redundant.
if not self.show_errors_in_grade_mode:
sys.stderr = self._stderr
buff.close()
from unitgrade.utils import Logger
super().stopTest(test)
......@@ -139,6 +155,7 @@ class UTextResult(unittest.TextTestResult):
self.cc = cc
def _restoreStdout(self): # Used when setting up the test.
if self._previousTestClass is None:
q_time = self.cc.terminate()
......
......@@ -137,7 +137,7 @@ class ActiveProgress():
def terminate(self):
if not self._running:
print("Stopping a progress bar which is not running (class unitgrade.utils.ActiveProgress")
# print("Stopping a progress bar which is not running (class unitgrade.utils.ActiveProgress")
pass
# raise Exception("Stopping a stopped progress bar. ")
self._running = False
......@@ -152,10 +152,7 @@ class ActiveProgress():
if self.mute_stdout:
import io
# from unitgrade.utils import Logger
sys.stdout = self._stdout #= sys.stdout
# sys.stdout = Logger(io.StringIO(), write_to_stdout=False)
sys.stdout = self._stdout
return time.time() - self.time_started
......@@ -308,9 +305,11 @@ def load_token(file_in):
## Key/value store related.
class DKPupDB:
DISABLE_DB = False
""" This key/value store store artifacts (associated with a specific question) in a dictionary. """
def __init__(self, artifact_file, use_pupdb=False, register_ephemeral=False):
# Make a double-headed disk cache thingy.
try:
self.dk = Cache(os.path.dirname(artifact_file)) # Start in this directory.
self.name_ = os.path.basename(artifact_file[:-5])
if self.name_ not in self.dk:
......@@ -320,8 +319,14 @@ class DKPupDB:
if self.use_pupdb:
from pupdb.core import PupDB
self.db_ = PupDB(artifact_file)
except Exception as e:
# print("Artifact file not readable. Possibly ")
self.DISABLE_DB = True
pass
def __setitem__(self, key, value):
if self.DISABLE_DB:
return
if self.use_pupdb:
self.db_.set(key, value)
with self.dk.transact():
......@@ -332,6 +337,8 @@ class DKPupDB:
self.dk[self.name_ + "-updated"] = True
def __getitem__(self, item):
if self.DISABLE_DB:
return "db disabled due to bad artifact file."
v = self.dk[self.name_][item]
if self.use_pupdb:
v2 = self.db_.get(item)
......@@ -344,11 +351,17 @@ class DKPupDB:
# return self.db_.keys()
def set(self, item, value): # This one is deprecated.
if self.DISABLE_DB:
return
self[item] = value
def get(self, item, default=None):
if self.DISABLE_DB:
return "artifact file not loaded."
return self[item] if item in self else default
def __contains__(self, item):
if self.DISABLE_DB:
return False
return item in self.dk[self.name_] #keys()
# return item in self.dk
__version__ = "0.1.30.6"
__version__ = "0.1.30.8"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment