Source code for gradelang.question
""" Question Manager.
"""
from tempfile import TemporaryDirectory
from typing import Union
[docs]class Question:
def __init__(self, name: Union[str, int], body: tuple, value=0):
self.name = name
self.body = body
self.value = value
self.results = None
self.output = None
self.exception = None
self.traceback = None
return
def update(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
return
def __eq__(self, other: 'Question') -> bool:
return all((self.name == other.name, self.body == other.body))
def __str__(self) -> str:
return str(self.name)
def __repr__(self) -> str:
return f'{self.name}: [{self.body}]'
@property
def workdir(self):
if '_workdir' not in self.__dict__:
self.__dict__['_workdir'] = TemporaryDirectory(prefix=f'{self.name}-')
return self.__dict__['_workdir']
def report(self):
base = f'Question {self.name}: {self.score}/{self.max_score}.'
if self.exception:
base = '\n'.join([base, f'Exception thrown: {self.exception}\n{self.traceback}'])
if self.output:
base = '\n'.join([base, f'Output: {self.output}'])
return base
def json(self):
return {
'name': self.name,
'max_score': self.max_score,
'score': self.score,
'output': '\n'.join(filter(lambda x: x, [self.output, self.exception, self.traceback]))
}
def markdown(self):
return '\n'.join(filter(lambda x: x, [
f'### {self.name} {self.score}/{self.max_score}',
self.output,
self.exception,
self.traceback
]))
def award(self, points):
self.value += points
@property
def score(self):
return self.value
@property
def max_score(self):
def find(node) -> int:
if node[0] == 'award':
return int(node[1])
elif node[0] == 'seq':
return find(node[1]) + find(node[2])
else:
return 0
return find(self.body)