rbx.cp 0.18.3__py3-none-any.whl → 0.18.5__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/__version__.py +1 -1
- rbx/box/cli.py +7 -0
- rbx/box/code.py +26 -18
- rbx/box/contest/build_contest_statements.py +21 -15
- rbx/box/environment.py +1 -1
- rbx/box/exception.py +71 -0
- rbx/box/generators.py +16 -10
- rbx/box/main.py +12 -1
- rbx/box/solutions.py +75 -23
- rbx/box/statements/latex.py +5 -4
- rbx/box/stresses.py +29 -11
- rbx/console.py +4 -0
- rbx/grading/judge/sandboxes/tee.py +8 -2
- rbx/grading/steps.py +18 -12
- rbx/grading/steps_with_caching.py +14 -10
- rbx/resources/presets/default/env.rbx.yml +1 -1
- rbx/resources/presets/default/preset.rbx.yml +1 -1
- {rbx_cp-0.18.3.dist-info → rbx_cp-0.18.5.dist-info}/METADATA +1 -1
- {rbx_cp-0.18.3.dist-info → rbx_cp-0.18.5.dist-info}/RECORD +22 -22
- rbx/resources/envs/default.rbx.yml +0 -67
- {rbx_cp-0.18.3.dist-info → rbx_cp-0.18.5.dist-info}/LICENSE +0 -0
- {rbx_cp-0.18.3.dist-info → rbx_cp-0.18.5.dist-info}/WHEEL +0 -0
- {rbx_cp-0.18.3.dist-info → rbx_cp-0.18.5.dist-info}/entry_points.txt +0 -0
rbx/__version__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = '0.18.
|
1
|
+
__version__ = '0.18.5'
|
rbx/box/cli.py
CHANGED
@@ -680,6 +680,12 @@ async def stress(
|
|
680
680
|
help='Whether to print descriptors of the stress test.',
|
681
681
|
hidden=True,
|
682
682
|
),
|
683
|
+
skip_invalid_testcases: bool = typer.Option(
|
684
|
+
False,
|
685
|
+
'--skip-invalid',
|
686
|
+
'--skip',
|
687
|
+
help='Whether to skip invalid testcases.',
|
688
|
+
),
|
683
689
|
):
|
684
690
|
if finder and not generator_args or generator_args and not finder:
|
685
691
|
console.console.print(
|
@@ -701,6 +707,7 @@ async def stress(
|
|
701
707
|
verbose=verbose,
|
702
708
|
sanitized=sanitized,
|
703
709
|
print_descriptors=print_descriptors,
|
710
|
+
skip_invalid_testcases=skip_invalid_testcases,
|
704
711
|
)
|
705
712
|
|
706
713
|
stresses.print_stress_report(report)
|
rbx/box/code.py
CHANGED
@@ -443,17 +443,19 @@ def _precompile_header(
|
|
443
443
|
)
|
444
444
|
|
445
445
|
with profiling.PushContext('code.precompile_header'):
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
446
|
+
try:
|
447
|
+
steps_with_caching.compile(
|
448
|
+
commands,
|
449
|
+
params=sandbox_params,
|
450
|
+
artifacts=precompilation_artifacts,
|
451
|
+
sandbox=sandbox,
|
452
|
+
dependency_cache=dependency_cache,
|
453
|
+
)
|
454
|
+
except steps.CompilationError as e:
|
455
|
+
e.print(
|
454
456
|
f'[error]Failed to precompile header file: [item]{input_artifact.src}[/item][/error]'
|
455
457
|
)
|
456
|
-
raise
|
458
|
+
raise
|
457
459
|
|
458
460
|
if verbose:
|
459
461
|
console.console.print(
|
@@ -487,13 +489,14 @@ def _precompile_header(
|
|
487
489
|
):
|
488
490
|
input = DigestOrSource.create(local_cacher.put_file_from_fobj(f))
|
489
491
|
|
490
|
-
|
492
|
+
res = GradingFileInput(
|
491
493
|
**input.expand(),
|
492
494
|
dest=input_artifact.dest.with_suffix('.h.gch'),
|
493
495
|
# Do not track fingerprint of the precompiled header file,
|
494
496
|
# trust the compilation step above.
|
495
497
|
hash=False,
|
496
498
|
)
|
499
|
+
return res
|
497
500
|
|
498
501
|
|
499
502
|
# Compile code item and return its digest in the storage.
|
@@ -609,14 +612,19 @@ def compile_item(
|
|
609
612
|
grading_context.CacheLevel.NO_CACHE,
|
610
613
|
when=lambda: is_path_remote(code.path),
|
611
614
|
):
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
615
|
+
try:
|
616
|
+
steps_with_caching.compile(
|
617
|
+
commands,
|
618
|
+
params=sandbox_params,
|
619
|
+
artifacts=artifacts,
|
620
|
+
sandbox=sandbox,
|
621
|
+
dependency_cache=dependency_cache,
|
622
|
+
)
|
623
|
+
except steps.CompilationError as e:
|
624
|
+
e.print(
|
625
|
+
f'[error]Failed to compile item: [item]{code.path}[/item][/error]'
|
626
|
+
)
|
627
|
+
raise
|
620
628
|
|
621
629
|
assert compiled_digest.value is not None
|
622
630
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import dataclasses
|
2
2
|
import pathlib
|
3
|
+
import shutil
|
3
4
|
import tempfile
|
4
5
|
import typing
|
5
6
|
from typing import Any, Dict, List, Optional, Tuple
|
@@ -228,10 +229,10 @@ def _build_problem_statements(
|
|
228
229
|
)
|
229
230
|
issue_stack.add_issue(StatementBuildIssue(extracted_problem.problem))
|
230
231
|
continue
|
231
|
-
dest_dir =
|
232
|
+
dest_dir = pathlib.Path('.problems') / extracted_problem.problem.short_name
|
232
233
|
dest_path = dest_dir / f'statement{output_type.get_file_suffix()}'
|
233
|
-
dest_dir.mkdir(parents=True, exist_ok=True)
|
234
|
-
dest_path.write_bytes(content)
|
234
|
+
(root / dest_dir).mkdir(parents=True, exist_ok=True)
|
235
|
+
(root / dest_path).write_bytes(content)
|
235
236
|
|
236
237
|
problem_assets = (
|
237
238
|
get_relative_assets(
|
@@ -240,7 +241,7 @@ def _build_problem_statements(
|
|
240
241
|
)
|
241
242
|
+ contest_assets
|
242
243
|
)
|
243
|
-
prepare_assets(problem_assets, dest_dir)
|
244
|
+
prepare_assets(problem_assets, root / dest_dir)
|
244
245
|
|
245
246
|
res.append(dataclasses.replace(extracted_problem, built_statement=dest_path))
|
246
247
|
return res
|
@@ -393,6 +394,10 @@ def build_statement_rooted(
|
|
393
394
|
return last_content, last_output
|
394
395
|
|
395
396
|
|
397
|
+
def get_statement_build_dir(statement: ContestStatement) -> pathlib.Path:
|
398
|
+
return pathlib.Path('build') / 'statement_build' / statement.name
|
399
|
+
|
400
|
+
|
396
401
|
def build_statement(
|
397
402
|
statement: ContestStatement,
|
398
403
|
contest: Contest,
|
@@ -401,17 +406,18 @@ def build_statement(
|
|
401
406
|
custom_vars: Optional[Dict[str, Any]] = None,
|
402
407
|
install_tex: bool = False,
|
403
408
|
) -> pathlib.Path:
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
409
|
+
root = get_statement_build_dir(statement)
|
410
|
+
shutil.rmtree(root, ignore_errors=True)
|
411
|
+
root.mkdir(parents=True, exist_ok=True)
|
412
|
+
last_content, last_output = build_statement_rooted(
|
413
|
+
statement,
|
414
|
+
contest,
|
415
|
+
root,
|
416
|
+
output_type=output_type,
|
417
|
+
use_samples=use_samples,
|
418
|
+
custom_vars=custom_vars,
|
419
|
+
install_tex=install_tex,
|
420
|
+
)
|
415
421
|
|
416
422
|
statement_path = (pathlib.Path('build') / statement.name).with_suffix(
|
417
423
|
last_output.get_file_suffix()
|
rbx/box/environment.py
CHANGED
@@ -252,7 +252,7 @@ execution config can be individually overridden in the language configuration.""
|
|
252
252
|
|
253
253
|
|
254
254
|
def get_app_environment_path(env: str) -> pathlib.Path:
|
255
|
-
return config.get_resources_file(pathlib.PosixPath('
|
255
|
+
return config.get_resources_file(pathlib.PosixPath('presets') / env / 'env.rbx.yml')
|
256
256
|
|
257
257
|
|
258
258
|
def get_active_environment_path() -> pathlib.Path:
|
rbx/box/exception.py
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
from typing import List, Optional
|
2
|
+
|
3
|
+
from rich.console import Capture, Console
|
4
|
+
|
5
|
+
from rbx import console
|
6
|
+
|
7
|
+
|
8
|
+
class PossiblyCapture:
|
9
|
+
def __init__(
|
10
|
+
self, console: Console, msg: List[str], capture: Optional[Capture] = None
|
11
|
+
):
|
12
|
+
self.console = console
|
13
|
+
self.msg = msg
|
14
|
+
self.capture = capture
|
15
|
+
self.actual_capture = None
|
16
|
+
|
17
|
+
def __enter__(self):
|
18
|
+
if self.capture is not None:
|
19
|
+
return
|
20
|
+
self.actual_capture = self.console.capture()
|
21
|
+
self.actual_capture.__enter__()
|
22
|
+
return self
|
23
|
+
|
24
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
25
|
+
if self.actual_capture is not None:
|
26
|
+
self.actual_capture.__exit__(exc_type, exc_value, traceback)
|
27
|
+
self.msg.append(self.actual_capture.get())
|
28
|
+
self.actual_capture = None
|
29
|
+
|
30
|
+
|
31
|
+
class RbxException(RuntimeError):
|
32
|
+
def __init__(self):
|
33
|
+
super().__init__()
|
34
|
+
self.msg = []
|
35
|
+
self.capture = None
|
36
|
+
self.console = console.new_console()
|
37
|
+
|
38
|
+
def possibly_capture(self):
|
39
|
+
return PossiblyCapture(self.console, self.msg, self.capture)
|
40
|
+
|
41
|
+
def rule(self, *args, **kwargs):
|
42
|
+
with self.possibly_capture():
|
43
|
+
self.console.rule(*args, **kwargs)
|
44
|
+
|
45
|
+
def print(self, *args, **kwargs):
|
46
|
+
with self.possibly_capture():
|
47
|
+
self.console.print(*args, **kwargs)
|
48
|
+
|
49
|
+
def log(self, *args, **kwargs):
|
50
|
+
with self.possibly_capture():
|
51
|
+
self.console.log(*args, **kwargs)
|
52
|
+
|
53
|
+
def __enter__(self):
|
54
|
+
capture = self.console.capture()
|
55
|
+
capture.__enter__()
|
56
|
+
self.capture = capture
|
57
|
+
return self
|
58
|
+
|
59
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
60
|
+
if self.capture is not None:
|
61
|
+
self.capture.__exit__(exc_type, exc_value, traceback)
|
62
|
+
self.msg.append(self.capture.get())
|
63
|
+
self.capture = None
|
64
|
+
if exc_type is not None:
|
65
|
+
return
|
66
|
+
raise self
|
67
|
+
|
68
|
+
def __str__(self) -> str:
|
69
|
+
if not self.msg:
|
70
|
+
return ''
|
71
|
+
return ''.join(self.msg)
|
rbx/box/generators.py
CHANGED
@@ -4,10 +4,12 @@ import shutil
|
|
4
4
|
from typing import Dict, List, Optional, Set
|
5
5
|
|
6
6
|
import typer
|
7
|
+
from rich.console import Console
|
7
8
|
|
8
9
|
from rbx import console
|
9
10
|
from rbx.box import checkers, package, testcase_utils, validators
|
10
11
|
from rbx.box.code import SanitizationLevel, compile_item, run_item
|
12
|
+
from rbx.box.exception import RbxException
|
11
13
|
from rbx.box.schema import (
|
12
14
|
CodeItem,
|
13
15
|
GeneratorCall,
|
@@ -37,6 +39,10 @@ from rbx.grading.steps import (
|
|
37
39
|
from rbx.utils import StatusProgress
|
38
40
|
|
39
41
|
|
42
|
+
class ValidationError(RbxException):
|
43
|
+
pass
|
44
|
+
|
45
|
+
|
40
46
|
def _compile_generator(generator: CodeItem) -> str:
|
41
47
|
return compile_item(generator, sanitized=SanitizationLevel.PREFER)
|
42
48
|
|
@@ -261,7 +267,7 @@ async def generate_standalone(
|
|
261
267
|
validator_digest: Optional[str] = None,
|
262
268
|
progress: Optional[StatusProgress] = None,
|
263
269
|
):
|
264
|
-
def _print_error_header(text: Optional[str] = None):
|
270
|
+
def _print_error_header(console: Console, text: Optional[str] = None):
|
265
271
|
prefix = 'Failed generating test'
|
266
272
|
if group_entry is not None:
|
267
273
|
prefix += (
|
@@ -271,11 +277,11 @@ async def generate_standalone(
|
|
271
277
|
if text:
|
272
278
|
suffix = f': {text}'
|
273
279
|
if spec.generator_call is not None:
|
274
|
-
console.
|
280
|
+
console.print(
|
275
281
|
f'[error]{prefix} using generator call [info]{spec.generator_call.name} {spec.generator_call.args}[/info]{suffix}[/error]'
|
276
282
|
)
|
277
283
|
else:
|
278
|
-
console.
|
284
|
+
console.print(f'[error]{prefix}{suffix}[/error]')
|
279
285
|
|
280
286
|
if spec.generator_call is not None:
|
281
287
|
call = spec.generator_call
|
@@ -301,7 +307,7 @@ async def generate_standalone(
|
|
301
307
|
extra_args=call.args or None,
|
302
308
|
)
|
303
309
|
if not generation_log or generation_log.exitcode != 0:
|
304
|
-
_print_error_header()
|
310
|
+
_print_error_header(console.console)
|
305
311
|
if generation_log is not None:
|
306
312
|
console.console.print(
|
307
313
|
f'[error]Summary:[/error] {generation_log.get_summary()}'
|
@@ -333,12 +339,12 @@ async def generate_standalone(
|
|
333
339
|
validator_digest,
|
334
340
|
)
|
335
341
|
if not validation_info.ok:
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
+
with ValidationError() as err:
|
343
|
+
_print_error_header(err.console, 'failed validating testcase.')
|
344
|
+
err.print(f'[error]Message:[/error] {validation_info.message}')
|
345
|
+
err.print(
|
346
|
+
f'Testcase written at [item]{spec.copied_to.inputPath}[/item]'
|
347
|
+
)
|
342
348
|
|
343
349
|
|
344
350
|
async def generate_testcases(
|
rbx/box/main.py
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
# flake8: noqa
|
2
2
|
import nest_asyncio
|
3
|
+
import sys
|
4
|
+
|
5
|
+
from rbx.box.exception import RbxException
|
3
6
|
|
4
7
|
nest_asyncio.apply()
|
5
8
|
|
6
|
-
from rbx.box.cli import app
|
9
|
+
from rbx.box.cli import app as app_cli
|
10
|
+
|
11
|
+
|
12
|
+
def app():
|
13
|
+
try:
|
14
|
+
app_cli()
|
15
|
+
except RbxException as e:
|
16
|
+
print(str(e))
|
17
|
+
sys.exit(1)
|
rbx/box/solutions.py
CHANGED
@@ -55,7 +55,7 @@ from rbx.box.testcase_utils import (
|
|
55
55
|
parse_interaction,
|
56
56
|
print_interaction,
|
57
57
|
)
|
58
|
-
from rbx.grading import grading_context
|
58
|
+
from rbx.grading import grading_context, steps
|
59
59
|
from rbx.grading.limits import Limits
|
60
60
|
from rbx.grading.steps import (
|
61
61
|
Evaluation,
|
@@ -90,6 +90,7 @@ class SolutionReportSkeleton(BaseModel):
|
|
90
90
|
entries: List[TestcaseEntry]
|
91
91
|
groups: List[GroupSkeleton]
|
92
92
|
limits: Dict[str, Limits]
|
93
|
+
compiled_solutions: Dict[str, str]
|
93
94
|
verification: VerificationLevel
|
94
95
|
capture_pipes: bool = False
|
95
96
|
|
@@ -125,6 +126,9 @@ class SolutionReportSkeleton(BaseModel):
|
|
125
126
|
return i
|
126
127
|
return None
|
127
128
|
|
129
|
+
def get_solution_compiled_digest(self, solution: Solution) -> str:
|
130
|
+
return self.compiled_solutions[str(solution.path)]
|
131
|
+
|
128
132
|
def get_solution_path_set(self) -> Set[str]:
|
129
133
|
return set(str(sol.path) for sol in self.solutions)
|
130
134
|
|
@@ -179,10 +183,22 @@ def get_exact_matching_solutions(expected_outcome: ExpectedOutcome) -> List[Solu
|
|
179
183
|
return res
|
180
184
|
|
181
185
|
|
186
|
+
class FailedToCompileSolutionIssue(issue_stack.Issue):
|
187
|
+
def __init__(self, solution: Solution):
|
188
|
+
self.solution = solution
|
189
|
+
|
190
|
+
def get_detailed_section(self) -> Tuple[str, ...]:
|
191
|
+
return ('solutions',)
|
192
|
+
|
193
|
+
def get_detailed_message(self) -> str:
|
194
|
+
return f'[item]{href(self.solution.path)}[/item] could not be compiled and was skipped.'
|
195
|
+
|
196
|
+
|
182
197
|
def compile_solutions(
|
183
198
|
progress: Optional[StatusProgress] = None,
|
184
199
|
tracked_solutions: Optional[Set[str]] = None,
|
185
200
|
sanitized: bool = False,
|
201
|
+
fail_if_one: bool = True,
|
186
202
|
) -> Dict[pathlib.Path, str]:
|
187
203
|
compiled_solutions = {}
|
188
204
|
|
@@ -199,6 +215,10 @@ def compile_solutions(
|
|
199
215
|
if sanitized
|
200
216
|
else SanitizationLevel.NONE,
|
201
217
|
)
|
218
|
+
except steps.CompilationError:
|
219
|
+
if fail_if_one and len(tracked_solutions) <= 1:
|
220
|
+
raise
|
221
|
+
issue_stack.add_issue(FailedToCompileSolutionIssue(solution))
|
202
222
|
except:
|
203
223
|
console.console.print(
|
204
224
|
f'[error]Failed compiling solution {href(solution.path)}.[/error]'
|
@@ -283,13 +303,48 @@ def _get_solutions_for_skeleton(
|
|
283
303
|
return solutions
|
284
304
|
|
285
305
|
|
306
|
+
def _get_compiled_solutions_for_skeleton(
|
307
|
+
tracked_solutions: Optional[Iterable[str]] = None,
|
308
|
+
progress: Optional[StatusProgress] = None,
|
309
|
+
sanitized: bool = False,
|
310
|
+
verification: VerificationLevel = VerificationLevel.NONE,
|
311
|
+
) -> Tuple[List[Solution], Dict[str, str]]:
|
312
|
+
solutions_to_compile = _get_solutions_for_skeleton(tracked_solutions, verification)
|
313
|
+
|
314
|
+
compiled_solutions = compile_solutions(
|
315
|
+
progress=progress,
|
316
|
+
tracked_solutions=set(str(solution.path) for solution in solutions_to_compile),
|
317
|
+
sanitized=sanitized,
|
318
|
+
)
|
319
|
+
|
320
|
+
# TODO: Handle solutions that failed to compile.
|
321
|
+
solutions = [
|
322
|
+
solution
|
323
|
+
for solution in solutions_to_compile
|
324
|
+
if solution.path in compiled_solutions
|
325
|
+
]
|
326
|
+
|
327
|
+
return solutions, {
|
328
|
+
str(solution_path): digest
|
329
|
+
for solution_path, digest in compiled_solutions.items()
|
330
|
+
}
|
331
|
+
|
332
|
+
|
286
333
|
def _get_report_skeleton(
|
287
334
|
tracked_solutions: Optional[Iterable[str]] = None,
|
288
335
|
verification: VerificationLevel = VerificationLevel.NONE,
|
289
336
|
timelimit_override: Optional[int] = None,
|
337
|
+
progress: Optional[StatusProgress] = None,
|
338
|
+
sanitized: bool = False,
|
290
339
|
) -> SolutionReportSkeleton:
|
291
340
|
pkg = package.find_problem_package_or_die()
|
292
|
-
|
341
|
+
|
342
|
+
solutions, compiled_solutions = _get_compiled_solutions_for_skeleton(
|
343
|
+
tracked_solutions=tracked_solutions,
|
344
|
+
verification=verification,
|
345
|
+
progress=progress,
|
346
|
+
sanitized=sanitized,
|
347
|
+
)
|
293
348
|
|
294
349
|
langs = set(find_language_name(solution) for solution in solutions)
|
295
350
|
limits = {
|
@@ -324,6 +379,7 @@ def _get_report_skeleton(
|
|
324
379
|
groups=groups,
|
325
380
|
limits=limits,
|
326
381
|
entries=entries,
|
382
|
+
compiled_solutions=compiled_solutions,
|
327
383
|
verification=verification,
|
328
384
|
capture_pipes=state.STATE.debug_logs,
|
329
385
|
)
|
@@ -340,7 +396,6 @@ def _produce_solution_items(
|
|
340
396
|
verification: VerificationLevel = VerificationLevel.NONE,
|
341
397
|
check: bool = True,
|
342
398
|
timelimit_override: Optional[int] = None,
|
343
|
-
sanitized: bool = False,
|
344
399
|
nruns: int = 0,
|
345
400
|
) -> List[EvaluationItem]:
|
346
401
|
pkg = package.find_problem_package_or_die()
|
@@ -354,12 +409,6 @@ def _produce_solution_items(
|
|
354
409
|
checker_digest = checkers.compile_checker() if check else None
|
355
410
|
interactor_digest = None
|
356
411
|
|
357
|
-
compiled_solutions = compile_solutions(
|
358
|
-
progress=progress,
|
359
|
-
tracked_solutions=skeleton.get_solution_path_set(),
|
360
|
-
sanitized=sanitized,
|
361
|
-
)
|
362
|
-
|
363
412
|
def yield_items(
|
364
413
|
solution: SolutionSkeleton, group_name: str
|
365
414
|
) -> List[EvaluationItem]:
|
@@ -367,7 +416,7 @@ def _produce_solution_items(
|
|
367
416
|
for i, eval in enumerate(
|
368
417
|
_run_solution(
|
369
418
|
solution,
|
370
|
-
|
419
|
+
skeleton.get_solution_compiled_digest(solution),
|
371
420
|
checker_digest,
|
372
421
|
solution.runs_dir,
|
373
422
|
group_name,
|
@@ -425,9 +474,11 @@ def run_solutions(
|
|
425
474
|
nruns: int = 0,
|
426
475
|
) -> RunSolutionResult:
|
427
476
|
skeleton = _get_report_skeleton(
|
428
|
-
|
477
|
+
progress=progress,
|
478
|
+
tracked_solutions=tracked_solutions,
|
429
479
|
verification=verification,
|
430
480
|
timelimit_override=timelimit_override,
|
481
|
+
sanitized=sanitized,
|
431
482
|
)
|
432
483
|
result = RunSolutionResult(
|
433
484
|
skeleton=skeleton,
|
@@ -437,7 +488,6 @@ def run_solutions(
|
|
437
488
|
verification=verification,
|
438
489
|
check=check,
|
439
490
|
timelimit_override=timelimit_override,
|
440
|
-
sanitized=sanitized,
|
441
491
|
nruns=nruns,
|
442
492
|
),
|
443
493
|
)
|
@@ -588,7 +638,6 @@ def _run_interactive_solutions(
|
|
588
638
|
progress: Optional[StatusProgress] = None,
|
589
639
|
verification: VerificationLevel = VerificationLevel.NONE,
|
590
640
|
check: bool = True,
|
591
|
-
sanitized: bool = False,
|
592
641
|
) -> Iterator[EvaluationItem]:
|
593
642
|
pkg = package.find_problem_package_or_die()
|
594
643
|
|
@@ -599,12 +648,6 @@ def _run_interactive_solutions(
|
|
599
648
|
checker_digest = checkers.compile_checker() if check else None
|
600
649
|
interactor_digest = None
|
601
650
|
|
602
|
-
compiled_solutions = compile_solutions(
|
603
|
-
progress=progress,
|
604
|
-
tracked_solutions=skeleton.get_solution_path_set(),
|
605
|
-
sanitized=sanitized,
|
606
|
-
)
|
607
|
-
|
608
651
|
if progress:
|
609
652
|
progress.update('Running solutions...')
|
610
653
|
|
@@ -614,7 +657,7 @@ def _run_interactive_solutions(
|
|
614
657
|
async def run_fn(solution=solution, output_dir=output_dir):
|
615
658
|
return await run_solution_on_testcase(
|
616
659
|
solution,
|
617
|
-
|
660
|
+
skeleton.get_solution_compiled_digest(solution),
|
618
661
|
checker_digest,
|
619
662
|
testcase,
|
620
663
|
output_dir=output_dir,
|
@@ -632,9 +675,16 @@ def _run_interactive_solutions(
|
|
632
675
|
|
633
676
|
def _get_interactive_skeleton(
|
634
677
|
tracked_solutions: Optional[Iterable[str]] = None,
|
678
|
+
progress: Optional[StatusProgress] = None,
|
679
|
+
sanitized: bool = False,
|
635
680
|
verification: VerificationLevel = VerificationLevel.NONE,
|
636
681
|
) -> SolutionReportSkeleton:
|
637
|
-
solutions =
|
682
|
+
solutions, compiled_solutions = _get_compiled_solutions_for_skeleton(
|
683
|
+
tracked_solutions,
|
684
|
+
verification=verification,
|
685
|
+
progress=progress,
|
686
|
+
sanitized=sanitized,
|
687
|
+
)
|
638
688
|
|
639
689
|
langs = set(find_language_name(solution) for solution in solutions)
|
640
690
|
limits = {
|
@@ -660,6 +710,7 @@ def _get_interactive_skeleton(
|
|
660
710
|
limits=limits,
|
661
711
|
entries=[],
|
662
712
|
verification=verification,
|
713
|
+
compiled_solutions=compiled_solutions,
|
663
714
|
capture_pipes=True,
|
664
715
|
)
|
665
716
|
|
@@ -682,8 +733,10 @@ async def run_and_print_interactive_solutions(
|
|
682
733
|
):
|
683
734
|
pkg = package.find_problem_package_or_die()
|
684
735
|
skeleton = _get_interactive_skeleton(
|
685
|
-
tracked_solutions,
|
736
|
+
tracked_solutions=tracked_solutions,
|
686
737
|
verification=verification,
|
738
|
+
sanitized=sanitized,
|
739
|
+
progress=progress,
|
687
740
|
)
|
688
741
|
|
689
742
|
should_cache = testcase_entry is not None
|
@@ -705,7 +758,6 @@ async def run_and_print_interactive_solutions(
|
|
705
758
|
progress=progress,
|
706
759
|
verification=verification,
|
707
760
|
check=check,
|
708
|
-
sanitized=sanitized,
|
709
761
|
)
|
710
762
|
|
711
763
|
for item in items:
|
rbx/box/statements/latex.py
CHANGED
@@ -37,16 +37,17 @@ class Latex:
|
|
37
37
|
self.latex = latex
|
38
38
|
|
39
39
|
def build_pdf(self, temp_dir: pathlib.Path) -> LatexResult:
|
40
|
-
temp_path =
|
40
|
+
temp_path = pathlib.Path('statement.tex')
|
41
41
|
output_path = temp_path.with_suffix('.pdf')
|
42
42
|
args = ['pdflatex', '-interaction', 'nonstopmode', str(temp_path)]
|
43
|
-
|
43
|
+
|
44
|
+
(temp_dir / temp_path).write_text(self.latex)
|
44
45
|
|
45
46
|
completed = subprocess.run(args, timeout=15, capture_output=True, cwd=temp_dir)
|
46
|
-
if completed.returncode != 0 or not output_path.exists():
|
47
|
+
if completed.returncode != 0 or not (temp_dir / output_path).exists():
|
47
48
|
return LatexResult(result=completed, pdf=None)
|
48
49
|
|
49
|
-
return LatexResult(result=completed, pdf=output_path.read_bytes())
|
50
|
+
return LatexResult(result=completed, pdf=(temp_dir / output_path).read_bytes())
|
50
51
|
|
51
52
|
|
52
53
|
def install_tex_packages(path: pathlib.Path, cwd: pathlib.Path):
|
rbx/box/stresses.py
CHANGED
@@ -14,6 +14,7 @@ from rbx.box import checkers, generators, package, tasks, validators
|
|
14
14
|
from rbx.box.code import SanitizationLevel, compile_item
|
15
15
|
from rbx.box.generators import (
|
16
16
|
GenerationMetadata,
|
17
|
+
ValidationError,
|
17
18
|
expand_generator_call,
|
18
19
|
generate_standalone,
|
19
20
|
)
|
@@ -34,6 +35,7 @@ class StressFinding(BaseModel):
|
|
34
35
|
class StressReport(BaseModel):
|
35
36
|
findings: List[StressFinding] = []
|
36
37
|
executed: int = 0
|
38
|
+
skipped: int = 0
|
37
39
|
|
38
40
|
|
39
41
|
def _compile_finder(finder: CodeItem) -> str:
|
@@ -57,6 +59,7 @@ async def run_stress(
|
|
57
59
|
progress: Optional[StatusProgress] = None,
|
58
60
|
sanitized: bool = False,
|
59
61
|
print_descriptors: bool = False,
|
62
|
+
skip_invalid_testcases: bool = False,
|
60
63
|
) -> StressReport:
|
61
64
|
pkg = package.find_problem_package_or_die()
|
62
65
|
|
@@ -129,6 +132,7 @@ async def run_stress(
|
|
129
132
|
startTime = time.monotonic()
|
130
133
|
|
131
134
|
executed = 0
|
135
|
+
skipped = 0
|
132
136
|
findings = []
|
133
137
|
|
134
138
|
while len(findings) < findingsLimit:
|
@@ -142,9 +146,11 @@ async def run_stress(
|
|
142
146
|
|
143
147
|
if progress:
|
144
148
|
seconds = timeoutInSeconds - int(time.monotonic() - startTime)
|
149
|
+
skipped_str = f'skipped [item]{skipped}[/item], ' if skipped else ''
|
145
150
|
progress.update(
|
146
151
|
f'Stress testing: found [item]{len(findings)}[/item] tests, '
|
147
152
|
f'executed [item]{executed}[/item], '
|
153
|
+
f'{skipped_str}'
|
148
154
|
f'[item]{seconds}[/item] second(s) remaining...'
|
149
155
|
)
|
150
156
|
|
@@ -152,16 +158,26 @@ async def run_stress(
|
|
152
158
|
input_path.parent.mkdir(parents=True, exist_ok=True)
|
153
159
|
|
154
160
|
expanded_generator_call = expand_generator_call(stress.generator)
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
161
|
+
try:
|
162
|
+
await generate_standalone(
|
163
|
+
GenerationMetadata(
|
164
|
+
generator_call=expanded_generator_call,
|
165
|
+
copied_to=Testcase(inputPath=input_path),
|
166
|
+
),
|
167
|
+
generator_digest=generator_digest,
|
168
|
+
validator_digest=compiled_validator[1]
|
169
|
+
if compiled_validator is not None
|
170
|
+
else None,
|
171
|
+
)
|
172
|
+
except ValidationError as err:
|
173
|
+
if skip_invalid_testcases:
|
174
|
+
skipped += 1
|
175
|
+
continue
|
176
|
+
with err:
|
177
|
+
err.print('[warning]Invalid testcase generated.[/warning]')
|
178
|
+
err.print(
|
179
|
+
'[warning]You can use the [item]--skip[/item] flag to skip invalid testcases without halting.[/warning]'
|
180
|
+
)
|
165
181
|
|
166
182
|
@async_lru.alru_cache(maxsize=None)
|
167
183
|
async def run_solution_fn(
|
@@ -303,12 +319,14 @@ async def run_stress(
|
|
303
319
|
# Be cooperative.
|
304
320
|
time.sleep(0.001)
|
305
321
|
|
306
|
-
return StressReport(findings=findings, executed=executed)
|
322
|
+
return StressReport(findings=findings, executed=executed, skipped=skipped)
|
307
323
|
|
308
324
|
|
309
325
|
def print_stress_report(report: StressReport):
|
310
326
|
console.console.rule('Stress test report', style='status')
|
311
327
|
console.console.print(f'Executed [item]{report.executed}[/item] tests.')
|
328
|
+
if report.skipped:
|
329
|
+
console.console.print(f'Skipped [item]{report.skipped}[/item] invalid tests.')
|
312
330
|
if not report.findings:
|
313
331
|
console.console.print('No stress test findings.')
|
314
332
|
return
|
rbx/console.py
CHANGED
@@ -22,6 +22,10 @@ console = Console(theme=theme, style='info', highlight=False)
|
|
22
22
|
stderr_console = Console(theme=theme, style='info', highlight=False, stderr=True)
|
23
23
|
|
24
24
|
|
25
|
+
def new_console():
|
26
|
+
return Console(theme=theme, style='info', highlight=False)
|
27
|
+
|
28
|
+
|
25
29
|
def multiline_prompt(text: str) -> str:
|
26
30
|
console.print(f'{text} (Ctrl-D to finish):\n')
|
27
31
|
lines = sys.stdin.readlines()
|
@@ -20,12 +20,18 @@ with open(extra, 'w') as f:
|
|
20
20
|
rd = sys.stdin.read(1)
|
21
21
|
if rd == '':
|
22
22
|
break
|
23
|
-
|
24
|
-
|
23
|
+
|
24
|
+
# Write merged capture first.
|
25
25
|
if new:
|
26
26
|
sys.stderr.write(c)
|
27
27
|
sys.stderr.write(rd)
|
28
28
|
sys.stderr.flush()
|
29
29
|
|
30
|
+
# Write to program.
|
31
|
+
sys.stdout.write(rd)
|
32
|
+
sys.stdout.flush()
|
33
|
+
|
34
|
+
# Write to extra file kind of
|
35
|
+
# asynchronously.
|
30
36
|
f.write(rd)
|
31
37
|
new = rd == '\n'
|
rbx/grading/steps.py
CHANGED
@@ -14,7 +14,8 @@ import typer
|
|
14
14
|
from pydantic import BaseModel, Field
|
15
15
|
from rich.text import Text
|
16
16
|
|
17
|
-
from rbx import
|
17
|
+
from rbx import utils
|
18
|
+
from rbx.box.exception import RbxException
|
18
19
|
from rbx.config import get_bits_stdcpp, get_jngen, get_testlib
|
19
20
|
from rbx.console import console
|
20
21
|
from rbx.grading import grading_context
|
@@ -672,12 +673,16 @@ def _build_run_log(
|
|
672
673
|
return run_log
|
673
674
|
|
674
675
|
|
676
|
+
class CompilationError(RbxException):
|
677
|
+
pass
|
678
|
+
|
679
|
+
|
675
680
|
def compile(
|
676
681
|
commands: List[str],
|
677
682
|
params: SandboxParams,
|
678
683
|
sandbox: SandboxBase,
|
679
684
|
artifacts: GradingArtifacts,
|
680
|
-
)
|
685
|
+
):
|
681
686
|
sandbox.reset()
|
682
687
|
|
683
688
|
commands = _try_following_alias_for_commands(commands)
|
@@ -685,7 +690,7 @@ def compile(
|
|
685
690
|
|
686
691
|
if not commands:
|
687
692
|
# Code does not need preprocessing of any kind.
|
688
|
-
return
|
693
|
+
return
|
689
694
|
|
690
695
|
logs: List[PreprocessLog] = []
|
691
696
|
params = params.model_copy(deep=True) # Copy to allow further modification.
|
@@ -731,16 +736,17 @@ def compile(
|
|
731
736
|
artifacts.logs.preprocess = logs
|
732
737
|
|
733
738
|
if logs and logs[-1].exitcode != 0:
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
return False
|
739
|
+
with CompilationError() as err:
|
740
|
+
err.print(
|
741
|
+
'[error]FAILED[/error] Preprocessing failed with command',
|
742
|
+
utils.highlight_json_obj(logs[-1].cmd),
|
743
|
+
)
|
744
|
+
err.print(f'[error]Summary:[/error] {logs[-1].get_summary()}')
|
745
|
+
err.print(Text.from_ansi(logs[-1].log), style='default')
|
742
746
|
|
743
|
-
|
747
|
+
# testing_utils.print_directory_tree(sandbox.get_root_path())
|
748
|
+
if not _process_output_artifacts(artifacts, sandbox):
|
749
|
+
raise CompilationError()
|
744
750
|
|
745
751
|
|
746
752
|
async def run(
|
@@ -27,27 +27,31 @@ def compile(
|
|
27
27
|
):
|
28
28
|
artifacts.logs = GradingLogsHolder()
|
29
29
|
|
30
|
-
ok = True
|
31
30
|
cached_profile = profiling.Profiler('steps.compile[cached]', start=True)
|
31
|
+
err: Optional[steps.CompilationError] = None
|
32
|
+
|
32
33
|
with dependency_cache(
|
33
34
|
commands, [artifacts], params.get_cacheable_params()
|
34
35
|
) as is_cached:
|
35
36
|
if not is_cached:
|
36
37
|
with profiling.Profiler('steps.compile'):
|
37
38
|
profiling.add_to_counter('steps.compile')
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
39
|
+
try:
|
40
|
+
steps.compile(
|
41
|
+
commands=commands,
|
42
|
+
params=params,
|
43
|
+
artifacts=artifacts,
|
44
|
+
sandbox=sandbox,
|
45
|
+
)
|
46
|
+
except steps.CompilationError as e:
|
47
|
+
err = e
|
48
|
+
raise NoCacheException() from None
|
46
49
|
else:
|
47
50
|
cached_profile.stop()
|
48
51
|
profiling.add_to_counter('steps.compile[cached]')
|
49
52
|
|
50
|
-
|
53
|
+
if err is not None:
|
54
|
+
raise err
|
51
55
|
|
52
56
|
|
53
57
|
async def run(
|
@@ -1,16 +1,16 @@
|
|
1
1
|
rbx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
rbx/__version__.py,sha256=
|
2
|
+
rbx/__version__.py,sha256=lJoD4jnIqFNHWOMiBYcyL6aV6MMIlJKeIIiF88qTH-g,23
|
3
3
|
rbx/annotations.py,sha256=_TkLhgZWiUyon3bonHwUo03ls1jY8LwgcR4bVgtgnc0,3519
|
4
4
|
rbx/autoenum.py,sha256=cusv8ClXRlDVvhZ8eDrtYcL_2peXlHugAey_ht8roXk,12025
|
5
5
|
rbx/box/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
6
|
rbx/box/builder.py,sha256=umrTdVAwvsOosBDVvDZ6kq1yWg3Z2Lxp2o1zK-V7BBk,3594
|
7
7
|
rbx/box/cd.py,sha256=_XAzb3kV1NUaaRs8hc9SGDo10O1yh2_gr1EiAKzfUjI,2711
|
8
8
|
rbx/box/checkers.py,sha256=mRovZyTZdySFEaYFVc3Lc-xgEsu6F9FjVPOxDwub7aY,13226
|
9
|
-
rbx/box/cli.py,sha256=
|
10
|
-
rbx/box/code.py,sha256=
|
9
|
+
rbx/box/cli.py,sha256=NnOgA0imn17sUYwQfXpJ-34GEq8-wqEKuUen_FaKahY,30358
|
10
|
+
rbx/box/code.py,sha256=vBrXjyLht_VGZumbCLkFtIherDIR1WT_YgADwotQKS0,26121
|
11
11
|
rbx/box/compile.py,sha256=Kzn5mEQu4vb91W9vjyt0DS6cfPJzFLTUoowFj7uHLUo,2539
|
12
12
|
rbx/box/contest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
-
rbx/box/contest/build_contest_statements.py,sha256=
|
13
|
+
rbx/box/contest/build_contest_statements.py,sha256=M5KTxeuOWmUqKfvCRh_KPNUh4UdptXqqbOMHamPmEwQ,15052
|
14
14
|
rbx/box/contest/contest_package.py,sha256=d7PoUHIWVtqaRGatYOfRvZbQ-bz4MPGmv-H94Eg1yyQ,3289
|
15
15
|
rbx/box/contest/contest_utils.py,sha256=fsWHG1e65wq9zvRY3tdf32VF0nU1yzGTOBX5yjXiNk4,1102
|
16
16
|
rbx/box/contest/main.py,sha256=-aBmlwbEbGMHxWlF7ulIAeKLy2v7VVsvpb4c-kkqKK8,8564
|
@@ -20,11 +20,12 @@ rbx/box/creation.py,sha256=oTAC11XV2Pw2YAlF_d11Eo7A1fD6ItlpFMpLEzMLyFI,1331
|
|
20
20
|
rbx/box/deferred.py,sha256=II3X9e87JCOZtmspnHh-n4PFqh-FsH_oc0XJHZ9ZYVQ,691
|
21
21
|
rbx/box/download.py,sha256=tLW5gLVeLk0gHMEMwScSoHIXQPkXuPsqXzItsrsnUZY,3070
|
22
22
|
rbx/box/dump_schemas.py,sha256=HXJ195h4e017DpfoFfW3MRDukON2ZhcKtJjkRPX-dX4,649
|
23
|
-
rbx/box/environment.py,sha256=
|
23
|
+
rbx/box/environment.py,sha256=HVqNkK2QHJ4NkbmEABOqwKlzlX-GvvnGPXez9V5EMQw,14738
|
24
|
+
rbx/box/exception.py,sha256=pAZH4-yw5SaBj537rck-B0mNTlEF08hrmYnfZOE0XC8,2038
|
24
25
|
rbx/box/extensions.py,sha256=Von8kIeXvNFTkGlMRMTvL2HIHPwlkuiMswr-ydbGV1w,519
|
25
26
|
rbx/box/fields.py,sha256=Gsox7Q1M7I8I2FtKvwiAfYUC6USpwghk8fel2Q9Eyhg,2291
|
26
27
|
rbx/box/formatting.py,sha256=i3vXHpo_L_VpVPxOe4wHlai1WhlDJlfxUexS9DC0Szg,1249
|
27
|
-
rbx/box/generators.py,sha256=
|
28
|
+
rbx/box/generators.py,sha256=4JyYUnDYo3Q9FNSsJZcJZqJAI6SR_-htGfYRAncwO1Q,17900
|
28
29
|
rbx/box/git_utils.py,sha256=wuM_k5RgCz5lvoiBciSHo5XT1BdNLhXB0hBlGsc08Vs,2140
|
29
30
|
rbx/box/global_package.py,sha256=YfFGw2vxFspF2v3phBEeBCrLe1sfbANrctGqii3I2X4,2106
|
30
31
|
rbx/box/header.py,sha256=OZJD2J0fdIiYyiEAwQ3x3M8TwM1v1J9nhIjnPVz4Zy8,3029
|
@@ -32,7 +33,7 @@ rbx/box/lang.py,sha256=CSD-yxFUC3LWdGpv4IVFOLdgONc_JbsI45BEN3bjaFw,888
|
|
32
33
|
rbx/box/lazy_importing_main.py,sha256=6Z8As7qVFFT619xHH9Xt8VCH57NjC4aDxfAgkWiUwT8,116
|
33
34
|
rbx/box/limits_info.py,sha256=NTtcZTlDzemOtQQXbNbLORpl3RM9nYHc2-cGMnGYfF8,5370
|
34
35
|
rbx/box/linting.py,sha256=wRE0hKCduTBHZYBFmmis_d9AMTsDu0Q-AjByCeTnkrY,3187
|
35
|
-
rbx/box/main.py,sha256=
|
36
|
+
rbx/box/main.py,sha256=w0Nyyj8Y0eaOg4AhzI6PFITnOZePbkeDHbbGvLLmIrg,264
|
36
37
|
rbx/box/naming.py,sha256=M6aYLIge8PHhIuCX50rwGe5VRzgUL--2BVtymIqeeXs,2389
|
37
38
|
rbx/box/package.py,sha256=pzViArUFKvQ_S_EWtuigDMZrDx1ymXGqbQ7H9Ieqmik,15611
|
38
39
|
rbx/box/packaging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -63,18 +64,18 @@ rbx/box/sanitizers/issue_stack.py,sha256=nHtF8bksTIbvOlmDEy72SoXnXfQyIDBHU_3NOn-
|
|
63
64
|
rbx/box/sanitizers/warning_stack.py,sha256=L7tCWmqj2SRtgT7nWPJrKLTqbk4hb5bN9wRKfkCFMWU,2890
|
64
65
|
rbx/box/schema.py,sha256=pbmRiVf8pB6ipA8HCpQer9B9SxpbTvJuCNZswLfWe8g,20314
|
65
66
|
rbx/box/setter_config.py,sha256=vyZbsbgkjelZOblMLX5A1j4CLqPNQkrv83IZr_3-46Y,5301
|
66
|
-
rbx/box/solutions.py,sha256=
|
67
|
+
rbx/box/solutions.py,sha256=fZMQDgUS4eWRSNDuV92XE9LccnJYHWFH1a1drM5e1Uk,54735
|
67
68
|
rbx/box/state.py,sha256=MMf3DvfQji0jKEliCHct2Tpp_0epL1tvP8HbHNArQIc,166
|
68
69
|
rbx/box/statements/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
69
70
|
rbx/box/statements/build_statements.py,sha256=ZbciKblRUnRnTuuZfqU4W4EK6XhKkxuT1ByGMPjzNQU,13298
|
70
71
|
rbx/box/statements/builders.py,sha256=6849Nku1N0gBYC13wt8Eo6A3s6EfL4hh1VORwrpbEZI,13865
|
71
72
|
rbx/box/statements/expander.py,sha256=sdbMtNcJQCbXGIkFIl9h24pGr77vhFLnM31V5AfuduI,1715
|
72
73
|
rbx/box/statements/joiners.py,sha256=jItNXkAbTjFQpPMgfDMW86n3vMTbaE8sgo9I8Yf4Txg,2886
|
73
|
-
rbx/box/statements/latex.py,sha256=
|
74
|
+
rbx/box/statements/latex.py,sha256=JpPBihuwwgTRHSdULX7gBLA-V245wIy4g57p4ZM9gbQ,1627
|
74
75
|
rbx/box/statements/latex_jinja.py,sha256=UQyD3hOFsiEQdFjqMswRrPXyGCiRPgnzZPmAcvJuPyM,11671
|
75
76
|
rbx/box/statements/schema.py,sha256=zCjpSsq24V179pS7Pti82x4gIpIMogNP6u1EQxdWolE,5529
|
76
77
|
rbx/box/stats.py,sha256=rUAnmp7kTgUvIQ56NLpQaIQkazB37MVcUos5en3xUQw,3258
|
77
|
-
rbx/box/stresses.py,sha256=
|
78
|
+
rbx/box/stresses.py,sha256=H8cNn9MJejZ9PZK-o5WxzaDQlc53_BKO-Fn_TPg2s5E,12994
|
78
79
|
rbx/box/stressing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
79
80
|
rbx/box/stressing/finder_parser.py,sha256=PnONJD2yun5X5EmHqkaz-rh3DHhn_BkTPHZrIXRKZbw,11898
|
80
81
|
rbx/box/stressing/generator_parser.py,sha256=iIWFVPhbdnBZD3zGGDooZ6BWuQ0lRbehqpzc7i_nBeo,7429
|
@@ -124,7 +125,7 @@ rbx/box/ui/widgets/two_sided_test_output_box.py,sha256=L-ORiDwd6CP5DFpavrKGBaX0Z
|
|
124
125
|
rbx/box/unit.py,sha256=3hqhFBoQQSH76EcCVa87XGVII9JRaz3r_feKldlITsk,7876
|
125
126
|
rbx/box/validators.py,sha256=nugrsZ6NMJa1SCH-VybDTDDf_hLP3tJehksessNv75s,10445
|
126
127
|
rbx/config.py,sha256=Tj0NHSf13fXxbNpif5C4qnaL1k3S-G87OnzuykEAcNQ,8463
|
127
|
-
rbx/console.py,sha256=
|
128
|
+
rbx/console.py,sha256=RMNkO6vxcRypLvsQYtNpomsyA7n8f_DjH80WNq8e10c,1074
|
128
129
|
rbx/grading/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
129
130
|
rbx/grading/caching.py,sha256=hasSs10PV4J_3e6b3xc7BDCnUNzT9uwrDZcZ_h_hL1I,16951
|
130
131
|
rbx/grading/debug_context.py,sha256=kuAXEI8yRG8xfhS9WKKIRh9X0e5JUD8zvl_cpczJTC8,699
|
@@ -136,18 +137,17 @@ rbx/grading/judge/program.py,sha256=VJ-ItHGsumAvR7YWYtnmAFairfAIu_ASHfyhu7bqvRw,
|
|
136
137
|
rbx/grading/judge/sandbox.py,sha256=e9Nstf9EoFGE0OBQgqcz5BD5hYDegIeGP5dWVZSA29Q,21342
|
137
138
|
rbx/grading/judge/sandboxes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
138
139
|
rbx/grading/judge/sandboxes/stupid_sandbox.py,sha256=0Pw-Jvh2A7Jbm5mpx3r4mojP9HgFkDhSREWFuS3ixKs,11765
|
139
|
-
rbx/grading/judge/sandboxes/tee.py,sha256=
|
140
|
+
rbx/grading/judge/sandboxes/tee.py,sha256=lNNjSjOpOx8hta1lAo1beroR5XQOwKbRvAn_QXMLuyM,804
|
140
141
|
rbx/grading/judge/storage.py,sha256=8o3pz0Ansanc5t23XGtshJHCD_q4dIR_XorpeVEvg1g,15621
|
141
142
|
rbx/grading/limits.py,sha256=zCyRTEtUQFd1RKL_fFKl3qSiRSIDCalBaSLlt1yhi0Y,896
|
142
143
|
rbx/grading/profiling.py,sha256=OEdtoAzjYjLfi-QI5Ke7tLZzJeqvGpMB2utQBNuH3E4,3369
|
143
|
-
rbx/grading/steps.py,sha256=
|
144
|
-
rbx/grading/steps_with_caching.py,sha256=
|
144
|
+
rbx/grading/steps.py,sha256=Cy0IvuYLxYCBG8pdd55H_v_8mTq0NqeCiIzySZg0gpg,26841
|
145
|
+
rbx/grading/steps_with_caching.py,sha256=zUA_MIxLS0g3VwPMd6cH83TZSDQmt5GlQnxI4zrqHc4,4964
|
145
146
|
rbx/resources/checkers/boilerplate.cpp,sha256=vj1Qjy59JKEzb4ZpaX_MkL1FaZn_tTLZXjrIkP0nGfc,363
|
146
147
|
rbx/resources/checkers/noop.cpp,sha256=aZI6EfZEWq2opbb-kysvl0UeUoYGLU682LccP7cfBG8,214
|
147
148
|
rbx/resources/default_config.json,sha256=8GZVHns4nci0-e5ALk9C1lfO6TO9W2ZlmZtxHkL6ibA,949
|
148
149
|
rbx/resources/default_setter_config.mac.yml,sha256=UWRvdsFp-6I9dU1b1q9hYNAday9TXvyVd_5gquIkcFQ,1438
|
149
150
|
rbx/resources/default_setter_config.yml,sha256=cYTiQqxadRyOmgI9aS6LlG3Cn-azKhOmaZlpZBXvBow,1409
|
150
|
-
rbx/resources/envs/default.rbx.yml,sha256=quSPG5Xs9KroYLATNLPNtORLGRWtrLLt2Fx81T1enAM,1692
|
151
151
|
rbx/resources/packagers/boca/checker.sh,sha256=kesoIYeCttAtuQBq-7HvfXK8cAFTJhFbqHm9rNd_udg,1272
|
152
152
|
rbx/resources/packagers/boca/compare.sh,sha256=a6AmQqwrIq616DHjp_S2l95wO7UiMVy0LQ9EajZKDDk,1201
|
153
153
|
rbx/resources/packagers/boca/compile/c,sha256=DZ9PWjgDTuauwY4my8Y8WXz0gZCBd4I7n0k0QxBaAUs,4466
|
@@ -200,8 +200,8 @@ rbx/resources/presets/default/contest/statement/contest.rbx.tex,sha256=Jx6op_WdV
|
|
200
200
|
rbx/resources/presets/default/contest/statement/info.rbx.tex,sha256=Wz8Tbmi2lPWMgDbJsJolUi1xaQMwSnHmpZ3JwAy_Tb0,998
|
201
201
|
rbx/resources/presets/default/contest/statement/instructions.tex,sha256=JG_eR13ukZgEahrrmrbg40H8cUzpoUE8QLocihN-fZ8,2414
|
202
202
|
rbx/resources/presets/default/contest/statement/logo.png,sha256=RLNYmZoc-BR6AZKkmr4UEg3h01YeFzvy604jMAQC7aA,414485
|
203
|
-
rbx/resources/presets/default/env.rbx.yml,sha256=
|
204
|
-
rbx/resources/presets/default/preset.rbx.yml,sha256=
|
203
|
+
rbx/resources/presets/default/env.rbx.yml,sha256=9MaKkSc289LrwATbMgIEFpuUayrJwdFBSw4rWY1TS0c,2098
|
204
|
+
rbx/resources/presets/default/preset.rbx.yml,sha256=19kR3AmBq4nyyT9sxHPP2Yq8G_pep2KioJxCOc_C7WQ,520
|
205
205
|
rbx/resources/presets/default/problem/.gitignore,sha256=1rt95y9Q7ZHIQn28JyZQUdD5zkpRosjAl9ZqoQmX2cE,149
|
206
206
|
rbx/resources/presets/default/problem/gens/gen.cpp,sha256=rn6sGRjZ1sFE1Rq02r6488iquY9xTrutcvLv4d1sohA,178
|
207
207
|
rbx/resources/presets/default/problem/manual_tests/samples/000.in,sha256=w66OEtCJGqjUNj8cJrqgImgGVm8W_OlIUtF255ds-ow,4
|
@@ -223,8 +223,8 @@ rbx/resources/templates/rbx.h,sha256=0AZds9R0PmuPgnlTENb33Y81LW0LlnmOJFaoN8oG3Yo
|
|
223
223
|
rbx/resources/templates/template.cpp,sha256=xXWpWo7fa7HfmPNqkmHcmv3i46Wm0ZL-gPmkRfGvLn4,317
|
224
224
|
rbx/testing_utils.py,sha256=vNNdaytowJfuopszVHeFzVtHWlPfipPW4zpqCOvdZKU,2908
|
225
225
|
rbx/utils.py,sha256=zOXjEkEN9tlzLliWpssNTSmcvdgveUWDdo427qI3dhM,12225
|
226
|
-
rbx_cp-0.18.
|
227
|
-
rbx_cp-0.18.
|
228
|
-
rbx_cp-0.18.
|
229
|
-
rbx_cp-0.18.
|
230
|
-
rbx_cp-0.18.
|
226
|
+
rbx_cp-0.18.5.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
|
227
|
+
rbx_cp-0.18.5.dist-info/METADATA,sha256=KS5gRuxRjzcDVX6LdOG4MSBOng7lHr0o4QyzeZoBfc0,4845
|
228
|
+
rbx_cp-0.18.5.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
229
|
+
rbx_cp-0.18.5.dist-info/entry_points.txt,sha256=Gw2_BZ5Jon61biaH_ETbAQGXy8fR5On9gw2U4A1erpo,40
|
230
|
+
rbx_cp-0.18.5.dist-info/RECORD,,
|
@@ -1,67 +0,0 @@
|
|
1
|
-
---
|
2
|
-
sandbox: "stupid"
|
3
|
-
defaultCompilation:
|
4
|
-
sandbox:
|
5
|
-
maxProcesses: 1000
|
6
|
-
timeLimit: 50000 # 50 seconds
|
7
|
-
wallTimeLimit: 50000 # 50 seconds
|
8
|
-
memoryLimit: 1024 # 1gb
|
9
|
-
defaultExecution:
|
10
|
-
sandbox:
|
11
|
-
# Useful for checkers, validators, etc.
|
12
|
-
timeLimit: 50000 # 50 seconds
|
13
|
-
wallTimeLimit: 50000 # 50 seconds
|
14
|
-
memoryLimit: 1024 # 1gb
|
15
|
-
languages:
|
16
|
-
- name: "cpp"
|
17
|
-
readableName: "C++20"
|
18
|
-
extension: "cpp"
|
19
|
-
compilation:
|
20
|
-
commands: ["g++ -std=c++20 -O2 -o {executable} {compilable}"]
|
21
|
-
execution:
|
22
|
-
command: "./{executable}"
|
23
|
-
fileMapping:
|
24
|
-
compilable: "compilable.cpp"
|
25
|
-
extensions:
|
26
|
-
boca:
|
27
|
-
bocaLanguage: "cc"
|
28
|
-
- name: "c"
|
29
|
-
readableName: "C"
|
30
|
-
extension: "c"
|
31
|
-
compilation:
|
32
|
-
commands: ["gcc -std=gnu11 -O2 -lm -o {executable} {compilable}"]
|
33
|
-
execution:
|
34
|
-
command: "./{executable}"
|
35
|
-
fileMapping:
|
36
|
-
compilable: "compilable.c"
|
37
|
-
- name: "py"
|
38
|
-
readableName: "Python3"
|
39
|
-
extension: "py"
|
40
|
-
execution:
|
41
|
-
command: "python3 {executable}"
|
42
|
-
fileMapping:
|
43
|
-
executable: "executable.py"
|
44
|
-
extensions:
|
45
|
-
boca:
|
46
|
-
bocaLanguage: "py3"
|
47
|
-
- name: "java"
|
48
|
-
readableName: "Java"
|
49
|
-
extension: "java"
|
50
|
-
compilation:
|
51
|
-
commands:
|
52
|
-
- "javac -Xlint -encoding UTF-8 {compilable}"
|
53
|
-
- "jar cvf {executable} @glob:*.class"
|
54
|
-
execution:
|
55
|
-
command:
|
56
|
-
"java -Xss100m -Xmx{{memory}}m -Xms{{initialMemory}}m -cp {executable}
|
57
|
-
Main"
|
58
|
-
fileMapping:
|
59
|
-
compilable: "Main.java"
|
60
|
-
executable: "Main.jar"
|
61
|
-
extensions:
|
62
|
-
boca:
|
63
|
-
languages: ["c", "cc", "java", "py3"]
|
64
|
-
flags:
|
65
|
-
c: "-O2 -lm -static"
|
66
|
-
cc: "-std=c++20 -O2 -lm -static"
|
67
|
-
preferContestLetter: true
|
File without changes
|
File without changes
|
File without changes
|