-
Notifications
You must be signed in to change notification settings - Fork 78
Better grader error display #376
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Let's hold off with merging this until we get some input on the intended behavior for multiple graders from here Kattis/problem-package-format#529. |
Matistjati
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Me and Fredrik agree that there should be at most one grader, and that we should add it to the spec. We decided not to rename the folder to grader for backwards compatibility, and thus I didn't rename the class name.
| if not grader.compile()[0]: | ||
| self.fatal(f'Failed to compile grader {grader}') | ||
| return ('JE', None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should really document what invariants we have for check, setup and what their purposes are.
This check is already performed in check. Do we want to have the an invariant that check is always called before grade? To me, it feels strange that compilation happens as part of check, does it not make more sense to compile as part of setup?
My inferred view is that we keep setup cheap so that we don't have to pay for problem parts we don't use. But then, are we guaranteed that check is always called before calling the part's "do work" function? I would assume yes, in which case we can remove this check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we should document this better. As I mentioned on Slack, I'm looking to do a larger refactor at some point (separating the parsing of a problem package from the various checks we have), which should hopefully resolve that.
Until then, my understanding is that setup is basically a constructor. It should probably only fail when things are in such a bad state that we're not sure we're making sense of what we're seeing. It is also called from the constructor, so it is safe to assume it has been run before check. That said, setup should basically never do any actual checks (as we may need to run setup on aspects which the user has explictly told us not to check).
| if not self._default_grader: | ||
| self.fatal('Failed to locate default grader') | ||
| return ('JE', None) | ||
| grader = self._default_grader | ||
| else: | ||
| graders = self._graders | ||
| if not self._grader: | ||
| self.fatal('Problem has grading: custom without any custom grader') | ||
| return ('JE', None) | ||
| grader = self._grader |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In TestcaseGroup, there are already checks for this. Do we want to assume that TestcaseGroup's check function must be called before running grade, so these checks can be removed? In that case, should we document that dependency?
The code there is
if self.config['grading'] == 'custom' and self._problem.graders._grader is None:
self._problem.graders.fatal(f'{self} has custom grading but no custom graders provided')
if self.config['grading'] == 'default' and Graders._default_grader is None:
self._problem.graders.fatal(f'{self} has default grading but I could not find default grader')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Order of checks is still a bit of a mess. I think with the current state of the code base, it's better to be defensive and duplicate checks like this, particularly fatal checks (so we're not gonna spam twice when this happens, as we're going to stop execution).
This PR does 3 things:
open()code to be crash-safeSample outputs:
Differing grader outputs:
Grader stderr (bizarre error, I know):