rbx.cp 0.5.0__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/__init__.py +0 -0
- rbx/annotations.py +127 -0
- rbx/autoenum.py +333 -0
- rbx/box/__init__.py +0 -0
- rbx/box/builder.py +77 -0
- rbx/box/cd.py +37 -0
- rbx/box/checkers.py +134 -0
- rbx/box/code.py +185 -0
- rbx/box/compile.py +56 -0
- rbx/box/conftest.py +42 -0
- rbx/box/contest/__init__.py +0 -0
- rbx/box/contest/build_contest_statements.py +347 -0
- rbx/box/contest/contest_package.py +76 -0
- rbx/box/contest/contest_utils.py +20 -0
- rbx/box/contest/main.py +179 -0
- rbx/box/contest/schema.py +155 -0
- rbx/box/contest/statements.py +82 -0
- rbx/box/creation.py +72 -0
- rbx/box/download.py +64 -0
- rbx/box/environment.py +345 -0
- rbx/box/extensions.py +26 -0
- rbx/box/generators.py +478 -0
- rbx/box/generators_test.py +63 -0
- rbx/box/main.py +449 -0
- rbx/box/package.py +316 -0
- rbx/box/packaging/boca/extension.py +27 -0
- rbx/box/packaging/boca/packager.py +245 -0
- rbx/box/packaging/contest_main.py +82 -0
- rbx/box/packaging/main.py +68 -0
- rbx/box/packaging/packager.py +117 -0
- rbx/box/packaging/polygon/packager.py +320 -0
- rbx/box/packaging/polygon/test.py +81 -0
- rbx/box/packaging/polygon/xml_schema.py +106 -0
- rbx/box/presets/__init__.py +503 -0
- rbx/box/presets/fetch.py +70 -0
- rbx/box/presets/lock_schema.py +20 -0
- rbx/box/presets/schema.py +59 -0
- rbx/box/schema.py +394 -0
- rbx/box/solutions.py +792 -0
- rbx/box/solutions_test.py +41 -0
- rbx/box/statements/__init__.py +0 -0
- rbx/box/statements/build_statements.py +359 -0
- rbx/box/statements/builders.py +375 -0
- rbx/box/statements/joiners.py +113 -0
- rbx/box/statements/latex.py +47 -0
- rbx/box/statements/latex_jinja.py +214 -0
- rbx/box/statements/schema.py +138 -0
- rbx/box/stresses.py +292 -0
- rbx/box/stressing/__init__.py +0 -0
- rbx/box/stressing/finder_parser.py +359 -0
- rbx/box/stressing/generator_parser.py +258 -0
- rbx/box/testcases.py +54 -0
- rbx/box/ui/__init__.py +0 -0
- rbx/box/ui/captured_log.py +372 -0
- rbx/box/ui/css/app.tcss +48 -0
- rbx/box/ui/main.py +38 -0
- rbx/box/ui/run.py +209 -0
- rbx/box/validators.py +245 -0
- rbx/box/validators_test.py +15 -0
- rbx/checker.py +128 -0
- rbx/clone.py +197 -0
- rbx/config.py +271 -0
- rbx/conftest.py +38 -0
- rbx/console.py +27 -0
- rbx/create.py +37 -0
- rbx/edit.py +24 -0
- rbx/grading/__init__.py +0 -0
- rbx/grading/caching.py +356 -0
- rbx/grading/conftest.py +33 -0
- rbx/grading/judge/__init__.py +0 -0
- rbx/grading/judge/cacher.py +503 -0
- rbx/grading/judge/digester.py +35 -0
- rbx/grading/judge/sandbox.py +748 -0
- rbx/grading/judge/sandboxes/__init__.py +0 -0
- rbx/grading/judge/sandboxes/isolate.py +683 -0
- rbx/grading/judge/sandboxes/stupid_sandbox.py +310 -0
- rbx/grading/judge/sandboxes/timeit.py +217 -0
- rbx/grading/judge/storage.py +284 -0
- rbx/grading/judge/test.py +38 -0
- rbx/grading/judge/testiso.py +54 -0
- rbx/grading/steps.py +522 -0
- rbx/grading/steps_with_caching.py +59 -0
- rbx/grading/steps_with_caching_run_test.py +429 -0
- rbx/grading_utils.py +148 -0
- rbx/hydration.py +101 -0
- rbx/main.py +122 -0
- rbx/metadata.py +105 -0
- rbx/providers/__init__.py +43 -0
- rbx/providers/codeforces.py +73 -0
- rbx/providers/provider.py +26 -0
- rbx/resources/checkers/boilerplate.cpp +20 -0
- rbx/resources/default_config.json +48 -0
- rbx/resources/envs/default.rbx.yml +37 -0
- rbx/resources/envs/isolate.rbx.yml +37 -0
- rbx/resources/packagers/boca/checker.sh +43 -0
- rbx/resources/packagers/boca/compare +53 -0
- rbx/resources/packagers/boca/compile/c +172 -0
- rbx/resources/packagers/boca/compile/cc +173 -0
- rbx/resources/packagers/boca/compile/cpp +172 -0
- rbx/resources/packagers/boca/compile/java +194 -0
- rbx/resources/packagers/boca/compile/kt +155 -0
- rbx/resources/packagers/boca/compile/pas +172 -0
- rbx/resources/packagers/boca/compile/py2 +173 -0
- rbx/resources/packagers/boca/compile/py3 +173 -0
- rbx/resources/packagers/boca/run/c +128 -0
- rbx/resources/packagers/boca/run/cc +128 -0
- rbx/resources/packagers/boca/run/cpp +128 -0
- rbx/resources/packagers/boca/run/java +194 -0
- rbx/resources/packagers/boca/run/kt +159 -0
- rbx/resources/packagers/boca/run/py2 +166 -0
- rbx/resources/packagers/boca/run/py3 +166 -0
- rbx/resources/presets/default/contest/contest.rbx.yml +14 -0
- rbx/resources/presets/default/contest/statement/contest.rbx.tex +97 -0
- rbx/resources/presets/default/contest/statement/olymp.sty +250 -0
- rbx/resources/presets/default/contest/statement/template.rbx.tex +42 -0
- rbx/resources/presets/default/preset.rbx.yml +12 -0
- rbx/resources/presets/default/problem/.gitignore +6 -0
- rbx/resources/presets/default/problem/gen.cpp +9 -0
- rbx/resources/presets/default/problem/problem.rbx.yml +44 -0
- rbx/resources/presets/default/problem/random.py +3 -0
- rbx/resources/presets/default/problem/random.txt +2 -0
- rbx/resources/presets/default/problem/sols/main.cpp +9 -0
- rbx/resources/presets/default/problem/sols/slow.cpp +15 -0
- rbx/resources/presets/default/problem/sols/wa.cpp +9 -0
- rbx/resources/presets/default/problem/statement/olymp.sty +250 -0
- rbx/resources/presets/default/problem/statement/projecao.png +0 -0
- rbx/resources/presets/default/problem/statement/statement.rbx.tex +18 -0
- rbx/resources/presets/default/problem/statement/template.rbx.tex +89 -0
- rbx/resources/presets/default/problem/tests/samples/000.in +1 -0
- rbx/resources/presets/default/problem/tests/samples/001.in +1 -0
- rbx/resources/presets/default/problem/validator.cpp +16 -0
- rbx/resources/presets/default/problem/wcmp.cpp +34 -0
- rbx/resources/templates/template.cpp +19 -0
- rbx/run.py +45 -0
- rbx/schema.py +64 -0
- rbx/submit.py +61 -0
- rbx/submitors/__init__.py +18 -0
- rbx/submitors/codeforces.py +120 -0
- rbx/submitors/submitor.py +25 -0
- rbx/test.py +347 -0
- rbx/testcase.py +70 -0
- rbx/testcase_rendering.py +79 -0
- rbx/testdata/box1/gen1.cpp +7 -0
- rbx/testdata/box1/gen2.cpp +9 -0
- rbx/testdata/box1/genScript.py +2 -0
- rbx/testdata/box1/hard-tle.sol.cpp +26 -0
- rbx/testdata/box1/ole.cpp +17 -0
- rbx/testdata/box1/problem.rbx.yml +39 -0
- rbx/testdata/box1/re.sol.cpp +23 -0
- rbx/testdata/box1/sol.cpp +22 -0
- rbx/testdata/box1/tests/1.in +1 -0
- rbx/testdata/box1/tle-and-incorrect.sol.cpp +33 -0
- rbx/testdata/box1/tle.sol.cpp +35 -0
- rbx/testdata/box1/validator.cpp +11 -0
- rbx/testdata/box1/wa.sol.cpp +22 -0
- rbx/testdata/caching/executable.py +1 -0
- rbx/testdata/compatible +0 -0
- rbx/testing_utils.py +65 -0
- rbx/utils.py +162 -0
- rbx_cp-0.5.0.dist-info/LICENSE +201 -0
- rbx_cp-0.5.0.dist-info/METADATA +89 -0
- rbx_cp-0.5.0.dist-info/RECORD +164 -0
- rbx_cp-0.5.0.dist-info/WHEEL +4 -0
- rbx_cp-0.5.0.dist-info/entry_points.txt +4 -0
rbx/box/checkers.py
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
import pathlib
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
import typer
|
5
|
+
|
6
|
+
from rbx import console
|
7
|
+
from rbx.box import package
|
8
|
+
from rbx.box.code import compile_item, run_item
|
9
|
+
from rbx.box.schema import Testcase
|
10
|
+
from rbx.grading.judge.sandbox import SandboxBase
|
11
|
+
from rbx.grading.steps import (
|
12
|
+
CheckerResult,
|
13
|
+
DigestHolder,
|
14
|
+
DigestOrDest,
|
15
|
+
DigestOrSource,
|
16
|
+
GradingFileInput,
|
17
|
+
Outcome,
|
18
|
+
RunLog,
|
19
|
+
)
|
20
|
+
|
21
|
+
|
22
|
+
def compile_checker() -> str:
|
23
|
+
checker = package.get_checker()
|
24
|
+
|
25
|
+
try:
|
26
|
+
digest = compile_item(checker)
|
27
|
+
except Exception as e:
|
28
|
+
console.console.print('[error]Failed compiling checker.[/error]')
|
29
|
+
raise typer.Exit(1) from e
|
30
|
+
return digest
|
31
|
+
|
32
|
+
|
33
|
+
def _check_pre_output(run_log: Optional[RunLog]) -> CheckerResult:
|
34
|
+
pkg = package.find_problem_package_or_die()
|
35
|
+
|
36
|
+
if run_log is None:
|
37
|
+
return CheckerResult(outcome=Outcome.INTERNAL_ERROR)
|
38
|
+
|
39
|
+
timelimit = pkg.timelimit_for_language(run_log.get_run_language())
|
40
|
+
if run_log.time is not None and run_log.time * 1000 > timelimit * 2:
|
41
|
+
return CheckerResult(outcome=Outcome.TIME_LIMIT_EXCEEDED)
|
42
|
+
|
43
|
+
if run_log.exitstatus in [SandboxBase.EXIT_SIGNAL, SandboxBase.EXIT_NONZERO_RETURN]:
|
44
|
+
return CheckerResult(outcome=Outcome.RUNTIME_ERROR)
|
45
|
+
if run_log.exitstatus in [SandboxBase.EXIT_TIMEOUT, SandboxBase.EXIT_TIMEOUT_WALL]:
|
46
|
+
return CheckerResult(outcome=Outcome.TIME_LIMIT_EXCEEDED)
|
47
|
+
if run_log.exitstatus == SandboxBase.EXIT_MEMORY_LIMIT_EXCEEDED:
|
48
|
+
return CheckerResult(outcome=Outcome.MEMORY_LIMIT_EXCEEDED)
|
49
|
+
if run_log.exitstatus == SandboxBase.EXIT_SANDBOX_ERROR:
|
50
|
+
return CheckerResult(outcome=Outcome.INTERNAL_ERROR)
|
51
|
+
if run_log.exitstatus == SandboxBase.EXIT_OUTPUT_LIMIT_EXCEEDED:
|
52
|
+
return CheckerResult(outcome=Outcome.OUTPUT_LIMIT_EXCEEDED)
|
53
|
+
return CheckerResult(outcome=Outcome.ACCEPTED)
|
54
|
+
|
55
|
+
|
56
|
+
def _convert_tle(result: CheckerResult, run_log: Optional[RunLog]) -> CheckerResult:
|
57
|
+
if result.outcome == Outcome.TIME_LIMIT_EXCEEDED:
|
58
|
+
# This already is a TLE outcome.
|
59
|
+
return result
|
60
|
+
pkg = package.find_problem_package_or_die()
|
61
|
+
if (
|
62
|
+
run_log is not None
|
63
|
+
and run_log.time is not None
|
64
|
+
and run_log.time * 1000
|
65
|
+
>= pkg.timelimit_for_language(run_log.get_run_language())
|
66
|
+
):
|
67
|
+
# Soft TLE.
|
68
|
+
result.no_tle_outcome = result.outcome
|
69
|
+
result.outcome = Outcome.TIME_LIMIT_EXCEEDED
|
70
|
+
return result
|
71
|
+
|
72
|
+
|
73
|
+
def check_with_no_output(run_log: Optional[RunLog]) -> CheckerResult:
|
74
|
+
result = _check_pre_output(run_log)
|
75
|
+
return _convert_tle(result, run_log)
|
76
|
+
|
77
|
+
|
78
|
+
def check(
|
79
|
+
checker_digest: str,
|
80
|
+
run_log: Optional[RunLog],
|
81
|
+
testcase: Testcase,
|
82
|
+
program_output: pathlib.Path,
|
83
|
+
skip_run_log: bool = False,
|
84
|
+
) -> CheckerResult:
|
85
|
+
if not skip_run_log:
|
86
|
+
result = _check_pre_output(run_log)
|
87
|
+
if result.outcome != Outcome.ACCEPTED:
|
88
|
+
return _convert_tle(result, run_log)
|
89
|
+
|
90
|
+
pkg = package.find_problem_package_or_die()
|
91
|
+
output_size = program_output.stat().st_size
|
92
|
+
if output_size > pkg.outputLimit * 1024:
|
93
|
+
return CheckerResult(
|
94
|
+
outcome=Outcome.OUTPUT_LIMIT_EXCEEDED,
|
95
|
+
message=f'Output size {pkg.outputLimit}kb, limit is {output_size // 1024}kb.',
|
96
|
+
)
|
97
|
+
|
98
|
+
error = DigestHolder()
|
99
|
+
inputs = [
|
100
|
+
GradingFileInput(
|
101
|
+
src=testcase.inputPath,
|
102
|
+
dest=pathlib.PosixPath('input.txt'),
|
103
|
+
),
|
104
|
+
GradingFileInput(
|
105
|
+
src=testcase.outputPath,
|
106
|
+
dest=pathlib.PosixPath('expected.txt'),
|
107
|
+
),
|
108
|
+
GradingFileInput(
|
109
|
+
src=program_output,
|
110
|
+
dest=pathlib.PosixPath('output.txt'),
|
111
|
+
),
|
112
|
+
]
|
113
|
+
checker_run_log = run_item(
|
114
|
+
package.get_checker(),
|
115
|
+
DigestOrSource.create(checker_digest),
|
116
|
+
stderr=DigestOrDest.create(error),
|
117
|
+
inputs=inputs,
|
118
|
+
extra_args='input.txt output.txt expected.txt',
|
119
|
+
)
|
120
|
+
message = package.get_digest_as_string(error.value or '') or ''
|
121
|
+
|
122
|
+
if checker_run_log is None or checker_run_log.exitcode not in [0, 1, 2, 3]:
|
123
|
+
return CheckerResult(outcome=Outcome.INTERNAL_ERROR)
|
124
|
+
|
125
|
+
result = CheckerResult(outcome=Outcome.ACCEPTED, message=message)
|
126
|
+
|
127
|
+
if checker_run_log.exitcode in [1, 2]:
|
128
|
+
result = CheckerResult(outcome=Outcome.WRONG_ANSWER, message=message)
|
129
|
+
if checker_run_log.exitcode == 3:
|
130
|
+
result = CheckerResult(outcome=Outcome.JUDGE_FAILED, message=message)
|
131
|
+
|
132
|
+
if skip_run_log:
|
133
|
+
return result
|
134
|
+
return _convert_tle(result, run_log)
|
rbx/box/code.py
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
import pathlib
|
2
|
+
import shlex
|
3
|
+
import sys
|
4
|
+
from pathlib import PosixPath
|
5
|
+
from typing import List, Optional
|
6
|
+
|
7
|
+
import typer
|
8
|
+
|
9
|
+
from rbx.box import download, package
|
10
|
+
from rbx.box.environment import (
|
11
|
+
ExecutionConfig,
|
12
|
+
get_compilation_config,
|
13
|
+
get_execution_config,
|
14
|
+
get_extension_or_default,
|
15
|
+
get_file_mapping,
|
16
|
+
get_language,
|
17
|
+
get_mapped_command,
|
18
|
+
get_mapped_commands,
|
19
|
+
get_sandbox_params_from_config,
|
20
|
+
merge_execution_configs,
|
21
|
+
)
|
22
|
+
from rbx.box.extensions import MacExtension
|
23
|
+
from rbx.box.schema import CodeItem
|
24
|
+
from rbx.grading import steps_with_caching
|
25
|
+
from rbx.grading.steps import (
|
26
|
+
DigestHolder,
|
27
|
+
DigestOrDest,
|
28
|
+
DigestOrSource,
|
29
|
+
GradingArtifacts,
|
30
|
+
GradingFileInput,
|
31
|
+
GradingFileOutput,
|
32
|
+
RunLog,
|
33
|
+
RunLogMetadata,
|
34
|
+
)
|
35
|
+
|
36
|
+
|
37
|
+
def normalize_for_macos(commands: List[str]) -> List[str]:
|
38
|
+
def normalize(command: str) -> str:
|
39
|
+
extension = get_extension_or_default('mac', MacExtension)
|
40
|
+
if extension.gpp_alternative is None:
|
41
|
+
return command
|
42
|
+
return command.replace('g++', extension.gpp_alternative)
|
43
|
+
|
44
|
+
return [normalize(command) for command in commands]
|
45
|
+
|
46
|
+
|
47
|
+
def get_extension(code: CodeItem) -> str:
|
48
|
+
path: pathlib.Path = PosixPath(code.path)
|
49
|
+
return path.suffix[1:]
|
50
|
+
|
51
|
+
|
52
|
+
def find_language_name(code: CodeItem) -> str:
|
53
|
+
if code.language is not None:
|
54
|
+
return get_language(code.language).name
|
55
|
+
return get_language(get_extension(code)).name
|
56
|
+
|
57
|
+
|
58
|
+
# Compile code item and return its digest in the storage.
|
59
|
+
def compile_item(code: CodeItem) -> str:
|
60
|
+
generator_path = PosixPath(code.path)
|
61
|
+
language = find_language_name(code)
|
62
|
+
compilation_options = get_compilation_config(language)
|
63
|
+
file_mapping = get_file_mapping(language)
|
64
|
+
dependency_cache = package.get_dependency_cache()
|
65
|
+
sandbox = package.get_singleton_sandbox()
|
66
|
+
sandbox_params = get_sandbox_params_from_config(compilation_options.sandbox)
|
67
|
+
|
68
|
+
if not compilation_options.commands:
|
69
|
+
# Language is not compiled.
|
70
|
+
return sandbox.file_cacher.put_file_from_path(generator_path)
|
71
|
+
|
72
|
+
# Compile the generator
|
73
|
+
commands = get_mapped_commands(compilation_options.commands, file_mapping)
|
74
|
+
if sys.platform == 'darwin':
|
75
|
+
commands = normalize_for_macos(commands)
|
76
|
+
|
77
|
+
compiled_digest = DigestHolder()
|
78
|
+
|
79
|
+
artifacts = GradingArtifacts()
|
80
|
+
artifacts.inputs.extend(
|
81
|
+
GradingFileInput(src=src, dest=dest)
|
82
|
+
for src, dest in package.get_compilation_files(code)
|
83
|
+
)
|
84
|
+
download.maybe_add_testlib(code, artifacts)
|
85
|
+
download.maybe_add_jngen(code, artifacts)
|
86
|
+
artifacts.inputs.append(
|
87
|
+
GradingFileInput(src=generator_path, dest=PosixPath(file_mapping.compilable))
|
88
|
+
)
|
89
|
+
artifacts.outputs.append(
|
90
|
+
GradingFileOutput(
|
91
|
+
src=PosixPath(file_mapping.executable),
|
92
|
+
digest=compiled_digest,
|
93
|
+
executable=True,
|
94
|
+
)
|
95
|
+
)
|
96
|
+
|
97
|
+
if not steps_with_caching.compile(
|
98
|
+
commands,
|
99
|
+
params=sandbox_params,
|
100
|
+
artifacts=artifacts,
|
101
|
+
sandbox=sandbox,
|
102
|
+
dependency_cache=dependency_cache,
|
103
|
+
):
|
104
|
+
raise typer.Exit(1)
|
105
|
+
|
106
|
+
assert compiled_digest.value is not None
|
107
|
+
return compiled_digest.value
|
108
|
+
|
109
|
+
|
110
|
+
def run_item(
|
111
|
+
code: CodeItem,
|
112
|
+
executable: DigestOrSource,
|
113
|
+
stdin: Optional[DigestOrSource] = None,
|
114
|
+
stdout: Optional[DigestOrDest] = None,
|
115
|
+
stderr: Optional[DigestOrDest] = None,
|
116
|
+
inputs: Optional[List[GradingFileInput]] = None,
|
117
|
+
outputs: Optional[List[GradingFileOutput]] = None,
|
118
|
+
extra_args: Optional[str] = None,
|
119
|
+
extra_config: Optional[ExecutionConfig] = None,
|
120
|
+
) -> Optional[RunLog]:
|
121
|
+
language = find_language_name(code)
|
122
|
+
execution_options = get_execution_config(language)
|
123
|
+
if extra_config is not None:
|
124
|
+
execution_options = merge_execution_configs([execution_options, extra_config])
|
125
|
+
file_mapping = get_file_mapping(language)
|
126
|
+
dependency_cache = package.get_dependency_cache()
|
127
|
+
sandbox = package.get_singleton_sandbox()
|
128
|
+
sandbox_params = get_sandbox_params_from_config(execution_options.sandbox)
|
129
|
+
|
130
|
+
sandbox_params.set_stdall(
|
131
|
+
stdin=PosixPath(file_mapping.input) if stdin is not None else None,
|
132
|
+
stdout=PosixPath(file_mapping.output) if stdout is not None else None,
|
133
|
+
stderr=PosixPath(file_mapping.error) if stderr is not None else None,
|
134
|
+
)
|
135
|
+
|
136
|
+
assert execution_options.command
|
137
|
+
command = get_mapped_command(execution_options.command, file_mapping)
|
138
|
+
|
139
|
+
if extra_args is not None:
|
140
|
+
splitted_command = shlex.split(command)
|
141
|
+
splitted_command.extend(shlex.split(extra_args))
|
142
|
+
command = shlex.join(splitted_command)
|
143
|
+
|
144
|
+
artifacts = GradingArtifacts()
|
145
|
+
artifacts.inputs.append(
|
146
|
+
GradingFileInput(
|
147
|
+
**executable.expand(),
|
148
|
+
dest=PosixPath(file_mapping.executable),
|
149
|
+
executable=True,
|
150
|
+
)
|
151
|
+
)
|
152
|
+
if stdin is not None:
|
153
|
+
artifacts.inputs.append(
|
154
|
+
GradingFileInput(
|
155
|
+
**stdin.expand(),
|
156
|
+
dest=PosixPath(file_mapping.input),
|
157
|
+
)
|
158
|
+
)
|
159
|
+
if stdout is not None:
|
160
|
+
artifacts.outputs.append(
|
161
|
+
GradingFileOutput(
|
162
|
+
src=PosixPath(file_mapping.output),
|
163
|
+
**stdout.expand(),
|
164
|
+
)
|
165
|
+
)
|
166
|
+
if stderr is not None:
|
167
|
+
artifacts.outputs.append(
|
168
|
+
GradingFileOutput(
|
169
|
+
src=PosixPath(file_mapping.error),
|
170
|
+
**stderr.expand(),
|
171
|
+
)
|
172
|
+
)
|
173
|
+
if inputs:
|
174
|
+
artifacts.inputs.extend(inputs)
|
175
|
+
if outputs:
|
176
|
+
artifacts.outputs.extend(outputs)
|
177
|
+
|
178
|
+
return steps_with_caching.run(
|
179
|
+
command,
|
180
|
+
params=sandbox_params,
|
181
|
+
sandbox=sandbox,
|
182
|
+
artifacts=artifacts,
|
183
|
+
dependency_cache=dependency_cache,
|
184
|
+
metadata=RunLogMetadata(language=code.language),
|
185
|
+
)
|
rbx/box/compile.py
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
import pathlib
|
2
|
+
|
3
|
+
import typer
|
4
|
+
|
5
|
+
from rbx import annotations, console
|
6
|
+
from rbx.box import code, package
|
7
|
+
from rbx.box.schema import CodeItem
|
8
|
+
|
9
|
+
app = typer.Typer(no_args_is_help=True, cls=annotations.AliasGroup)
|
10
|
+
|
11
|
+
|
12
|
+
def _compile_out():
|
13
|
+
return package.get_build_path() / 'exe'
|
14
|
+
|
15
|
+
|
16
|
+
def _compile(item: CodeItem):
|
17
|
+
console.console.print(f'Compiling [item]{item.path}[/item]...')
|
18
|
+
digest = code.compile_item(item)
|
19
|
+
cacher = package.get_file_cacher()
|
20
|
+
out_path = _compile_out()
|
21
|
+
cacher.get_file_to_path(digest, out_path)
|
22
|
+
out_path.chmod(0o755)
|
23
|
+
|
24
|
+
console.console.print(
|
25
|
+
f'[success]Compiled file written at [item]{out_path}[/item].[/success]'
|
26
|
+
)
|
27
|
+
|
28
|
+
|
29
|
+
@app.command('any, a', help='Compile an asset given its path.')
|
30
|
+
@package.within_problem
|
31
|
+
def any(path: str):
|
32
|
+
_compile(CodeItem(path=pathlib.Path(path)))
|
33
|
+
|
34
|
+
|
35
|
+
@app.command('solution, s', help='Compile a solution given its path.')
|
36
|
+
@package.within_problem
|
37
|
+
def solution(path: str):
|
38
|
+
_compile(package.get_solution(path))
|
39
|
+
|
40
|
+
|
41
|
+
@app.command('generator, gen, g', help='Compile a generator given its name.')
|
42
|
+
@package.within_problem
|
43
|
+
def generator(name: str):
|
44
|
+
_compile(package.get_generator(name))
|
45
|
+
|
46
|
+
|
47
|
+
@app.command('checker, c', help='Compile the checker.')
|
48
|
+
@package.within_problem
|
49
|
+
def checker():
|
50
|
+
_compile(package.get_checker())
|
51
|
+
|
52
|
+
|
53
|
+
@app.command('validator, v', help='Compile the main validator.')
|
54
|
+
@package.within_problem
|
55
|
+
def validator():
|
56
|
+
_compile(package.get_validator())
|
rbx/box/conftest.py
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
import os
|
2
|
+
import pathlib
|
3
|
+
import shutil
|
4
|
+
from collections.abc import Iterator
|
5
|
+
|
6
|
+
import pytest
|
7
|
+
|
8
|
+
from rbx import testing_utils
|
9
|
+
from rbx.box import package
|
10
|
+
|
11
|
+
|
12
|
+
@pytest.fixture
|
13
|
+
def pkg_cleandir(cleandir: pathlib.Path) -> Iterator[pathlib.Path]:
|
14
|
+
old_temp_dir = package.TEMP_DIR
|
15
|
+
package.TEMP_DIR = cleandir
|
16
|
+
|
17
|
+
pkgdir = cleandir / 'pkg'
|
18
|
+
pkgdir.mkdir(exist_ok=True, parents=True)
|
19
|
+
lwd = pathlib.Path.cwd()
|
20
|
+
os.chdir(str(pkgdir))
|
21
|
+
try:
|
22
|
+
yield pkgdir.absolute()
|
23
|
+
finally:
|
24
|
+
os.chdir(str(lwd))
|
25
|
+
package.TEMP_DIR = old_temp_dir
|
26
|
+
|
27
|
+
|
28
|
+
@pytest.fixture
|
29
|
+
def pkg_from_testdata(
|
30
|
+
request, testdata_path: pathlib.Path, pkg_cleandir: pathlib.Path
|
31
|
+
) -> Iterator[pathlib.Path]:
|
32
|
+
marker = request.node.get_closest_marker('test_pkg')
|
33
|
+
if marker is None:
|
34
|
+
raise ValueError('test_pkg marker not found')
|
35
|
+
testdata = testdata_path / marker.args[0]
|
36
|
+
shutil.copytree(str(testdata), str(pkg_cleandir), dirs_exist_ok=True)
|
37
|
+
yield pkg_cleandir
|
38
|
+
|
39
|
+
|
40
|
+
@pytest.fixture(autouse=True)
|
41
|
+
def clear_cache():
|
42
|
+
testing_utils.clear_all_functools_cache()
|
File without changes
|