rbx.cp 0.5.16__py3-none-any.whl → 0.5.18__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rbx/box/builder.py +2 -2
- rbx/box/cd.py +12 -2
- rbx/box/checkers.py +38 -4
- rbx/box/code.py +128 -18
- rbx/box/compile.py +40 -8
- rbx/box/contest/build_contest_statements.py +7 -6
- rbx/box/contest/contest_package.py +15 -2
- rbx/box/contest/contest_utils.py +0 -9
- rbx/box/contest/main.py +35 -24
- rbx/box/contest/statements.py +4 -5
- rbx/box/deferred.py +26 -0
- rbx/box/extensions.py +0 -8
- rbx/box/generators.py +6 -4
- rbx/box/main.py +195 -19
- rbx/box/package.py +24 -2
- rbx/box/packaging/contest_main.py +5 -5
- rbx/box/sanitizers/warning_stack.py +90 -0
- rbx/box/schema.py +15 -1
- rbx/box/setter_config.py +132 -0
- rbx/box/solutions.py +237 -149
- rbx/box/solutions_test.py +2 -1
- rbx/box/stresses.py +5 -3
- rbx/box/validators.py +5 -5
- rbx/config.py +3 -0
- rbx/grading/caching.py +4 -0
- rbx/grading/judge/sandboxes/stupid_sandbox.py +2 -0
- rbx/grading/judge/sandboxes/timeit.py +3 -3
- rbx/grading/steps.py +143 -15
- rbx/grading/steps_with_caching.py +2 -0
- rbx/resources/default_setter_config.mac.yml +31 -0
- rbx/resources/default_setter_config.yml +29 -0
- rbx/utils.py +8 -1
- {rbx_cp-0.5.16.dist-info → rbx_cp-0.5.18.dist-info}/METADATA +2 -1
- {rbx_cp-0.5.16.dist-info → rbx_cp-0.5.18.dist-info}/RECORD +37 -32
- {rbx_cp-0.5.16.dist-info → rbx_cp-0.5.18.dist-info}/LICENSE +0 -0
- {rbx_cp-0.5.16.dist-info → rbx_cp-0.5.18.dist-info}/WHEEL +0 -0
- {rbx_cp-0.5.16.dist-info → rbx_cp-0.5.18.dist-info}/entry_points.txt +0 -0
rbx/box/setter_config.py
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
import functools
|
2
|
+
import importlib
|
3
|
+
import importlib.resources
|
4
|
+
import pathlib
|
5
|
+
import shlex
|
6
|
+
import sys
|
7
|
+
from typing import Dict
|
8
|
+
|
9
|
+
import typer
|
10
|
+
from pydantic import BaseModel, Field
|
11
|
+
|
12
|
+
from rbx import config, console, utils
|
13
|
+
|
14
|
+
app = typer.Typer(no_args_is_help=True)
|
15
|
+
|
16
|
+
_CONFIG_FILE_NAME = 'default_setter_config.yml'
|
17
|
+
_CONFIG_FILE_NAME_MAC = 'default_setter_config.mac.yml'
|
18
|
+
|
19
|
+
|
20
|
+
class SanitizersConfig(BaseModel):
|
21
|
+
enabled: bool = Field(
|
22
|
+
False,
|
23
|
+
description='Whether to use sanitizers when running solutions.',
|
24
|
+
)
|
25
|
+
|
26
|
+
command_substitutions: Dict[str, str] = Field(
|
27
|
+
{},
|
28
|
+
description='Substitutions to apply to commands before running them with sanitizers.',
|
29
|
+
)
|
30
|
+
|
31
|
+
|
32
|
+
class WarningsConfig(BaseModel):
|
33
|
+
enabled: bool = Field(
|
34
|
+
False,
|
35
|
+
description='Whether to use warning flags when running solutions.',
|
36
|
+
)
|
37
|
+
|
38
|
+
|
39
|
+
class SetterConfig(BaseModel):
|
40
|
+
sanitizers: SanitizersConfig = Field(
|
41
|
+
default_factory=SanitizersConfig, # type: ignore
|
42
|
+
description='Configuration for sanitizers.',
|
43
|
+
)
|
44
|
+
warnings: WarningsConfig = Field(
|
45
|
+
default_factory=WarningsConfig, # type: ignore
|
46
|
+
description='Configuration for warnings.',
|
47
|
+
)
|
48
|
+
|
49
|
+
command_substitutions: Dict[str, str] = Field(
|
50
|
+
{},
|
51
|
+
description='Substitutions to apply to commands before running them.',
|
52
|
+
)
|
53
|
+
|
54
|
+
def substitute_command(self, command: str, sanitized: bool = False) -> str:
|
55
|
+
exe = shlex.split(command)[0]
|
56
|
+
if sanitized and exe in self.sanitizers.command_substitutions:
|
57
|
+
exe = self.sanitizers.command_substitutions[exe]
|
58
|
+
return ' '.join([exe, *shlex.split(command)[1:]])
|
59
|
+
if exe in self.command_substitutions:
|
60
|
+
exe = self.command_substitutions[exe]
|
61
|
+
return ' '.join([exe, *shlex.split(command)[1:]])
|
62
|
+
return command
|
63
|
+
|
64
|
+
|
65
|
+
def get_default_setter_config_path() -> pathlib.Path:
|
66
|
+
cfg_name = _CONFIG_FILE_NAME
|
67
|
+
if sys.platform == 'darwin':
|
68
|
+
cfg_name = _CONFIG_FILE_NAME_MAC
|
69
|
+
|
70
|
+
with importlib.resources.as_file(
|
71
|
+
importlib.resources.files('rbx') / 'resources' / cfg_name
|
72
|
+
) as file:
|
73
|
+
return file
|
74
|
+
|
75
|
+
|
76
|
+
def get_default_setter_config() -> SetterConfig:
|
77
|
+
return utils.model_from_yaml(
|
78
|
+
SetterConfig, get_default_setter_config_path().read_text()
|
79
|
+
)
|
80
|
+
|
81
|
+
|
82
|
+
def get_setter_config_path() -> pathlib.Path:
|
83
|
+
return config.get_app_path() / 'setter_config.yml'
|
84
|
+
|
85
|
+
|
86
|
+
@functools.cache
|
87
|
+
def get_setter_config() -> SetterConfig:
|
88
|
+
config_path = get_setter_config_path()
|
89
|
+
if not config_path.is_file():
|
90
|
+
utils.create_and_write(
|
91
|
+
config_path, get_default_setter_config_path().read_text()
|
92
|
+
)
|
93
|
+
return utils.model_from_yaml(SetterConfig, config_path.read_text())
|
94
|
+
|
95
|
+
|
96
|
+
def save_setter_config(config: SetterConfig):
|
97
|
+
config_path = get_setter_config_path()
|
98
|
+
config_path.write_text(utils.model_to_yaml(config))
|
99
|
+
get_setter_config.cache_clear()
|
100
|
+
|
101
|
+
|
102
|
+
@app.command(help='Show the path to the setter config.')
|
103
|
+
def path():
|
104
|
+
print(get_setter_config_path())
|
105
|
+
|
106
|
+
|
107
|
+
@app.command('list, ls')
|
108
|
+
def list():
|
109
|
+
"""
|
110
|
+
Pretty print the config file.
|
111
|
+
"""
|
112
|
+
console.console.print_json(utils.model_json(get_setter_config()))
|
113
|
+
|
114
|
+
|
115
|
+
@app.command(help='Open the setter config in an editor.')
|
116
|
+
def edit():
|
117
|
+
# Ensure config is created before calling the editor.
|
118
|
+
get_setter_config()
|
119
|
+
|
120
|
+
config.open_editor(get_setter_config_path())
|
121
|
+
|
122
|
+
|
123
|
+
@app.command()
|
124
|
+
def reset():
|
125
|
+
"""
|
126
|
+
Reset the config file to the default one.
|
127
|
+
"""
|
128
|
+
if not typer.confirm('Do you really want to reset your config to the default one?'):
|
129
|
+
return
|
130
|
+
cfg_path = get_setter_config_path()
|
131
|
+
cfg_path.unlink(missing_ok=True)
|
132
|
+
get_setter_config() # Reset the config.
|