rbx.cp 0.5.39__py3-none-any.whl → 0.5.42__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rbx/box/builder.py +6 -6
- rbx/box/checkers.py +105 -26
- rbx/box/cli.py +860 -0
- rbx/box/code.py +199 -84
- rbx/box/contest/statements.py +4 -2
- rbx/box/generators.py +55 -49
- rbx/box/generators_test.py +7 -7
- rbx/box/main.py +1 -852
- rbx/box/package.py +42 -1
- rbx/box/packaging/boca/packager.py +2 -1
- rbx/box/packaging/main.py +24 -7
- rbx/box/packaging/moj/packager.py +164 -0
- rbx/box/retries.py +5 -5
- rbx/box/schema.py +86 -4
- rbx/box/solutions.py +46 -108
- rbx/box/solutions_test.py +5 -6
- rbx/box/statements/build_statements.py +4 -2
- rbx/box/stresses.py +23 -12
- rbx/box/tasks.py +258 -0
- rbx/box/testcase_extractors.py +21 -21
- rbx/box/testcases/main.py +19 -14
- rbx/box/unit.py +116 -0
- rbx/box/validators.py +27 -18
- rbx/box/validators_test.py +3 -3
- rbx/grading/judge/sandbox.py +8 -0
- rbx/grading/judge/sandboxes/stupid_sandbox.py +12 -7
- rbx/grading/judge/sandboxes/timeit.py +8 -2
- rbx/grading/steps.py +76 -2
- rbx/grading/steps_with_caching.py +45 -3
- rbx/grading/steps_with_caching_run_test.py +51 -49
- rbx/resources/packagers/moj/scripts/compare.sh +101 -0
- rbx/test.py +6 -4
- rbx/testdata/interactive/checker.cpp +21 -0
- rbx/testdata/interactive/gen.cpp +11 -0
- rbx/testdata/interactive/interactor.cpp +63 -0
- rbx/testdata/interactive/problem.rbx.yml +40 -0
- rbx/testdata/interactive/sols/af_ac_pe.cpp +75 -0
- rbx/testdata/interactive/sols/af_ac_re.cpp +76 -0
- rbx/testdata/interactive/sols/af_ac_too_many_iter.cpp +72 -0
- rbx/testdata/interactive/sols/af_inf_cout_with_flush.cpp +79 -0
- rbx/testdata/interactive/sols/af_inf_cout_without_flush.cpp +78 -0
- rbx/testdata/interactive/sols/af_ml.cpp +78 -0
- rbx/testdata/interactive/sols/af_tl_after_ans.cpp +74 -0
- rbx/testdata/interactive/sols/af_wa.cpp +74 -0
- rbx/testdata/interactive/sols/interactive-binary-search_mm_naive_cin.cpp +17 -0
- rbx/testdata/interactive/sols/main.cpp +26 -0
- rbx/testdata/interactive/testplan.txt +6 -0
- rbx/testdata/interactive/validator.cpp +16 -0
- {rbx_cp-0.5.39.dist-info → rbx_cp-0.5.42.dist-info}/METADATA +2 -1
- {rbx_cp-0.5.39.dist-info → rbx_cp-0.5.42.dist-info}/RECORD +53 -32
- {rbx_cp-0.5.39.dist-info → rbx_cp-0.5.42.dist-info}/LICENSE +0 -0
- {rbx_cp-0.5.39.dist-info → rbx_cp-0.5.42.dist-info}/WHEEL +0 -0
- {rbx_cp-0.5.39.dist-info → rbx_cp-0.5.42.dist-info}/entry_points.txt +0 -0
rbx/box/builder.py
CHANGED
@@ -20,7 +20,7 @@ from rbx.box.validators import (
|
|
20
20
|
)
|
21
21
|
|
22
22
|
|
23
|
-
def build(
|
23
|
+
async def build(
|
24
24
|
verification: environment.VerificationParam,
|
25
25
|
groups: Optional[Set[str]] = None,
|
26
26
|
output: Optional[bool] = True,
|
@@ -35,7 +35,7 @@ def build(
|
|
35
35
|
'Built [item]{processed}[/item] testcases...',
|
36
36
|
keep=True,
|
37
37
|
) as s:
|
38
|
-
generate_testcases(s, groups=groups)
|
38
|
+
await generate_testcases(s, groups=groups)
|
39
39
|
|
40
40
|
if verification > 0:
|
41
41
|
validator = package.get_validator_or_nil()
|
@@ -50,7 +50,7 @@ def build(
|
|
50
50
|
'Validated [item]{processed}[/item] testcases...',
|
51
51
|
keep=True,
|
52
52
|
) as s:
|
53
|
-
infos = validate_testcases(
|
53
|
+
infos = await validate_testcases(
|
54
54
|
s,
|
55
55
|
groups=groups,
|
56
56
|
)
|
@@ -70,9 +70,9 @@ def build(
|
|
70
70
|
if output:
|
71
71
|
entries = [
|
72
72
|
entry.group_entry
|
73
|
-
for entry in extract_generation_testcases_from_groups(groups)
|
73
|
+
for entry in await extract_generation_testcases_from_groups(groups)
|
74
74
|
]
|
75
|
-
generate_outputs_for_testcases(entries, s)
|
75
|
+
await generate_outputs_for_testcases(entries, s)
|
76
76
|
|
77
77
|
console.console.print(
|
78
78
|
'[success]Problem built.[/success] '
|
@@ -88,7 +88,7 @@ def build(
|
|
88
88
|
|
89
89
|
|
90
90
|
async def verify(verification: environment.VerificationParam) -> bool:
|
91
|
-
if not build(verification=verification):
|
91
|
+
if not await build(verification=verification):
|
92
92
|
return False
|
93
93
|
|
94
94
|
if verification < VerificationLevel.FAST_SOLUTIONS.value:
|
rbx/box/checkers.py
CHANGED
@@ -17,11 +17,15 @@ from rbx.grading.steps import (
|
|
17
17
|
Outcome,
|
18
18
|
RunLog,
|
19
19
|
)
|
20
|
+
from rbx.utils import StatusProgress
|
20
21
|
|
21
22
|
|
22
|
-
def compile_checker() -> str:
|
23
|
+
def compile_checker(progress: Optional[StatusProgress] = None) -> str:
|
23
24
|
checker = package.get_checker()
|
24
25
|
|
26
|
+
if progress:
|
27
|
+
progress.update('Compiling checker...')
|
28
|
+
|
25
29
|
try:
|
26
30
|
digest = compile_item(checker, sanitized=SanitizationLevel.PREFER)
|
27
31
|
except Exception as e:
|
@@ -30,6 +34,24 @@ def compile_checker() -> str:
|
|
30
34
|
return digest
|
31
35
|
|
32
36
|
|
37
|
+
def compile_interactor(progress: Optional[StatusProgress] = None) -> str:
|
38
|
+
interactor = package.get_interactor()
|
39
|
+
|
40
|
+
if interactor is None:
|
41
|
+
console.console.print('[error]No interactor found for this problem.[/error]')
|
42
|
+
raise typer.Exit(1)
|
43
|
+
|
44
|
+
if progress:
|
45
|
+
progress.update('Compiling interactor...')
|
46
|
+
|
47
|
+
try:
|
48
|
+
digest = compile_item(interactor, sanitized=SanitizationLevel.PREFER)
|
49
|
+
except Exception as e:
|
50
|
+
console.console.print('[error]Failed compiling interactor.[/error]')
|
51
|
+
raise typer.Exit(1) from e
|
52
|
+
return digest
|
53
|
+
|
54
|
+
|
33
55
|
def _check_pre_output(run_log: Optional[RunLog]) -> CheckerResult:
|
34
56
|
pkg = package.find_problem_package_or_die()
|
35
57
|
|
@@ -86,12 +108,39 @@ def _convert_tle(result: CheckerResult, run_log: Optional[RunLog]) -> CheckerRes
|
|
86
108
|
return result
|
87
109
|
|
88
110
|
|
111
|
+
def process_checker_run_log(
|
112
|
+
checker_run_log: Optional[RunLog], message: str
|
113
|
+
) -> Optional[CheckerResult]:
|
114
|
+
if (
|
115
|
+
checker_run_log is not None
|
116
|
+
and checker_run_log.exitcode != 0
|
117
|
+
and (
|
118
|
+
checker_run_log.exitstatus != SandboxBase.EXIT_NONZERO_RETURN
|
119
|
+
or checker_run_log.exitcode not in [0, 1, 2, 3]
|
120
|
+
)
|
121
|
+
):
|
122
|
+
return None
|
123
|
+
|
124
|
+
if checker_run_log is None:
|
125
|
+
return CheckerResult(outcome=Outcome.INTERNAL_ERROR)
|
126
|
+
if checker_run_log.exitcode not in [0, 1, 2, 3]:
|
127
|
+
return None
|
128
|
+
|
129
|
+
result = CheckerResult(outcome=Outcome.ACCEPTED, message=message)
|
130
|
+
|
131
|
+
if checker_run_log.exitcode in [1, 2]:
|
132
|
+
result = CheckerResult(outcome=Outcome.WRONG_ANSWER, message=message)
|
133
|
+
if checker_run_log.exitcode == 3:
|
134
|
+
result = CheckerResult(outcome=Outcome.JUDGE_FAILED, message=message)
|
135
|
+
return result
|
136
|
+
|
137
|
+
|
89
138
|
def check_with_no_output(run_log: Optional[RunLog]) -> CheckerResult:
|
90
139
|
result = _check_pre_output(run_log)
|
91
140
|
return _convert_tle(result, run_log)
|
92
141
|
|
93
142
|
|
94
|
-
def _check(
|
143
|
+
async def _check(
|
95
144
|
checker_digest: str,
|
96
145
|
run_log: Optional[RunLog],
|
97
146
|
testcase: Testcase,
|
@@ -118,7 +167,7 @@ def _check(
|
|
118
167
|
dest=pathlib.PosixPath('input.txt'),
|
119
168
|
),
|
120
169
|
GradingFileInput(
|
121
|
-
src=testcase.outputPath,
|
170
|
+
src=testcase.outputPath or package.get_empty_sentinel_path(),
|
122
171
|
dest=pathlib.PosixPath('expected.txt'),
|
123
172
|
),
|
124
173
|
GradingFileInput(
|
@@ -126,7 +175,7 @@ def _check(
|
|
126
175
|
dest=pathlib.PosixPath('output.txt'),
|
127
176
|
),
|
128
177
|
]
|
129
|
-
checker_run_log = run_item(
|
178
|
+
checker_run_log = await run_item(
|
130
179
|
package.get_checker(),
|
131
180
|
DigestOrSource.create(checker_digest),
|
132
181
|
stderr=DigestOrDest.create(error),
|
@@ -135,20 +184,15 @@ def _check(
|
|
135
184
|
)
|
136
185
|
message = package.get_digest_as_string(error.value or '') or ''
|
137
186
|
|
138
|
-
|
139
|
-
|
140
|
-
and checker_run_log.exitcode != 0
|
141
|
-
and (
|
142
|
-
checker_run_log.exitstatus != SandboxBase.EXIT_NONZERO_RETURN
|
143
|
-
or checker_run_log.exitcode not in [0, 1, 2, 3]
|
144
|
-
)
|
145
|
-
):
|
187
|
+
processed_checker_result = process_checker_run_log(checker_run_log, message)
|
188
|
+
if processed_checker_result is None:
|
146
189
|
console.console.print(
|
147
190
|
f'[error]Checker [item]{package.get_checker().path}[/item] failed unexpectedly.[/error]'
|
148
191
|
)
|
149
|
-
|
150
|
-
|
151
|
-
|
192
|
+
if checker_run_log is not None:
|
193
|
+
console.console.print(
|
194
|
+
f'[error]Summary:[/error] {checker_run_log.get_summary()}'
|
195
|
+
)
|
152
196
|
console.console.print(
|
153
197
|
f'[error]Testcase input:[/error] [item]{testcase.inputPath}[/item]'
|
154
198
|
)
|
@@ -160,15 +204,7 @@ def _check(
|
|
160
204
|
)
|
161
205
|
raise typer.Exit(1)
|
162
206
|
|
163
|
-
|
164
|
-
return CheckerResult(outcome=Outcome.INTERNAL_ERROR)
|
165
|
-
|
166
|
-
result = CheckerResult(outcome=Outcome.ACCEPTED, message=message)
|
167
|
-
|
168
|
-
if checker_run_log.exitcode in [1, 2]:
|
169
|
-
result = CheckerResult(outcome=Outcome.WRONG_ANSWER, message=message)
|
170
|
-
if checker_run_log.exitcode == 3:
|
171
|
-
result = CheckerResult(outcome=Outcome.JUDGE_FAILED, message=message)
|
207
|
+
result = processed_checker_result
|
172
208
|
|
173
209
|
if skip_run_log:
|
174
210
|
return result
|
@@ -181,13 +217,56 @@ def _check_sanitizer_warnings(run_log: Optional[RunLog]) -> bool:
|
|
181
217
|
return run_log.warnings
|
182
218
|
|
183
219
|
|
184
|
-
def check(
|
220
|
+
async def check(
|
185
221
|
checker_digest: str,
|
186
222
|
run_log: Optional[RunLog],
|
187
223
|
testcase: Testcase,
|
188
224
|
program_output: pathlib.Path,
|
189
225
|
skip_run_log: bool = False,
|
190
226
|
) -> CheckerResult:
|
191
|
-
result = _check(
|
227
|
+
result = await _check(
|
228
|
+
checker_digest, run_log, testcase, program_output, skip_run_log
|
229
|
+
)
|
192
230
|
result.sanitizer_warnings = _check_sanitizer_warnings(run_log)
|
193
231
|
return result
|
232
|
+
|
233
|
+
|
234
|
+
async def check_communication(
|
235
|
+
checker_digest: Optional[str],
|
236
|
+
run_log: Optional[RunLog],
|
237
|
+
interactor_run_log: Optional[RunLog],
|
238
|
+
interactor_stderr: pathlib.Path,
|
239
|
+
testcase: Testcase,
|
240
|
+
program_output: pathlib.Path,
|
241
|
+
skip_run_log: bool = False,
|
242
|
+
) -> CheckerResult:
|
243
|
+
sanitizer_warnings = _check_sanitizer_warnings(run_log)
|
244
|
+
|
245
|
+
result = check_with_no_output(run_log)
|
246
|
+
result.sanitizer_warnings = sanitizer_warnings
|
247
|
+
if result.outcome != Outcome.ACCEPTED:
|
248
|
+
return result
|
249
|
+
|
250
|
+
result = process_checker_run_log(
|
251
|
+
interactor_run_log,
|
252
|
+
interactor_stderr.read_text(),
|
253
|
+
)
|
254
|
+
|
255
|
+
if result is None:
|
256
|
+
result = check_with_no_output(interactor_run_log)
|
257
|
+
result.sanitizer_warnings = sanitizer_warnings
|
258
|
+
if result.outcome != Outcome.ACCEPTED:
|
259
|
+
result.outcome = Outcome.JUDGE_FAILED
|
260
|
+
return result
|
261
|
+
|
262
|
+
result.sanitizer_warnings = sanitizer_warnings
|
263
|
+
if result.outcome != Outcome.ACCEPTED:
|
264
|
+
return result
|
265
|
+
|
266
|
+
if checker_digest is not None:
|
267
|
+
result = await check(
|
268
|
+
checker_digest, run_log, testcase, program_output, skip_run_log
|
269
|
+
)
|
270
|
+
result.sanitizer_warnings = sanitizer_warnings
|
271
|
+
|
272
|
+
return result
|