rbx.cp 0.5.52__py3-none-any.whl → 0.5.54__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/checkers.py +13 -3
- rbx/box/dump_schemas.py +18 -0
- rbx/box/packaging/polygon/upload.py +20 -2
- rbx/grading/processing_context.py +43 -4
- rbx/grading/steps.py +58 -14
- rbx/utils.py +16 -6
- {rbx_cp-0.5.52.dist-info → rbx_cp-0.5.54.dist-info}/METADATA +2 -1
- {rbx_cp-0.5.52.dist-info → rbx_cp-0.5.54.dist-info}/RECORD +11 -10
- {rbx_cp-0.5.52.dist-info → rbx_cp-0.5.54.dist-info}/LICENSE +0 -0
- {rbx_cp-0.5.52.dist-info → rbx_cp-0.5.54.dist-info}/WHEEL +0 -0
- {rbx_cp-0.5.52.dist-info → rbx_cp-0.5.54.dist-info}/entry_points.txt +0 -0
rbx/box/checkers.py
CHANGED
@@ -226,6 +226,10 @@ def _check_sanitizer_warnings(run_log: Optional[RunLog]) -> bool:
|
|
226
226
|
return run_log.warnings
|
227
227
|
|
228
228
|
|
229
|
+
def _is_testlib_eof(stderr: str) -> bool:
|
230
|
+
return 'wrong output format Unexpected end of file' in stderr
|
231
|
+
|
232
|
+
|
229
233
|
async def check(
|
230
234
|
checker_digest: str,
|
231
235
|
run_log: Optional[RunLog],
|
@@ -283,15 +287,21 @@ async def check_communication(
|
|
283
287
|
# interactor exited before it. Thus, check the interactor, as it might have
|
284
288
|
# returned a checker verdict.
|
285
289
|
#
|
286
|
-
# Also,
|
287
|
-
#
|
290
|
+
# Also, treat the case where the solution has a non-zero exit code similarly.
|
291
|
+
# This is aligned with what Polygon/Codeforces does: for some languages, we don't
|
292
|
+
# get a SIGPIPE. Instead, we get a non-zero exit code which we can't distinguish
|
293
|
+
# from a normal RTE. Thus, we decide that we should prioritize the interactor verdict
|
294
|
+
# over the solution's exit code in these cases.
|
288
295
|
if (
|
289
296
|
interactor_run_log is not None
|
290
297
|
and run_log is not None
|
291
298
|
and (
|
292
299
|
run_log.exitcode == -signal.SIGPIPE
|
293
300
|
or run_log.exitstatus == SandboxBase.EXIT_TERMINATED
|
294
|
-
or
|
301
|
+
or (
|
302
|
+
run_log.exitstatus == SandboxBase.EXIT_NONZERO_RETURN
|
303
|
+
and not _is_testlib_eof(interactor_stderr.read_text())
|
304
|
+
)
|
295
305
|
)
|
296
306
|
):
|
297
307
|
result = _check_interactor()
|
rbx/box/dump_schemas.py
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
import pathlib
|
2
|
+
|
3
|
+
import mkdocs_gen_files
|
4
|
+
|
5
|
+
from rbx.box.contest.schema import Contest
|
6
|
+
from rbx.box.environment import Environment
|
7
|
+
from rbx.box.package import Package
|
8
|
+
from rbx.box.presets.lock_schema import PresetLock
|
9
|
+
from rbx.box.presets.schema import Preset
|
10
|
+
from rbx.box.statements.schema import Statement
|
11
|
+
from rbx.utils import dump_schema_str
|
12
|
+
|
13
|
+
models = [Package, Environment, Contest, Preset, PresetLock, Statement]
|
14
|
+
|
15
|
+
for model in models:
|
16
|
+
path = pathlib.Path('schemas') / f'{model.__name__}.json'
|
17
|
+
with mkdocs_gen_files.open(str(path), 'w') as f:
|
18
|
+
f.write(dump_schema_str(model))
|
@@ -250,6 +250,24 @@ def _get_statement_blocks(statement: Statement) -> StatementBlocks:
|
|
250
250
|
)
|
251
251
|
|
252
252
|
|
253
|
+
def _get_explanations(explanations: Dict[int, str]) -> str:
|
254
|
+
entries = []
|
255
|
+
for i in sorted(explanations):
|
256
|
+
explanation = explanations[i]
|
257
|
+
entries.append(f'\\textbf{{Explanation for example {i + 1}}}\n\n{explanation}')
|
258
|
+
return '\n\n'.join(entries)
|
259
|
+
|
260
|
+
|
261
|
+
def _get_notes_with_explanations(blocks: StatementBlocks) -> Optional[str]:
|
262
|
+
notes = blocks.blocks.get('notes')
|
263
|
+
explanations = blocks.explanations
|
264
|
+
if notes is None and not explanations:
|
265
|
+
return None
|
266
|
+
if notes is None:
|
267
|
+
return _get_explanations(blocks.explanations)
|
268
|
+
return notes + '\n\n' + _get_explanations(blocks.explanations)
|
269
|
+
|
270
|
+
|
253
271
|
def _upload_statement_resources(problem: api.Problem, statement: Statement):
|
254
272
|
assets = get_relative_assets(statement.path, statement.assets)
|
255
273
|
for asset, relative_asset in assets:
|
@@ -293,7 +311,7 @@ def _upload_statement(problem: api.Problem):
|
|
293
311
|
input=blocks.blocks.get('input'),
|
294
312
|
output=blocks.blocks.get('output'),
|
295
313
|
interaction=blocks.blocks.get('interaction'),
|
296
|
-
notes=blocks
|
314
|
+
notes=_get_notes_with_explanations(blocks),
|
297
315
|
)
|
298
316
|
problem.save_statement(
|
299
317
|
lang=code_to_langs([language])[0], problem_statement=polygon_statement
|
@@ -311,8 +329,8 @@ async def upload_problem(name: str):
|
|
311
329
|
name = _normalize_problem_name(name)
|
312
330
|
problem = _find_or_create_problem(name)
|
313
331
|
_update_problem_info(problem)
|
314
|
-
_update_checker(problem)
|
315
332
|
_update_rbx_header(problem)
|
333
|
+
_update_checker(problem)
|
316
334
|
|
317
335
|
if (
|
318
336
|
pkg.type == TaskType.COMMUNICATION
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import asyncio
|
1
2
|
import contextlib
|
2
3
|
import os
|
3
4
|
import signal
|
@@ -5,22 +6,26 @@ import threading
|
|
5
6
|
from typing import Optional, Set
|
6
7
|
|
7
8
|
_processing_context_pids: Optional[Set[int]] = None
|
9
|
+
_terminate_all_on_error = False
|
8
10
|
_lock = threading.Lock()
|
9
11
|
|
10
12
|
# Creating a processing context is not thread-safe, but adding to it is.
|
11
13
|
|
12
14
|
|
13
15
|
@contextlib.contextmanager
|
14
|
-
def new_processing_context():
|
15
|
-
global _processing_context_pids
|
16
|
+
def new_processing_context(terminate_all_on_error: bool = False):
|
17
|
+
global _processing_context_pids, _terminate_all_on_error
|
16
18
|
with _lock:
|
17
19
|
old_processing_context_pids = _processing_context_pids
|
20
|
+
_old_terminate_all_on_error = _terminate_all_on_error
|
18
21
|
_processing_context_pids = set()
|
22
|
+
_terminate_all_on_error = terminate_all_on_error
|
19
23
|
try:
|
20
24
|
yield
|
21
25
|
finally:
|
22
26
|
with _lock:
|
23
27
|
_processing_context_pids = old_processing_context_pids
|
28
|
+
_terminate_all_on_error = _old_terminate_all_on_error
|
24
29
|
|
25
30
|
|
26
31
|
def get_processing_context() -> Set[int]:
|
@@ -36,7 +41,8 @@ def add_to_processing_context(pid: int):
|
|
36
41
|
_processing_context_pids.add(pid)
|
37
42
|
|
38
43
|
|
39
|
-
def terminate_all_processes_in_context():
|
44
|
+
def terminate_all_processes_in_context(clear: bool = True):
|
45
|
+
global _processing_context_pids
|
40
46
|
with _lock:
|
41
47
|
if _processing_context_pids is None:
|
42
48
|
return
|
@@ -45,4 +51,37 @@ def terminate_all_processes_in_context():
|
|
45
51
|
os.kill(pid, signal.SIGTERM)
|
46
52
|
except OSError:
|
47
53
|
pass
|
48
|
-
|
54
|
+
if clear:
|
55
|
+
_processing_context_pids.clear()
|
56
|
+
|
57
|
+
|
58
|
+
async def wait_all_processes_in_context(wait_for: int):
|
59
|
+
global _processing_context_pids, _terminate_all_on_error
|
60
|
+
wait_pids = set()
|
61
|
+
while len(get_processing_context()) < wait_for:
|
62
|
+
await asyncio.sleep(0.01)
|
63
|
+
|
64
|
+
with _lock:
|
65
|
+
if _processing_context_pids is None:
|
66
|
+
return
|
67
|
+
wait_pids.update(_processing_context_pids)
|
68
|
+
|
69
|
+
wait_lock = threading.Lock()
|
70
|
+
finished_pids = []
|
71
|
+
|
72
|
+
def process(pid: int, returncode: int):
|
73
|
+
with wait_lock:
|
74
|
+
finished_pids.append(pid)
|
75
|
+
if returncode != 0 and _terminate_all_on_error:
|
76
|
+
terminate_all_processes_in_context()
|
77
|
+
|
78
|
+
def wait_all_processes():
|
79
|
+
while len(finished_pids) < len(wait_pids):
|
80
|
+
try:
|
81
|
+
pid, status = os.wait()
|
82
|
+
except ChildProcessError:
|
83
|
+
return
|
84
|
+
if pid in wait_pids:
|
85
|
+
process(pid, os.waitstatus_to_exitcode(status))
|
86
|
+
|
87
|
+
await asyncio.to_thread(wait_all_processes)
|
rbx/grading/steps.py
CHANGED
@@ -193,6 +193,11 @@ class RunLogMetadata(BaseModel):
|
|
193
193
|
retryIndex: Optional[int] = None
|
194
194
|
|
195
195
|
|
196
|
+
class ProcessingContextLog(BaseModel):
|
197
|
+
pid: int = -1
|
198
|
+
exitindex: int = -1
|
199
|
+
|
200
|
+
|
196
201
|
class RunLog(BaseModel):
|
197
202
|
exitcode: int = 0
|
198
203
|
exitstatus: str = SandboxBase.EXIT_SANDBOX_ERROR
|
@@ -330,14 +335,29 @@ def _expand_part(part: str, sandbox: SandboxBase) -> List[str]:
|
|
330
335
|
return [part]
|
331
336
|
|
332
337
|
|
338
|
+
def _get_java_memory_limits(sandbox: SandboxBase) -> Tuple[int, int]:
|
339
|
+
max_memory = sandbox.params.address_space
|
340
|
+
if max_memory is None:
|
341
|
+
max_memory = 2048
|
342
|
+
return max_memory, min(512, int(max_memory * 0.9))
|
343
|
+
|
344
|
+
|
333
345
|
def _split_and_expand(command: str, sandbox: SandboxBase) -> List[str]:
|
334
346
|
res = []
|
335
|
-
|
347
|
+
max_mem, init_mem = _get_java_memory_limits(sandbox)
|
348
|
+
parts = shlex.split(command.format(memory=max_mem, initialMemory=init_mem))
|
336
349
|
for part in parts:
|
337
350
|
res.extend(_expand_part(part, sandbox))
|
338
351
|
return res
|
339
352
|
|
340
353
|
|
354
|
+
def get_exe_from_command(command: str) -> str:
|
355
|
+
cmds = shlex.split(command)
|
356
|
+
if not cmds:
|
357
|
+
return command
|
358
|
+
return cmds[0]
|
359
|
+
|
360
|
+
|
341
361
|
def _is_c_command(exe_command: str) -> bool:
|
342
362
|
return 'gcc' in exe_command or 'clang' in exe_command
|
343
363
|
|
@@ -351,15 +371,26 @@ def is_cxx_command(exe_command: str) -> bool:
|
|
351
371
|
|
352
372
|
|
353
373
|
def is_cxx_sanitizer_command(command: str) -> bool:
|
354
|
-
|
355
|
-
if not
|
374
|
+
exe = get_exe_from_command(command)
|
375
|
+
if not exe:
|
356
376
|
return False
|
357
|
-
exe = cmds[0]
|
358
377
|
if not is_cxx_command(exe):
|
359
378
|
return False
|
360
379
|
return 'fsanitize' in command
|
361
380
|
|
362
381
|
|
382
|
+
def is_java_command(exe_command: str) -> bool:
|
383
|
+
return 'javac' in exe_command or 'java' in exe_command
|
384
|
+
|
385
|
+
|
386
|
+
def is_kotlin_command(exe_command: str) -> bool:
|
387
|
+
return 'kotlinc' in exe_command or 'kotlin' in exe_command
|
388
|
+
|
389
|
+
|
390
|
+
def is_java_like_command(exe_command: str) -> bool:
|
391
|
+
return is_java_command(exe_command) or is_kotlin_command(exe_command)
|
392
|
+
|
393
|
+
|
363
394
|
@functools.cache
|
364
395
|
def _complain_about_clang() -> None:
|
365
396
|
console.print(
|
@@ -539,6 +570,10 @@ def compile(
|
|
539
570
|
stderr_file = pathlib.PosixPath(f'compile-{i}.stderr')
|
540
571
|
sandbox.params.set_stdall(stdout=stdout_file, stderr=stderr_file)
|
541
572
|
|
573
|
+
# Remove memory constraints for Java.
|
574
|
+
if is_java_like_command(get_exe_from_command(command)):
|
575
|
+
sandbox.params.address_space = None
|
576
|
+
|
542
577
|
if bits_artifact is not None and _is_cpp_command(cmd[0]):
|
543
578
|
# Include from sandbox directory to import bits/stdc++.h.
|
544
579
|
cmd.append('-I.')
|
@@ -604,6 +639,10 @@ async def run(
|
|
604
639
|
cmd = _split_and_expand(command, sandbox)
|
605
640
|
sandbox.set_params(params)
|
606
641
|
|
642
|
+
# Remove memory constraints for Java.
|
643
|
+
if is_java_like_command(get_exe_from_command(command)):
|
644
|
+
sandbox.params.address_space = None
|
645
|
+
|
607
646
|
if not await asyncio.to_thread(sandbox.execute_without_std, cmd):
|
608
647
|
console.print(
|
609
648
|
'[error]Sandbox crashed while processing command:[/error]',
|
@@ -614,7 +653,7 @@ async def run(
|
|
614
653
|
return None
|
615
654
|
|
616
655
|
if sandbox.get_exit_code() != 0 and kill_on_processing_context_exit:
|
617
|
-
processing_context.terminate_all_processes_in_context()
|
656
|
+
processing_context.terminate_all_processes_in_context(clear=False)
|
618
657
|
|
619
658
|
if not _process_output_artifacts(artifacts, sandbox):
|
620
659
|
return None
|
@@ -657,22 +696,27 @@ async def run_coordinated(
|
|
657
696
|
interactor: CoordinatedRunParams,
|
658
697
|
solution: CoordinatedRunParams,
|
659
698
|
) -> Tuple[Optional[RunLog], Optional[RunLog]]:
|
660
|
-
with processing_context.new_processing_context():
|
699
|
+
with processing_context.new_processing_context(terminate_all_on_error=True):
|
700
|
+
# Schedule both runs to execute immediately.
|
661
701
|
runs = tuple(
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
702
|
+
asyncio.create_task(
|
703
|
+
run(
|
704
|
+
params.command,
|
705
|
+
params.params,
|
706
|
+
params.sandbox,
|
707
|
+
params.artifacts,
|
708
|
+
params.metadata,
|
709
|
+
kill_on_processing_context_exit=True,
|
710
|
+
)
|
669
711
|
)
|
670
712
|
for params in [interactor, solution]
|
671
713
|
)
|
672
|
-
|
714
|
+
await processing_context.wait_all_processes_in_context(wait_for=2)
|
715
|
+
logs = typing.cast(
|
673
716
|
Tuple[Optional[RunLog], Optional[RunLog]],
|
674
717
|
tuple(await asyncio.gather(*runs)),
|
675
718
|
)
|
719
|
+
return logs
|
676
720
|
|
677
721
|
|
678
722
|
def _normalize_checked_words(s: str) -> Tuple[str, ...]:
|
rbx/utils.py
CHANGED
@@ -57,21 +57,32 @@ def get_app_path() -> pathlib.Path:
|
|
57
57
|
return pathlib.Path(app_dir)
|
58
58
|
|
59
59
|
|
60
|
-
def
|
61
|
-
|
60
|
+
def dump_schema_str(model: Type[BaseModel]) -> str:
|
61
|
+
return json.dumps(model.model_json_schema(), indent=4)
|
62
|
+
|
63
|
+
|
64
|
+
def dump_schema(model: Type[BaseModel], path: pathlib.Path):
|
62
65
|
path.parent.mkdir(parents=True, exist_ok=True)
|
63
|
-
schema =
|
66
|
+
schema = dump_schema_str(model)
|
64
67
|
path.write_text(schema)
|
68
|
+
|
69
|
+
|
70
|
+
def ensure_schema(model: Type[BaseModel]) -> pathlib.Path:
|
71
|
+
path = get_app_path() / 'schemas' / f'{model.__name__}.json'
|
72
|
+
dump_schema(model, path)
|
65
73
|
return path.resolve()
|
66
74
|
|
67
75
|
|
68
76
|
def model_json(model: BaseModel) -> str:
|
69
|
-
ensure_schema(model.__class__)
|
70
77
|
return model.model_dump_json(indent=4, exclude_unset=True, exclude_none=True)
|
71
78
|
|
72
79
|
|
80
|
+
def uploaded_schema_path(model: Type[BaseModel]) -> str:
|
81
|
+
return f'https://rsalesc.github.io/rbx/schemas/{model.__name__}.json'
|
82
|
+
|
83
|
+
|
73
84
|
def model_to_yaml(model: BaseModel) -> str:
|
74
|
-
path =
|
85
|
+
path = uploaded_schema_path(model.__class__)
|
75
86
|
return f'# yaml-language-server: $schema={path}\n\n' + yaml.dump(
|
76
87
|
model.model_dump(mode='json', exclude_unset=True, exclude_none=True),
|
77
88
|
sort_keys=False,
|
@@ -80,7 +91,6 @@ def model_to_yaml(model: BaseModel) -> str:
|
|
80
91
|
|
81
92
|
|
82
93
|
def model_from_yaml(model: Type[T], s: str) -> T:
|
83
|
-
ensure_schema(model)
|
84
94
|
return model(**yaml.safe_load(s))
|
85
95
|
|
86
96
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: rbx.cp
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.54
|
4
4
|
Summary:
|
5
5
|
Author: Roberto Sales
|
6
6
|
Requires-Python: >=3.9,<4.0
|
@@ -21,6 +21,7 @@ Requires-Dist: latexbuild (>=0.2.2,<0.3.0)
|
|
21
21
|
Requires-Dist: mechanize (>=0.4.10,<0.5.0)
|
22
22
|
Requires-Dist: more-itertools (>=10.5.0,<11.0.0)
|
23
23
|
Requires-Dist: nest-asyncio (>=1.6.0,<2.0.0)
|
24
|
+
Requires-Dist: psutil (>=7.0.0,<8.0.0)
|
24
25
|
Requires-Dist: pydantic (==2.8.2)
|
25
26
|
Requires-Dist: pydantic-xml[lxml] (>=2.11.0,<3.0.0)
|
26
27
|
Requires-Dist: pyte (>=0.8.2,<0.9.0)
|
@@ -4,7 +4,7 @@ rbx/autoenum.py,sha256=cusv8ClXRlDVvhZ8eDrtYcL_2peXlHugAey_ht8roXk,12025
|
|
4
4
|
rbx/box/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
rbx/box/builder.py,sha256=MDm2qqmhedAbhn3rWP6cDwbBsGhV6sz_2sg1zLkPDw0,3613
|
6
6
|
rbx/box/cd.py,sha256=9a_SOnzoJBXxxffp4Wbf3UKXIwKuN3Hvj7K6SocALwE,1194
|
7
|
-
rbx/box/checkers.py,sha256=
|
7
|
+
rbx/box/checkers.py,sha256=5Pj6a8y5YCVY3KvV7B_WLo30uDmIhnEgxE6_KKZqzvY,11923
|
8
8
|
rbx/box/cli.py,sha256=GPoGDgmaV1lXL9puXhUbZUIEU0lOMvdH1kD4TGCXkCo,26738
|
9
9
|
rbx/box/code.py,sha256=hmA2EoGOr13AYzicHNsnU2SkFW-44l7kOdu8QRwTJlI,18848
|
10
10
|
rbx/box/compile.py,sha256=OJLthDQ921w9vyoE6Gk1Df54i5RwtRJ2YG-8XEfefcs,2489
|
@@ -19,6 +19,7 @@ rbx/box/contest/statements.py,sha256=Or8gFb6P_oViGdeiVgepXsvd_W84mA7LRaVmiAXWWSg
|
|
19
19
|
rbx/box/creation.py,sha256=Evz7K6JoarD-4JJQsZsgoxU9FgCF9Z7-LfuroG4Cqls,2444
|
20
20
|
rbx/box/deferred.py,sha256=II3X9e87JCOZtmspnHh-n4PFqh-FsH_oc0XJHZ9ZYVQ,691
|
21
21
|
rbx/box/download.py,sha256=DxAiAk4lDYWEz1C9UTvZzHTq6hgm4fxGezApm2IkCTM,2601
|
22
|
+
rbx/box/dump_schemas.py,sha256=3j5t47_vJmXj0BCczxDX6ByOcsfolGEDNCBXlPpk86w,593
|
22
23
|
rbx/box/environment.py,sha256=fZnNQCdpG3xzKne0FY7gkuaopy6fdYvVFAXeHmC1ZOo,11498
|
23
24
|
rbx/box/extensions.py,sha256=Von8kIeXvNFTkGlMRMTvL2HIHPwlkuiMswr-ydbGV1w,519
|
24
25
|
rbx/box/formatting.py,sha256=3phFRHzqVXj4Ok1yDhCq6Clbw6KlqwJNpMhs--oTWFI,405
|
@@ -39,7 +40,7 @@ rbx/box/packaging/packager.py,sha256=da2haC1L9cG30myneMrRIAdGubtid0Xmy38BHKPCZZ4
|
|
39
40
|
rbx/box/packaging/polygon/packager.py,sha256=GfZ-Dc2TDKkb3QNnfOy8yxldho2L401Ao06oWg--Gcs,11714
|
40
41
|
rbx/box/packaging/polygon/polygon_api.py,sha256=mPKEqiwANJ1nr-JhOgzGMaDhnbljsAgzzPHW6kkf7R4,41016
|
41
42
|
rbx/box/packaging/polygon/test.py,sha256=bgEju5PwudgyfwxXJagm8fM6CJVlWM6l_-2q1V-oKaQ,3069
|
42
|
-
rbx/box/packaging/polygon/upload.py,sha256=
|
43
|
+
rbx/box/packaging/polygon/upload.py,sha256=woaqf2vcWmvCyBXtAesBUOaMcVUns3hkuzXqzcgAjyo,11826
|
43
44
|
rbx/box/packaging/polygon/xml_schema.py,sha256=ZgcLyvxggMUccbTNdzflue5G-FTN2_ZmOGGF7FD0Y5A,2851
|
44
45
|
rbx/box/presets/__init__.py,sha256=BwmjBw8wF8yiZFjCYBjMk-HGMZaRwhlfszbWAj3B0vw,18689
|
45
46
|
rbx/box/presets/fetch.py,sha256=F-BCOlvEBEyDqtOhiDuGPn4EDtA4Bwm-fqHJ7zZGlW8,1975
|
@@ -97,8 +98,8 @@ rbx/grading/judge/sandboxes/timeit.py,sha256=jQonQhaVI93diYQsJYXwS77IO1t5iZVKJtm
|
|
97
98
|
rbx/grading/judge/storage.py,sha256=3vv0HvtenbUZBH33CB5ZzX66ppL22G6munBaAA9BgwQ,9418
|
98
99
|
rbx/grading/judge/test.py,sha256=ll0Iw7zyOpGdKPD_PGH7dvUkb4stQLu-ikbQnqJvuAc,944
|
99
100
|
rbx/grading/judge/testiso.py,sha256=v14DtkWiZFJ9AKMzrb0_vZKPWDt8jz8iIw1Z2O-Advk,1397
|
100
|
-
rbx/grading/processing_context.py,sha256=
|
101
|
-
rbx/grading/steps.py,sha256=
|
101
|
+
rbx/grading/processing_context.py,sha256=EOxsRTKB_JEgcKNodDWPIYaBramANU-6QnDkqdF8tEk,2556
|
102
|
+
rbx/grading/steps.py,sha256=VscFO-fnKtSspdB1Cnu18l8feaREbsh0MNkexJ6obOc,27163
|
102
103
|
rbx/grading/steps_with_caching.py,sha256=nez2YwgauGXKRjhk6tQxTDGQ-HEk7KfZOeAPhsxi5iw,3150
|
103
104
|
rbx/grading/steps_with_caching_run_test.py,sha256=mh4DRInrOGhnQFWD1SlcjDm_HvcSDFTDMSpAlG-Q5SI,15570
|
104
105
|
rbx/grading_utils.py,sha256=lL2KtSkOsMElqrRoApQTbFcqVOeHVWUDTMCa3IsLpC4,4484
|
@@ -191,9 +192,9 @@ rbx/test.py,sha256=tZyTrXDK8MLR-1TyCRxiOiNz-PhlXVpshfUGphakkT4,11830
|
|
191
192
|
rbx/testcase.py,sha256=yKOq3CAJZ1YTmInvnoIs0u1iJnRj_X85XiWbLI-p9d8,1951
|
192
193
|
rbx/testcase_rendering.py,sha256=nfmv6dSEqd4aR3TsaODwkKGK6AXty_DDKtWf_ejiQpI,2084
|
193
194
|
rbx/testing_utils.py,sha256=x_PqD8Zd2PkN91NxVHUnSTs044-1WK5KKtttKQBXpFs,2083
|
194
|
-
rbx/utils.py,sha256=
|
195
|
-
rbx_cp-0.5.
|
196
|
-
rbx_cp-0.5.
|
197
|
-
rbx_cp-0.5.
|
198
|
-
rbx_cp-0.5.
|
199
|
-
rbx_cp-0.5.
|
195
|
+
rbx/utils.py,sha256=SfR844_i0ebRDMkmS_w1YdZiWPc6h2RGADygewlWRbA,4845
|
196
|
+
rbx_cp-0.5.54.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
|
197
|
+
rbx_cp-0.5.54.dist-info/METADATA,sha256=Ki-VbHPb5TES3dtzJ_muEqjIuzJRACCQ5MIhdIGG0G4,3387
|
198
|
+
rbx_cp-0.5.54.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
199
|
+
rbx_cp-0.5.54.dist-info/entry_points.txt,sha256=qBTLBOeifT1F00LWaEewRRE_jQPgvH7BUdJfZ-dYsFU,57
|
200
|
+
rbx_cp-0.5.54.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|