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.
Files changed (53) hide show
  1. rbx/box/builder.py +6 -6
  2. rbx/box/checkers.py +105 -26
  3. rbx/box/cli.py +860 -0
  4. rbx/box/code.py +199 -84
  5. rbx/box/contest/statements.py +4 -2
  6. rbx/box/generators.py +55 -49
  7. rbx/box/generators_test.py +7 -7
  8. rbx/box/main.py +1 -852
  9. rbx/box/package.py +42 -1
  10. rbx/box/packaging/boca/packager.py +2 -1
  11. rbx/box/packaging/main.py +24 -7
  12. rbx/box/packaging/moj/packager.py +164 -0
  13. rbx/box/retries.py +5 -5
  14. rbx/box/schema.py +86 -4
  15. rbx/box/solutions.py +46 -108
  16. rbx/box/solutions_test.py +5 -6
  17. rbx/box/statements/build_statements.py +4 -2
  18. rbx/box/stresses.py +23 -12
  19. rbx/box/tasks.py +258 -0
  20. rbx/box/testcase_extractors.py +21 -21
  21. rbx/box/testcases/main.py +19 -14
  22. rbx/box/unit.py +116 -0
  23. rbx/box/validators.py +27 -18
  24. rbx/box/validators_test.py +3 -3
  25. rbx/grading/judge/sandbox.py +8 -0
  26. rbx/grading/judge/sandboxes/stupid_sandbox.py +12 -7
  27. rbx/grading/judge/sandboxes/timeit.py +8 -2
  28. rbx/grading/steps.py +76 -2
  29. rbx/grading/steps_with_caching.py +45 -3
  30. rbx/grading/steps_with_caching_run_test.py +51 -49
  31. rbx/resources/packagers/moj/scripts/compare.sh +101 -0
  32. rbx/test.py +6 -4
  33. rbx/testdata/interactive/checker.cpp +21 -0
  34. rbx/testdata/interactive/gen.cpp +11 -0
  35. rbx/testdata/interactive/interactor.cpp +63 -0
  36. rbx/testdata/interactive/problem.rbx.yml +40 -0
  37. rbx/testdata/interactive/sols/af_ac_pe.cpp +75 -0
  38. rbx/testdata/interactive/sols/af_ac_re.cpp +76 -0
  39. rbx/testdata/interactive/sols/af_ac_too_many_iter.cpp +72 -0
  40. rbx/testdata/interactive/sols/af_inf_cout_with_flush.cpp +79 -0
  41. rbx/testdata/interactive/sols/af_inf_cout_without_flush.cpp +78 -0
  42. rbx/testdata/interactive/sols/af_ml.cpp +78 -0
  43. rbx/testdata/interactive/sols/af_tl_after_ans.cpp +74 -0
  44. rbx/testdata/interactive/sols/af_wa.cpp +74 -0
  45. rbx/testdata/interactive/sols/interactive-binary-search_mm_naive_cin.cpp +17 -0
  46. rbx/testdata/interactive/sols/main.cpp +26 -0
  47. rbx/testdata/interactive/testplan.txt +6 -0
  48. rbx/testdata/interactive/validator.cpp +16 -0
  49. {rbx_cp-0.5.39.dist-info → rbx_cp-0.5.42.dist-info}/METADATA +2 -1
  50. {rbx_cp-0.5.39.dist-info → rbx_cp-0.5.42.dist-info}/RECORD +53 -32
  51. {rbx_cp-0.5.39.dist-info → rbx_cp-0.5.42.dist-info}/LICENSE +0 -0
  52. {rbx_cp-0.5.39.dist-info → rbx_cp-0.5.42.dist-info}/WHEEL +0 -0
  53. {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
- if (
139
- checker_run_log is not None
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
- console.console.print(
150
- f'[error]Summary:[/error] {checker_run_log.get_summary()}'
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
- if checker_run_log is None or checker_run_log.exitcode not in [0, 1, 2, 3]:
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(checker_digest, run_log, testcase, program_output, skip_run_log)
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