-
Notifications
You must be signed in to change notification settings - Fork 0
/
models.py
141 lines (109 loc) · 4.88 KB
/
models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import base64
from dataclasses import dataclass, field
from enum import Enum
from dataclasses_json import DataClassJsonMixin, LetterCase, Undefined, config
class DataClassJsonCamelMixIn(DataClassJsonMixin):
dataclass_json_config = config(letter_case=LetterCase.CAMEL, undefined=Undefined.EXCLUDE)['dataclasses_json']
def base64_to_bytes(data: dict[str, str] | None) -> dict[str, bytes] | None:
if data is not None:
print('base64_to_bytes:', {filename: type(content) for filename, content in (data or {}).items()})
if data is not None and all(isinstance(content, str) for content in data.values()):
return {filename: base64.b64decode(content.encode('utf-8')) for filename, content in data.items()}
return data
def bytes_to_base64(data: dict[str, bytes] | None) -> dict[str, str] | None:
if data is not None:
print('bytes_to_base64:', {filename: type(content) for filename, content in (data or {}).items()})
if data is not None and all(isinstance(content, bytes) for content in data.values()):
return {filename: base64.b64encode(content).decode('utf-8') for filename, content in data.items()}
return data
class Status(Enum):
OK = 'Solved'
WA = 'Wrong answer'
TLE = 'Time limit exceeded'
MLE = 'Memory limit exceeded'
OLE = 'Output limit exceeded'
RUNTIME_ERROR = 'Runtime error'
COMPILATION_ERROR = 'Compilation error'
LINTING_ERROR = 'Linting error'
SKIPPED = 'Skipped'
@dataclass
class TestCase(DataClassJsonCamelMixIn):
input: str
target: str
input_files: dict[str, str] | None = None # mapping filename -> textual content
target_files: dict[str, str] | None = None # mapping filename -> textual content
input_assets: dict[str, bytes] | None = field( # mapping filename -> binary content
metadata=config(encoder=bytes_to_base64, decoder=base64_to_bytes),
default=None,
)
target_assets: dict[str, bytes] | None = field( # mapping filename -> binary content
metadata=config(encoder=bytes_to_base64, decoder=base64_to_bytes),
default=None,
)
@dataclass
class TestGroup(DataClassJsonCamelMixIn):
points: float
points_per_test: float
count: int
def __post_init__(self):
if self.points != 0 and self.points_per_test != 0:
raise ValueError('Both points and points_per_test values are nonzero')
# Defining a recursive type doesn't seem to work with dataclasses-json
CodeTree = dict[str, str | dict[str, str | dict[str, str]]]
@dataclass
class SubmissionRequest(DataClassJsonCamelMixIn):
code: CodeTree # Mapping from filename.extension -> content (Http requests have 2MB limit)
language: str
id: str | None = None # Used to identify the submission (completely optional)
memory_limit: int = 512 # MB
time_limit: float = 5 # seconds
output_limit: float = 1 # MB
# In case of both problem and test_cases being provided, tests = test_cases + problem.tests
problem: str | None = None # used to find the test cases in the EFS
test_cases: list[TestCase] | None = None # list of test cases
test_groups: list[TestGroup] | None = None
return_outputs: bool = False
stop_on_first_fail: bool = True
lint: bool = False
# Checker parameters
comparison_mode: str = 'whole' # whole | token | custom
float_precision: float = 1e-5 # Floating point precision
delimiter: str | None = None
checker_code: CodeTree | None = None
checker_language: str | None = None
callback_url: str | None = None # Where to send the results when they're ready
encryption_key: str | None = None
def __post_init__(self):
self.language = self.language.lower()
if self.checker_language:
self.checker_language = self.checker_language.lower()
if self.test_cases is None:
self.test_cases = []
if self.comparison_mode == 'custom':
assert self.checker_code is not None and self.checker_language is not None
@dataclass
class RunResult(DataClassJsonCamelMixIn):
status: Status
memory: float
time: float
return_code: int
score: float = 0
message: str | None = None
outputs: str | None = None
errors: str | None = None
output_files: dict[str, str] | None = None # mapping filename -> textual content
output_assets: dict[str, bytes] | None = field( # mapping filename -> binary content
metadata=config(encoder=bytes_to_base64, decoder=base64_to_bytes),
default=None,
)
@dataclass
class SubmissionResult(DataClassJsonCamelMixIn):
overall: RunResult
compile_result: RunResult
linting_result: RunResult | None = None
test_results: list[RunResult] | None = None
@dataclass
class SyncRequest(DataClassJsonCamelMixIn):
bucket: str
key: str
encryption_key: str