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/environment.py
ADDED
@@ -0,0 +1,345 @@
|
|
1
|
+
import functools
|
2
|
+
import pathlib
|
3
|
+
from enum import Enum
|
4
|
+
from typing import Annotated, List, Optional, Type, TypeVar
|
5
|
+
|
6
|
+
import typer
|
7
|
+
from pydantic import BaseModel, ConfigDict
|
8
|
+
|
9
|
+
from rbx import config, console, utils
|
10
|
+
from rbx.box.extensions import Extensions, LanguageExtensions
|
11
|
+
from rbx.grading.judge.sandbox import SandboxBase, SandboxParams
|
12
|
+
from rbx.grading.judge.sandboxes.isolate import IsolateSandbox
|
13
|
+
from rbx.grading.judge.sandboxes.stupid_sandbox import StupidSandbox
|
14
|
+
|
15
|
+
T = TypeVar('T', bound=BaseModel)
|
16
|
+
|
17
|
+
|
18
|
+
class VerificationLevel(Enum):
|
19
|
+
NONE = 0
|
20
|
+
VALIDATE = 1
|
21
|
+
FAST_SOLUTIONS = 2
|
22
|
+
ASAN = 3
|
23
|
+
ALL_SOLUTIONS = 4
|
24
|
+
FULL = 5
|
25
|
+
|
26
|
+
|
27
|
+
VerificationParam = Annotated[
|
28
|
+
int,
|
29
|
+
typer.Option(
|
30
|
+
'--verification-level',
|
31
|
+
'--verification',
|
32
|
+
'-v',
|
33
|
+
help='Verification level to use when building package.',
|
34
|
+
default_factory=lambda: VerificationLevel.ALL_SOLUTIONS.value,
|
35
|
+
),
|
36
|
+
]
|
37
|
+
|
38
|
+
|
39
|
+
class FileMapping(BaseModel):
|
40
|
+
model_config = ConfigDict(extra='forbid')
|
41
|
+
|
42
|
+
# Path where to copy the stdin file to before running the program,
|
43
|
+
# relative to the sandbox root.
|
44
|
+
input: str = 'stdin'
|
45
|
+
|
46
|
+
# Path where to output the stdout file after running the program,
|
47
|
+
# relative to the sandbox root.
|
48
|
+
output: str = 'stdout'
|
49
|
+
|
50
|
+
# Path where to output the stderr file after running the program,
|
51
|
+
# relative to the sandbox root.
|
52
|
+
error: str = 'stderr'
|
53
|
+
|
54
|
+
# Path where to copy the compilable file to before compiling the program,
|
55
|
+
# relative to the sandbox root.
|
56
|
+
compilable: str = 'compilable'
|
57
|
+
|
58
|
+
# Path to where to output the executable file after compiling the program,
|
59
|
+
# relative to the sandbox root.
|
60
|
+
executable: str = 'executable'
|
61
|
+
|
62
|
+
|
63
|
+
class EnvironmentSandbox(BaseModel):
|
64
|
+
model_config = ConfigDict(extra='forbid')
|
65
|
+
|
66
|
+
# Max. number of process to allow to run concurrently for the program.
|
67
|
+
maxProcesses: Optional[int] = 1
|
68
|
+
|
69
|
+
# Time limit in milliseconds to allow the program to run.
|
70
|
+
timeLimit: Optional[int] = None
|
71
|
+
|
72
|
+
# Wall time limit in milliseconds to allow the program to run.
|
73
|
+
wallTimeLimit: Optional[int] = None
|
74
|
+
|
75
|
+
# Memory limit in MiB.
|
76
|
+
memoryLimit: Optional[int] = None
|
77
|
+
|
78
|
+
# File size limit in KiB
|
79
|
+
fileSizeLimit: Optional[int] = None
|
80
|
+
|
81
|
+
# Stack limit in MiB.
|
82
|
+
stackLimit: Optional[int] = None
|
83
|
+
|
84
|
+
# Whether to preserve env. variables coming from the host.
|
85
|
+
preserveEnv: Optional[bool] = False
|
86
|
+
|
87
|
+
# Directories in the host that should be read-only exposed to the sandbox.
|
88
|
+
mirrorDirs: Optional[List[str]] = []
|
89
|
+
|
90
|
+
|
91
|
+
class CompilationConfig(BaseModel):
|
92
|
+
# Commands to compile the program.
|
93
|
+
commands: Optional[List[str]] = []
|
94
|
+
|
95
|
+
# Sandbox configuration to use when compiling for this language.
|
96
|
+
sandbox: Optional[EnvironmentSandbox] = None
|
97
|
+
|
98
|
+
|
99
|
+
class ExecutionConfig(BaseModel):
|
100
|
+
model_config = ConfigDict(extra='forbid')
|
101
|
+
|
102
|
+
# Command to run the program.
|
103
|
+
command: Optional[str] = None
|
104
|
+
|
105
|
+
# Sandbox configuration to use when executing for this language.
|
106
|
+
sandbox: Optional[EnvironmentSandbox] = None
|
107
|
+
|
108
|
+
|
109
|
+
class EnvironmentLanguage(BaseModel):
|
110
|
+
model_config = ConfigDict(extra='forbid')
|
111
|
+
|
112
|
+
# Identifier of this language within this environment.
|
113
|
+
name: str
|
114
|
+
|
115
|
+
# Readable name for this language.
|
116
|
+
readable_name: Optional[str] = None
|
117
|
+
|
118
|
+
# File extension supported by this language. If there's only one language
|
119
|
+
# that supports a certain file extension in the environment, the tool
|
120
|
+
# will automatically identify the language based on such extension.
|
121
|
+
extension: str
|
122
|
+
|
123
|
+
# Compilation config to use when compiling programs for this language.
|
124
|
+
compilation: Optional[CompilationConfig] = None
|
125
|
+
|
126
|
+
# Execution config to use when running programs for this language.
|
127
|
+
execution: ExecutionConfig
|
128
|
+
|
129
|
+
# Mapping for files within the sandbox. If not specified, the default mapping
|
130
|
+
# for the environment will be used.
|
131
|
+
fileMapping: Optional[FileMapping] = None
|
132
|
+
|
133
|
+
# Exntensions to apply for this language.
|
134
|
+
extensions: Optional[LanguageExtensions] = None
|
135
|
+
|
136
|
+
def get_extension(self, name: str, _: Type[T]) -> Optional[T]:
|
137
|
+
if self.extensions is None:
|
138
|
+
return None
|
139
|
+
if hasattr(self.extensions, name):
|
140
|
+
return None
|
141
|
+
return getattr(self.extensions, name)
|
142
|
+
|
143
|
+
def get_extension_or_default(self, name: str, cls: Type[T]) -> T:
|
144
|
+
return self.get_extension(name, cls) or cls()
|
145
|
+
|
146
|
+
|
147
|
+
class Environment(BaseModel):
|
148
|
+
model_config = ConfigDict(extra='forbid')
|
149
|
+
|
150
|
+
# Default mapping for files within the sandbox. Fields in the mapping can be
|
151
|
+
# individually overridden in the language configuration.
|
152
|
+
defaultFileMapping: Optional[FileMapping] = None
|
153
|
+
|
154
|
+
# Default compilation configuration to use when compiling programs. Fields in
|
155
|
+
# the compilation config can be individually overridden in the language configuration.
|
156
|
+
defaultCompilation: Optional[CompilationConfig] = None
|
157
|
+
|
158
|
+
# Default execution configuration to use when running programs. Fields in the
|
159
|
+
# execution config can be individually overridden in the language configuration.
|
160
|
+
defaultExecution: Optional[ExecutionConfig] = None
|
161
|
+
|
162
|
+
# Configuration for each language supported in this environment.
|
163
|
+
languages: List[EnvironmentLanguage] = []
|
164
|
+
|
165
|
+
# Identifier of the sandbox used by this environment (e.g. "stupid", "isolate")
|
166
|
+
sandbox: str = 'stupid'
|
167
|
+
|
168
|
+
# Identifier of the preset that should be used when creating new problems.
|
169
|
+
preset: str = 'default'
|
170
|
+
|
171
|
+
# Extensions to be added to the environment.
|
172
|
+
extensions: Optional[Extensions] = None
|
173
|
+
|
174
|
+
|
175
|
+
def get_environment_path(env: str) -> pathlib.Path:
|
176
|
+
return config.get_app_file(pathlib.PosixPath('envs') / f'{env}.rbx.yml')
|
177
|
+
|
178
|
+
|
179
|
+
def get_local_environment_path() -> Optional[pathlib.Path]:
|
180
|
+
# TODO: implement logic to get env from local preset
|
181
|
+
return None
|
182
|
+
|
183
|
+
|
184
|
+
@functools.cache
|
185
|
+
def get_environment(env: Optional[str] = None) -> Environment:
|
186
|
+
env_path = (
|
187
|
+
get_environment_path(env) if env is not None else get_local_environment_path()
|
188
|
+
)
|
189
|
+
if env_path is None:
|
190
|
+
env_path = get_environment_path(config.get_config().boxEnvironment)
|
191
|
+
if not env_path.is_file():
|
192
|
+
console.console.print(
|
193
|
+
f'Environment file [item]{env_path}[/item] not found.', style='error'
|
194
|
+
)
|
195
|
+
raise typer.Exit()
|
196
|
+
return utils.model_from_yaml(Environment, env_path.read_text())
|
197
|
+
|
198
|
+
|
199
|
+
@functools.cache
|
200
|
+
def get_language(name: str) -> EnvironmentLanguage:
|
201
|
+
for lang in get_environment().languages:
|
202
|
+
if lang.name == name:
|
203
|
+
return lang
|
204
|
+
console.console.print(f'Language [item]{name}[/item] not found.', style='error')
|
205
|
+
raise typer.Exit()
|
206
|
+
|
207
|
+
|
208
|
+
def install_environment(name: str, file: pathlib.Path):
|
209
|
+
if not file.is_file():
|
210
|
+
console.console.print(
|
211
|
+
f'[error]Environment file [item]{file}[/item] could not be found.'
|
212
|
+
)
|
213
|
+
raise typer.Exit(1)
|
214
|
+
|
215
|
+
get_environment_path(name).write_bytes(file.read_bytes())
|
216
|
+
console.console.print(
|
217
|
+
f'[success]Environment [item]{name}[/item] was installed from [item]{file}[/item].'
|
218
|
+
)
|
219
|
+
|
220
|
+
|
221
|
+
def _merge_shallow_models(model: Type[T], base: T, override: T) -> T:
|
222
|
+
return model(
|
223
|
+
**{
|
224
|
+
**base.model_dump(exclude_unset=True),
|
225
|
+
**override.model_dump(exclude_unset=True),
|
226
|
+
}
|
227
|
+
)
|
228
|
+
|
229
|
+
|
230
|
+
def merge_compilation_configs(
|
231
|
+
compilation_configs: List[Optional[CompilationConfig]],
|
232
|
+
) -> CompilationConfig:
|
233
|
+
merged_cfg = CompilationConfig()
|
234
|
+
merged_cfg.sandbox = EnvironmentSandbox(
|
235
|
+
maxProcesses=None,
|
236
|
+
timeLimit=10000,
|
237
|
+
wallTimeLimit=10000,
|
238
|
+
memoryLimit=512,
|
239
|
+
preserveEnv=True,
|
240
|
+
mirrorDirs=['/etc', '/usr'],
|
241
|
+
)
|
242
|
+
for cfg in compilation_configs:
|
243
|
+
if cfg is None:
|
244
|
+
continue
|
245
|
+
merged_cfg.commands = cfg.commands or merged_cfg.commands
|
246
|
+
if cfg.sandbox is not None:
|
247
|
+
merged_cfg.sandbox = _merge_shallow_models(
|
248
|
+
EnvironmentSandbox, merged_cfg.sandbox, cfg.sandbox
|
249
|
+
)
|
250
|
+
return merged_cfg
|
251
|
+
|
252
|
+
|
253
|
+
@functools.cache
|
254
|
+
def get_compilation_config(language: str) -> CompilationConfig:
|
255
|
+
environment = get_environment()
|
256
|
+
return merge_compilation_configs(
|
257
|
+
[environment.defaultCompilation, get_language(language).compilation]
|
258
|
+
)
|
259
|
+
|
260
|
+
|
261
|
+
def merge_execution_configs(
|
262
|
+
execution_configs: List[Optional[ExecutionConfig]],
|
263
|
+
) -> ExecutionConfig:
|
264
|
+
merged_cfg = ExecutionConfig()
|
265
|
+
merged_cfg.sandbox = EnvironmentSandbox()
|
266
|
+
for cfg in execution_configs:
|
267
|
+
if cfg is None:
|
268
|
+
continue
|
269
|
+
merged_cfg.command = cfg.command or merged_cfg.command
|
270
|
+
if cfg.sandbox is not None:
|
271
|
+
merged_cfg.sandbox = _merge_shallow_models(
|
272
|
+
EnvironmentSandbox, merged_cfg.sandbox, cfg.sandbox
|
273
|
+
)
|
274
|
+
return merged_cfg
|
275
|
+
|
276
|
+
|
277
|
+
@functools.cache
|
278
|
+
def get_execution_config(language: str) -> ExecutionConfig:
|
279
|
+
environment = get_environment()
|
280
|
+
return merge_execution_configs(
|
281
|
+
[environment.defaultExecution, get_language(language).execution]
|
282
|
+
)
|
283
|
+
|
284
|
+
|
285
|
+
@functools.cache
|
286
|
+
def get_file_mapping(language: str) -> FileMapping:
|
287
|
+
environment = get_environment()
|
288
|
+
return _merge_shallow_models(
|
289
|
+
FileMapping,
|
290
|
+
environment.defaultFileMapping or FileMapping(),
|
291
|
+
get_language(language).fileMapping or FileMapping(),
|
292
|
+
)
|
293
|
+
|
294
|
+
|
295
|
+
@functools.cache
|
296
|
+
def get_sandbox_type() -> Type[SandboxBase]:
|
297
|
+
used_sandbox = get_environment().sandbox
|
298
|
+
if used_sandbox == 'stupid':
|
299
|
+
return StupidSandbox
|
300
|
+
if used_sandbox == 'isolate':
|
301
|
+
return IsolateSandbox
|
302
|
+
return StupidSandbox
|
303
|
+
|
304
|
+
|
305
|
+
def get_mapped_commands(
|
306
|
+
commands: List[str], mapping: Optional[FileMapping] = None
|
307
|
+
) -> List[str]:
|
308
|
+
mapping = mapping or FileMapping()
|
309
|
+
return [cmd.format(**mapping.model_dump()) for cmd in commands]
|
310
|
+
|
311
|
+
|
312
|
+
def get_mapped_command(command: str, mapping: Optional[FileMapping] = None) -> str:
|
313
|
+
return get_mapped_commands([command], mapping)[0]
|
314
|
+
|
315
|
+
|
316
|
+
def get_sandbox_params_from_config(
|
317
|
+
config: Optional[EnvironmentSandbox],
|
318
|
+
) -> SandboxParams:
|
319
|
+
config = config or EnvironmentSandbox()
|
320
|
+
params = SandboxParams()
|
321
|
+
params.timeout = config.timeLimit
|
322
|
+
params.wallclock_timeout = config.wallTimeLimit
|
323
|
+
params.address_space = config.memoryLimit
|
324
|
+
params.max_processes = config.maxProcesses
|
325
|
+
params.fsize = config.fileSizeLimit
|
326
|
+
if config.preserveEnv:
|
327
|
+
params.preserve_env = True
|
328
|
+
if config.mirrorDirs:
|
329
|
+
for dir in config.mirrorDirs:
|
330
|
+
path = pathlib.Path(dir)
|
331
|
+
params.add_mapped_directory(path)
|
332
|
+
return params
|
333
|
+
|
334
|
+
|
335
|
+
def get_extension(name: str, _: Type[T]) -> Optional[T]:
|
336
|
+
pkg = get_environment()
|
337
|
+
if pkg.extensions is None:
|
338
|
+
return None
|
339
|
+
if hasattr(pkg.extensions, name):
|
340
|
+
return None
|
341
|
+
return getattr(pkg.extensions, name)
|
342
|
+
|
343
|
+
|
344
|
+
def get_extension_or_default(name: str, cls: Type[T]) -> T:
|
345
|
+
return get_extension(name, cls) or cls()
|
rbx/box/extensions.py
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
|
3
|
+
from pydantic import BaseModel, Field
|
4
|
+
|
5
|
+
from rbx.box.packaging.boca.extension import BocaExtension, BocaLanguageExtension
|
6
|
+
|
7
|
+
|
8
|
+
# List of extensions defined in-place.
|
9
|
+
class MacExtension(BaseModel):
|
10
|
+
gpp_alternative: Optional[str] = None
|
11
|
+
|
12
|
+
|
13
|
+
# Extension abstractions.
|
14
|
+
class Extensions(BaseModel):
|
15
|
+
mac: Optional[MacExtension] = Field(
|
16
|
+
None, description='Extension for setting mac-only configuration.'
|
17
|
+
)
|
18
|
+
boca: Optional[BocaExtension] = Field(
|
19
|
+
None, description='Environment-level extensions for BOCA packaging.'
|
20
|
+
)
|
21
|
+
|
22
|
+
|
23
|
+
class LanguageExtensions(BaseModel):
|
24
|
+
boca: Optional[BocaLanguageExtension] = Field(
|
25
|
+
None, description='Language-level extensions for BOCA packaging.'
|
26
|
+
)
|