Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions gradescope_utils/autograder_utils/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,49 @@ def wrapper(*args, **kwargs):
return func(*args, **kwargs)

return wrapper




class extra_data(object):
"""Decorator that indicates that a test may have extra data to emit

Usage: @extra_data

Then, within the test, set the value by calling
kwargs['set_data'] with a dictionary. You can make this convenient
by explicitly declaring a set_data keyword argument, eg.

```
@extra_data()
def test_code(set_data=None):
// grab some_data from submission...
set_data({ 'key_name': some_data })
```

Additonally, a default value can be specified in the decorator. eg.

```
@extra_data({ 'key_name': None })
def test_code(set_data=None):
// any call to set_data would override the default value
```

Note: keys and values are cast to strings to be expressed in JSON format.
"""

def __init__(self, extra_data = {}):
self.extra_data = extra_data

def __call__(self, func):
func.__extra_data__ = self.extra_data

def set_data(d: dict):
wrapper.__extra_data__ = d

@wraps(func)
def wrapper(*args, **kwargs):
kwargs['set_data'] = set_data
return func(*args, **kwargs)

return wrapper
7 changes: 7 additions & 0 deletions gradescope_utils/autograder_utils/json_test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ def getLeaderboardData(self, test):
sort_order = getattr(getattr(test, test._testMethodName), '__leaderboard_sort_order__', None)
value = getattr(getattr(test, test._testMethodName), '__leaderboard_value__', None)
return (column_name, sort_order, value)

def getExtraData(self, test):
extra_data = getattr(getattr(test, test._testMethodName), '__extra_data__', {})
return {str(k): str(v) for (k, v) in extra_data.items()}

def startTest(self, test):
super(JSONTestResult, self).startTest(test)
Expand All @@ -75,6 +79,7 @@ def buildResult(self, test, err=None):
hide_errors_message = self.getHideErrors(test)
score = self.getScore(test)
output = self.getOutput() or ""
extra_data = self.getExtraData(test)
if err:
if hide_errors_message:
output += hide_errors_message
Expand Down Expand Up @@ -109,6 +114,8 @@ def buildResult(self, test, err=None):
result["visibility"] = visibility
if number:
result["number"] = number
if extra_data:
result["extra_data"] = extra_data
return result

def buildLeaderboardEntry(self, test):
Expand Down