rbx.cp 0.13.3__py3-none-any.whl → 0.13.4__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.
Files changed (53) hide show
  1. rbx/annotations.py +5 -5
  2. rbx/box/checkers.py +24 -13
  3. rbx/box/cli.py +1 -4
  4. rbx/box/contest/build_contest_statements.py +16 -3
  5. rbx/box/contest/schema.py +1 -2
  6. rbx/box/fields.py +25 -1
  7. rbx/box/generators.py +5 -2
  8. rbx/box/global_package.py +5 -1
  9. rbx/box/header.py +19 -11
  10. rbx/box/package.py +3 -1
  11. rbx/box/presets/__init__.py +2 -2
  12. rbx/box/schema.py +4 -25
  13. rbx/box/statements/build_statements.py +5 -1
  14. rbx/box/statements/builders.py +7 -7
  15. rbx/box/statements/schema.py +11 -2
  16. rbx/box/testcase_utils.py +2 -0
  17. rbx/box/testing/__init__.py +0 -0
  18. rbx/box/testing/testing_package.py +241 -0
  19. rbx/box/testing/testing_preset.py +36 -0
  20. rbx/box/testing/testing_shared.py +81 -0
  21. rbx/box/validators.py +2 -1
  22. rbx/grading/caching.py +3 -2
  23. rbx/resources/presets/default/shared/contest_template.rbx.tex +1 -1
  24. rbx/resources/presets/default/shared/problem_template.rbx.tex +5 -1
  25. rbx/testing_utils.py +1 -1
  26. rbx/utils.py +8 -0
  27. {rbx_cp-0.13.3.dist-info → rbx_cp-0.13.4.dist-info}/METADATA +2 -1
  28. {rbx_cp-0.13.3.dist-info → rbx_cp-0.13.4.dist-info}/RECORD +31 -49
  29. rbx/box/conftest.py +0 -42
  30. rbx/box/generators_test.py +0 -67
  31. rbx/box/lazy_importing_test.py +0 -25
  32. rbx/box/solutions_test.py +0 -47
  33. rbx/box/validators_test.py +0 -15
  34. rbx/checker.py +0 -128
  35. rbx/clone.py +0 -197
  36. rbx/conftest.py +0 -38
  37. rbx/create.py +0 -37
  38. rbx/edit.py +0 -24
  39. rbx/grading/conftest.py +0 -33
  40. rbx/grading/steps_with_caching_run_test.py +0 -707
  41. rbx/grading_utils.py +0 -148
  42. rbx/hydration.py +0 -101
  43. rbx/main.py +0 -118
  44. rbx/metadata.py +0 -105
  45. rbx/run.py +0 -45
  46. rbx/schema.py +0 -64
  47. rbx/submit.py +0 -61
  48. rbx/test.py +0 -349
  49. rbx/testcase.py +0 -70
  50. rbx/testcase_rendering.py +0 -79
  51. {rbx_cp-0.13.3.dist-info → rbx_cp-0.13.4.dist-info}/LICENSE +0 -0
  52. {rbx_cp-0.13.3.dist-info → rbx_cp-0.13.4.dist-info}/WHEEL +0 -0
  53. {rbx_cp-0.13.3.dist-info → rbx_cp-0.13.4.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,241 @@
1
+ import pathlib
2
+ from dataclasses import dataclass
3
+ from typing import Dict, List, Optional
4
+
5
+ from rbx import console, utils
6
+ from rbx.box.fields import Primitive
7
+ from rbx.box.schema import (
8
+ CodeItem,
9
+ ExpectedOutcome,
10
+ Generator,
11
+ Interactor,
12
+ Package,
13
+ Solution,
14
+ TaskType,
15
+ TestcaseGroup,
16
+ )
17
+ from rbx.box.testing.testing_preset import TestingPreset
18
+ from rbx.box.testing.testing_shared import PathOrStr, TestingShared
19
+ from rbx.grading.steps import Evaluation
20
+ from rbx.testing_utils import print_directory_tree
21
+
22
+
23
+ @dataclass
24
+ class TestcaseArtifacts:
25
+ output: Optional[str] = None
26
+ log: Optional[Evaluation] = None
27
+ interactor_input: Optional[str] = None
28
+ interactor_output: Optional[str] = None
29
+ interactor_pipes: Optional[str] = None
30
+
31
+
32
+ class TestingPackage(TestingShared):
33
+ def __init__(self, root: PathOrStr):
34
+ super().__init__(root)
35
+ self._yml = None
36
+
37
+ self.initialize()
38
+ self.preset = self.initialize_preset()
39
+
40
+ @property
41
+ def yml_path(self) -> pathlib.Path:
42
+ return self.root / 'problem.rbx.yml'
43
+
44
+ def initialize(self):
45
+ if not self.yml_path.exists():
46
+ self.yml_path.parent.mkdir(parents=True, exist_ok=True)
47
+ self.yml_path.touch()
48
+ self.yml_path.write_text(
49
+ utils.model_to_yaml(
50
+ Package(name='test-problem', timeLimit=1000, memoryLimit=256)
51
+ )
52
+ )
53
+
54
+ def initialize_preset(self) -> TestingPreset:
55
+ preset_path = self.root / '.local.rbx'
56
+ preset_path.mkdir(parents=True, exist_ok=True)
57
+ return TestingPreset(preset_path)
58
+
59
+ def print_tree(self):
60
+ print_directory_tree(self.root)
61
+
62
+ def print_yml(self):
63
+ console.console.print(self.yml_path.read_text(), highlight=True)
64
+
65
+ def print_debug(self):
66
+ self.print_yml()
67
+ self.print_tree()
68
+
69
+ @property
70
+ def yml(self) -> Package:
71
+ if self._yml is None:
72
+ self._yml = utils.model_from_yaml(Package, self.yml_path.read_text())
73
+ return self._yml
74
+
75
+ def save(self):
76
+ self.yml_path.write_text(utils.model_to_yaml(self.yml))
77
+
78
+ def set_type(self, type: TaskType):
79
+ self.yml.type = type
80
+ self.save()
81
+
82
+ def add_solution(
83
+ self,
84
+ path: PathOrStr,
85
+ outcome: ExpectedOutcome,
86
+ language: Optional[str] = None,
87
+ ):
88
+ self.yml.solutions = self.yml.solutions + [
89
+ Solution(path=pathlib.Path(path), language=language, outcome=outcome)
90
+ ]
91
+ self.save()
92
+ return self.add_file(path)
93
+
94
+ def add_generator(
95
+ self,
96
+ path: PathOrStr,
97
+ language: Optional[str] = None,
98
+ alias: Optional[str] = None,
99
+ src: Optional[PathOrStr] = None,
100
+ ):
101
+ if alias is not None:
102
+ self.yml.generators = self.yml.generators + [
103
+ Generator(path=pathlib.Path(path), language=language, name=alias)
104
+ ]
105
+ self.save()
106
+ return self.add_file(path, src=src)
107
+
108
+ def set_validator(
109
+ self,
110
+ path: PathOrStr,
111
+ language: Optional[str] = None,
112
+ src: Optional[PathOrStr] = None,
113
+ ):
114
+ self.yml.validator = CodeItem(path=pathlib.Path(path), language=language)
115
+ self.save()
116
+ return self.add_file(path, src=src)
117
+
118
+ def set_checker(
119
+ self,
120
+ path: PathOrStr,
121
+ language: Optional[str] = None,
122
+ src: Optional[PathOrStr] = None,
123
+ ):
124
+ self.yml.checker = CodeItem(path=pathlib.Path(path), language=language)
125
+ self.save()
126
+ return self.add_file(path, src=src)
127
+
128
+ def set_interactor(
129
+ self,
130
+ path: PathOrStr,
131
+ language: Optional[str] = None,
132
+ src: Optional[PathOrStr] = None,
133
+ ):
134
+ self.yml.interactor = Interactor(path=pathlib.Path(path), language=language)
135
+ self.save()
136
+ return self.add_file(path, src=src)
137
+
138
+ def set_var(self, name: str, value: Primitive):
139
+ self.yml.vars[name] = value
140
+ self.save()
141
+
142
+ def set_vars(self, vars: Dict[str, Primitive]):
143
+ self.yml.vars = vars
144
+ self.save()
145
+
146
+ def add_testplan(self, name: str, src: Optional[PathOrStr] = None):
147
+ path = self.add_file(pathlib.Path('testplan') / f'{name}.txt', src)
148
+ return path
149
+
150
+ def add_testscript(self, name: str, src: Optional[PathOrStr] = None):
151
+ path = self.add_file(pathlib.Path('testplan') / f'{name}.py', src)
152
+ return path
153
+
154
+ def add_testgroup_from_glob(
155
+ self,
156
+ name: str,
157
+ glob: str,
158
+ validator: Optional[PathOrStr] = None,
159
+ extra_validators: Optional[List[PathOrStr]] = None,
160
+ ):
161
+ self.yml.testcases = self.yml.testcases + [
162
+ TestcaseGroup(
163
+ name=name,
164
+ testcaseGlob=glob,
165
+ validator=CodeItem(path=pathlib.Path(validator)) if validator else None,
166
+ extraValidators=[
167
+ CodeItem(path=pathlib.Path(v)) for v in extra_validators
168
+ ]
169
+ if extra_validators
170
+ else [],
171
+ )
172
+ ]
173
+ self.save()
174
+
175
+ def add_testgroup_from_plan(
176
+ self,
177
+ name: str,
178
+ plan: str,
179
+ validator: Optional[PathOrStr] = None,
180
+ extra_validators: Optional[List[PathOrStr]] = None,
181
+ ):
182
+ plan_path = self.add_testplan(name)
183
+ plan_path.write_text(plan)
184
+ self.yml.testcases = self.yml.testcases + [
185
+ TestcaseGroup(
186
+ name=name,
187
+ generatorScript=CodeItem(path=plan_path),
188
+ validator=CodeItem(path=pathlib.Path(validator)) if validator else None,
189
+ extraValidators=[
190
+ CodeItem(path=pathlib.Path(v)) for v in extra_validators
191
+ ]
192
+ if extra_validators
193
+ else [],
194
+ )
195
+ ]
196
+ self.save()
197
+
198
+ def add_testgroup_from_script(
199
+ self,
200
+ name: str,
201
+ script: str,
202
+ validator: Optional[PathOrStr] = None,
203
+ extra_validators: Optional[List[PathOrStr]] = None,
204
+ ):
205
+ script_path = self.add_testscript(name)
206
+ script_path.write_text(script)
207
+ self.yml.testcases = self.yml.testcases + [
208
+ TestcaseGroup(
209
+ name=name,
210
+ generatorScript=CodeItem(path=script_path),
211
+ validator=CodeItem(path=pathlib.Path(validator)) if validator else None,
212
+ extraValidators=[
213
+ CodeItem(path=pathlib.Path(v)) for v in extra_validators
214
+ ]
215
+ if extra_validators
216
+ else [],
217
+ )
218
+ ]
219
+ self.save()
220
+
221
+ def get_build_testgroup_path(self, name: str) -> pathlib.Path:
222
+ return self.root / 'build' / 'tests' / name
223
+
224
+ def get_testcase_contents(self, path: pathlib.Path) -> TestcaseArtifacts:
225
+ contents = TestcaseArtifacts()
226
+ output_path = path.with_suffix('.out')
227
+ if output_path.exists():
228
+ contents.output = output_path.read_text()
229
+ log_path = path.with_suffix('.log')
230
+ if log_path.exists():
231
+ contents.log = Evaluation.model_validate_json(log_path.read_text())
232
+ interactor_input_path = path.with_suffix('.pin')
233
+ if interactor_input_path.exists():
234
+ contents.interactor_input = interactor_input_path.read_text()
235
+ interactor_output_path = path.with_suffix('.pout')
236
+ if interactor_output_path.exists():
237
+ contents.interactor_output = interactor_output_path.read_text()
238
+ interactor_pipes_path = path.with_suffix('.pio')
239
+ if interactor_pipes_path.exists():
240
+ contents.interactor_pipes = interactor_pipes_path.read_text()
241
+ return contents
@@ -0,0 +1,36 @@
1
+ import pathlib
2
+
3
+ from rbx import utils
4
+ from rbx.box.presets.schema import Preset
5
+ from rbx.box.testing.testing_shared import PathOrStr, TestingShared
6
+
7
+
8
+ class TestingPreset(TestingShared):
9
+ def __init__(self, root: PathOrStr):
10
+ super().__init__(root)
11
+ self._yml = None
12
+
13
+ def initialize(self):
14
+ if not self.yml_path.exists():
15
+ self.yml_path.parent.mkdir(parents=True, exist_ok=True)
16
+ self.yml_path.touch()
17
+ self.yml_path.write_text(
18
+ utils.model_to_yaml(
19
+ Preset(uri='rsalesc/test-preset', env=pathlib.Path('env.rbx.yml'))
20
+ )
21
+ )
22
+ self.add_from_resources(
23
+ pathlib.Path('env.rbx.yml'), pathlib.Path('presets/default/env.rbx.yml')
24
+ )
25
+
26
+ def yml_path(self) -> pathlib.Path:
27
+ return self.root / 'preset.rbx.yml'
28
+
29
+ @property
30
+ def yml(self) -> Preset:
31
+ if self._yml is None:
32
+ self._yml = utils.model_from_yaml(Preset, self.yml_path.read_text())
33
+ return self._yml
34
+
35
+ def save(self):
36
+ self.yml_path.write_text(utils.model_to_yaml(self.yml))
@@ -0,0 +1,81 @@
1
+ import os
2
+ import pathlib
3
+ import shutil
4
+ import tempfile
5
+ from typing import Optional, Union
6
+
7
+ from rbx import testing_utils, utils
8
+ from rbx.config import get_resources_file
9
+ from rbx.testing_utils import get_testdata_path
10
+
11
+ PathOrStr = Union[os.PathLike, str]
12
+
13
+
14
+ class TestingShared:
15
+ def __init__(self, root: PathOrStr):
16
+ self.root = pathlib.Path(root)
17
+ self._created_tmps = []
18
+ self._old_cwd = None
19
+
20
+ def __enter__(self):
21
+ self._old_cwd = pathlib.Path.cwd()
22
+ os.chdir(self.root)
23
+ testing_utils.clear_all_functools_cache()
24
+ return self
25
+
26
+ def __exit__(self, exc_type, exc_value, traceback):
27
+ if self._old_cwd is not None:
28
+ os.chdir(self._old_cwd)
29
+ self.cleanup()
30
+
31
+ def path(self, path: PathOrStr) -> pathlib.Path:
32
+ return self.root / path
33
+
34
+ def abspath(self, path: PathOrStr) -> pathlib.Path:
35
+ return utils.abspath(self.path(path))
36
+
37
+ def mkdtemp(self) -> pathlib.Path:
38
+ temp_dir = pathlib.Path(tempfile.mkdtemp())
39
+ self._created_tmps.append(temp_dir)
40
+ return temp_dir
41
+
42
+ def cleanup(self):
43
+ for tmp in self._created_tmps:
44
+ shutil.rmtree(tmp)
45
+
46
+ def add_file(
47
+ self, path: PathOrStr, src: Optional[PathOrStr] = None
48
+ ) -> pathlib.Path:
49
+ filename = self.path(path)
50
+ filename.parent.mkdir(parents=True, exist_ok=True)
51
+ if src is not None:
52
+ self.add_from_testdata(path, src)
53
+ else:
54
+ filename.touch()
55
+ return filename
56
+
57
+ def relpath(self, path: PathOrStr) -> pathlib.Path:
58
+ return pathlib.Path(path).relative_to(self.root)
59
+
60
+ def add_from_testdata(self, path: PathOrStr, src: PathOrStr):
61
+ testdata_path = get_testdata_path()
62
+ testdata_file = testdata_path / src
63
+ if testdata_file.is_file():
64
+ shutil.copy(testdata_file, self.path(path))
65
+ elif testdata_file.is_dir():
66
+ shutil.copytree(testdata_file, self.path(path))
67
+ else:
68
+ raise ValueError(f'{testdata_file} is not a file or directory')
69
+
70
+ def add_from_resources(self, path: PathOrStr, src: PathOrStr):
71
+ resources_file = get_resources_file(pathlib.Path(src))
72
+ shutil.copy(resources_file, self.path(path))
73
+
74
+ def exists_file(self, path: PathOrStr) -> bool:
75
+ return self.path(path).exists()
76
+
77
+ def delete_file(self, path: PathOrStr):
78
+ self.path(path).unlink()
79
+
80
+ def copy_from(self, other: 'TestingShared'):
81
+ shutil.copytree(other.root, self.root, dirs_exist_ok=True, symlinks=True)
rbx/box/validators.py CHANGED
@@ -8,7 +8,8 @@ from pydantic import BaseModel
8
8
  from rbx import console
9
9
  from rbx.box import package
10
10
  from rbx.box.code import SanitizationLevel, compile_item, run_item
11
- from rbx.box.schema import CodeItem, Primitive
11
+ from rbx.box.fields import Primitive
12
+ from rbx.box.schema import CodeItem
12
13
  from rbx.box.testcase_extractors import (
13
14
  GenerationTestcaseEntry,
14
15
  extract_generation_testcases_from_groups,
rbx/grading/caching.py CHANGED
@@ -8,6 +8,7 @@ import tempfile
8
8
  from typing import Any, Dict, List, Optional
9
9
 
10
10
  from pydantic import BaseModel
11
+ from sqlitedict import SqliteDict
11
12
 
12
13
  from rbx import console
13
14
  from rbx.grading import grading_context
@@ -334,9 +335,9 @@ class DependencyCache:
334
335
  def __init__(self, root: pathlib.Path, cacher: FileCacher):
335
336
  self.root = root
336
337
  self.cacher = cacher
337
- self.db = shelve.open(self._cache_name())
338
+ self.db = SqliteDict(self._cache_name(), autocommit=True)
338
339
  tmp_dir = pathlib.Path(tempfile.mkdtemp())
339
- self.transient_db = shelve.open(str(tmp_dir / '.cache_db'))
340
+ self.transient_db = SqliteDict(str(tmp_dir / '.cache_db'), autocommit=True)
340
341
  atexit.register(lambda: self.db.close())
341
342
  atexit.register(lambda: self.transient_db.close())
342
343
  atexit.register(lambda: shutil.rmtree(tmp_dir))
@@ -44,7 +44,7 @@
44
44
  %- endif
45
45
  }
46
46
  %- endif
47
- %- if problem.blocks.editorial is nonnull and vars.editorial is truthy
47
+ %- if problem.blocks.editorial is nonnull and problem.vars.editorial is truthy
48
48
  \subsection*{\strSolution}
49
49
  \VAR{problem.blocks.editorial}
50
50
  %- endif
@@ -53,5 +53,9 @@
53
53
  \VAR{problem.blocks.notes}
54
54
  %- endif
55
55
  }
56
- \end{document}
57
56
 
57
+ %- if problem.blocks.editorial is nonnull and problem.vars.editorial is truthy
58
+ \subsection*{\strSolution}
59
+ \VAR{problem.blocks.editorial}
60
+ %- endif
61
+ \end{document}
rbx/testing_utils.py CHANGED
@@ -47,7 +47,7 @@ def walk_directory(
47
47
  style=style,
48
48
  guide_style=style,
49
49
  )
50
- walk_directory(path, branch)
50
+ walk_directory(path, branch, show_hidden=show_hidden)
51
51
  else:
52
52
  text_filename = rich.text.Text(path.name, 'green')
53
53
  text_filename.highlight_regex(r'\..*$', 'bold red')
rbx/utils.py CHANGED
@@ -7,6 +7,7 @@ import os.path
7
7
  import pathlib
8
8
  import resource
9
9
  import subprocess
10
+ import sys
10
11
  from typing import Any, Optional, Type, TypeVar
11
12
 
12
13
  import rich
@@ -40,6 +41,13 @@ def abspath(path: pathlib.Path) -> pathlib.Path:
40
41
  return pathlib.Path(os.path.abspath(path))
41
42
 
42
43
 
44
+ def relpath(path: pathlib.Path, base: pathlib.Path) -> pathlib.Path:
45
+ if sys.version_info >= (3, 12):
46
+ return path.relative_to(base, walk_up=True)
47
+ else:
48
+ return pathlib.Path(os.path.relpath(path, base))
49
+
50
+
43
51
  def highlight_json_obj(obj: Any) -> text.Text:
44
52
  js = json.dumps(obj)
45
53
  return highlight_str(js)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rbx.cp
3
- Version: 0.13.3
3
+ Version: 0.13.4
4
4
  Summary:
5
5
  Author: Roberto Sales
6
6
  Requires-Python: >=3.9.1,<4.0.0
@@ -40,6 +40,7 @@ Requires-Dist: requests (>=2.32.3,<3.0.0)
40
40
  Requires-Dist: rich (>=13.9.4,<14.0.0)
41
41
  Requires-Dist: ruamel-yaml (>=0.18.14,<0.19.0)
42
42
  Requires-Dist: ruyaml (>=0.91.0,<0.92.0)
43
+ Requires-Dist: sqlitedict (>=2.1.0,<3.0.0)
43
44
  Requires-Dist: syncer (>=2.0.3,<3.0.0)
44
45
  Requires-Dist: textual (>=3.1.1,<4.0.0)
45
46
  Requires-Dist: textual-serve (>=1.1.2,<2.0.0)
@@ -1,20 +1,19 @@
1
1
  rbx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- rbx/annotations.py,sha256=qcJGL_INONSirH7LTrEma5RsweAIbO6QlRHVvRvb9ao,3521
2
+ rbx/annotations.py,sha256=_TkLhgZWiUyon3bonHwUo03ls1jY8LwgcR4bVgtgnc0,3519
3
3
  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=umrTdVAwvsOosBDVvDZ6kq1yWg3Z2Lxp2o1zK-V7BBk,3594
6
6
  rbx/box/cd.py,sha256=_XAzb3kV1NUaaRs8hc9SGDo10O1yh2_gr1EiAKzfUjI,2711
7
- rbx/box/checkers.py,sha256=wjS64fDrEkTjU6f80strt4QEBHPo4FQDh9ijELhOQT0,13016
8
- rbx/box/cli.py,sha256=44QKM2v4ibpIcpzSYsvkAI84VoB-X60ik9A1_68horY,30008
7
+ rbx/box/checkers.py,sha256=1gI9Rplpe0Drr_AvGrwGhT8fXIs7ApucOWBIdVfm72U,13418
8
+ rbx/box/cli.py,sha256=ZcEaMiMsO00S6GwEw2ENhdA2x_X0pcK49BgAChOZ6SQ,29935
9
9
  rbx/box/code.py,sha256=4GChCeUaHjT7stvtPAURbCL1_V238geG3xmXQjbdV20,26708
10
10
  rbx/box/compile.py,sha256=Kzn5mEQu4vb91W9vjyt0DS6cfPJzFLTUoowFj7uHLUo,2539
11
- rbx/box/conftest.py,sha256=sEmciXSeDC-wmrZ1JSxbsUenKNP_VWW32mrCun2pY3I,1070
12
11
  rbx/box/contest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- rbx/box/contest/build_contest_statements.py,sha256=OKf7BQ6DxtY65TpzjhNbY5Bu3wByrxZt7qCqWDXBaNQ,12693
12
+ rbx/box/contest/build_contest_statements.py,sha256=N7TQ8Ki7ZM94sATHploDsSKbY41Xey_FlXclEdCBpJI,13010
14
13
  rbx/box/contest/contest_package.py,sha256=r6BGq3S4Ezj3Ep7pCmtvz3SN44npb2_rKJEoT5lSOqk,2985
15
14
  rbx/box/contest/contest_utils.py,sha256=fsWHG1e65wq9zvRY3tdf32VF0nU1yzGTOBX5yjXiNk4,1102
16
15
  rbx/box/contest/main.py,sha256=e_DjbrwpXTFZQaVWJO7prJyehJ702GkVEAGEraRK6h4,8352
17
- rbx/box/contest/schema.py,sha256=eb7xtyq078YYWYHueximNhyHFINzwgLMFm1j9U3LxBQ,7461
16
+ rbx/box/contest/schema.py,sha256=21kP3v5aPMOjjp832R7Q_QzJirCVKQCSAklT8nnssdk,7435
18
17
  rbx/box/contest/statements.py,sha256=dI3AmaTYfOzyB1uh75ST9se9o_QqXzar4pNkIdC-_G8,3956
19
18
  rbx/box/creation.py,sha256=oTAC11XV2Pw2YAlF_d11Eo7A1fD6ItlpFMpLEzMLyFI,1331
20
19
  rbx/box/deferred.py,sha256=II3X9e87JCOZtmspnHh-n4PFqh-FsH_oc0XJHZ9ZYVQ,691
@@ -22,20 +21,18 @@ rbx/box/download.py,sha256=tLW5gLVeLk0gHMEMwScSoHIXQPkXuPsqXzItsrsnUZY,3070
22
21
  rbx/box/dump_schemas.py,sha256=3j5t47_vJmXj0BCczxDX6ByOcsfolGEDNCBXlPpk86w,593
23
22
  rbx/box/environment.py,sha256=iR-VTNvbW8iNienWKYVnd1xxCuhWml7bYa5FTIZCOY0,13574
24
23
  rbx/box/extensions.py,sha256=Von8kIeXvNFTkGlMRMTvL2HIHPwlkuiMswr-ydbGV1w,519
25
- rbx/box/fields.py,sha256=lc1OHpo_AC8RxzNasipULGkRmToAiXBGzWDeb14L_ss,1092
24
+ rbx/box/fields.py,sha256=rai4gE95mavvRPBLgnMj2jG5b2W76fvGuFQRXO0O4fM,1792
26
25
  rbx/box/formatting.py,sha256=i3vXHpo_L_VpVPxOe4wHlai1WhlDJlfxUexS9DC0Szg,1249
27
- rbx/box/generators.py,sha256=4iO5QNy_UzybhO5GhSyts9ZsLld-Hp38Xl-CHjrqivY,16149
28
- rbx/box/generators_test.py,sha256=J7aBfuJhU84MWDWzgReRoOuQw_hVa09B8gTKAvL2XVo,1987
26
+ rbx/box/generators.py,sha256=uSm56nzLaNs0ZdMiV46MeweBRp_-vilzaDpm7w1cu_c,16216
29
27
  rbx/box/git_utils.py,sha256=VlUgzuHOCnrjjiJQnDB32qDHbHw_zkwgA7wm4bloibc,750
30
- rbx/box/global_package.py,sha256=OMnvqY8VQlP9YVSZwH5LCVkTsE7zNIhhRcslIWktkQc,2016
31
- rbx/box/header.py,sha256=2XMsGfX3GTMPFRs6cPFUC3qncyJKKZj-UT6-KJ7jWQg,2176
28
+ rbx/box/global_package.py,sha256=8Rdq-TfE5Bc4xznLYtL1TQUH_H3SveNydiHmUcPqb5o,2106
29
+ rbx/box/header.py,sha256=c70wxz2fWMCEv3bdjd5Gsau7o3NmXUqbVZlnSHSllaQ,2385
32
30
  rbx/box/lang.py,sha256=CSD-yxFUC3LWdGpv4IVFOLdgONc_JbsI45BEN3bjaFw,888
33
31
  rbx/box/lazy_importing_main.py,sha256=6Z8As7qVFFT619xHH9Xt8VCH57NjC4aDxfAgkWiUwT8,116
34
- rbx/box/lazy_importing_test.py,sha256=B0-b3y_DkxEmtVfu4NfmVsgVdFl6kRCsEL6GLMHJISo,628
35
32
  rbx/box/linting.py,sha256=wRE0hKCduTBHZYBFmmis_d9AMTsDu0Q-AjByCeTnkrY,3187
36
33
  rbx/box/main.py,sha256=a8CYi77kOywPFly4-ucEIJLXQW-1NFp91kK2fA42YTE,86
37
34
  rbx/box/naming.py,sha256=pOG37X_wQM9CCSYwJIUf-b-ZHEs_nchO7wQEdP_quJg,1367
38
- rbx/box/package.py,sha256=VyG7TZKYGeqzilPkLs8rbJDa1kTIXfrZADequnJvyE4,15110
35
+ rbx/box/package.py,sha256=u88u75RIfFd6WjPcCHzJzywkp9-I9e2Q-hYHjtEcNes,15159
39
36
  rbx/box/packaging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
37
  rbx/box/packaging/boca/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
38
  rbx/box/packaging/boca/extension.py,sha256=EQALNEOv4zVDXSKs_dk11n92y7cBZVn8TogIK683lE0,890
@@ -52,26 +49,25 @@ rbx/box/packaging/polygon/polygon_api.py,sha256=mPKEqiwANJ1nr-JhOgzGMaDhnbljsAgz
52
49
  rbx/box/packaging/polygon/test.py,sha256=bgEju5PwudgyfwxXJagm8fM6CJVlWM6l_-2q1V-oKaQ,3069
53
50
  rbx/box/packaging/polygon/upload.py,sha256=W9LcEe2D2ySOdyXETp529lP5BtB4GyOUD2lLPbSzCjE,13548
54
51
  rbx/box/packaging/polygon/xml_schema.py,sha256=TSl4BWwMWv7V07BKJ56mcLXNr_3zlRgNmqN2q-wnk4M,3128
55
- rbx/box/presets/__init__.py,sha256=L6fy_hetXnB8Eo_MO3oadv_ce2hwVW2J-BJm9CooEdA,33432
52
+ rbx/box/presets/__init__.py,sha256=Vm9Xievtn1fbFMHubPh6Ngz-GvMx3ycfx15tkvwcvfA,33421
56
53
  rbx/box/presets/fetch.py,sha256=900aq9S8e12TlgSenG0iHgtF4OWgqavZsptgI_a1YKM,2508
57
54
  rbx/box/presets/lock_schema.py,sha256=8PKL7UMX4dkdVpCPLwYtaNIIrZpAfHGvTfnF8bRFedM,1708
58
55
  rbx/box/presets/schema.py,sha256=iOGWHqJ9Z-ljQV8ljOjQMuCwqJQLJKm_pYX9cLjZbmE,2432
59
56
  rbx/box/remote.py,sha256=PsJ4i3suQEr3cxiKk4nCho98QBGs5b2v8_TEvn_nE-o,5204
60
57
  rbx/box/retries.py,sha256=BZsi4sYBjm3VK5zb_pBQSYQuKo3ZntmtEFoVPZHg4QI,4982
61
58
  rbx/box/sanitizers/warning_stack.py,sha256=6-rr3dkMq6MpfjrVZ8lSQjF4RZ5YzZSAPMzHCfm-6h4,2876
62
- rbx/box/schema.py,sha256=kOWMe0lrAJBEhU5gBAWvhwMHHzWx17PBwThou4zuo1A,18834
59
+ rbx/box/schema.py,sha256=YLziLE5X-gI76844cCARHo0EmnUZSpr_ngEWzS8M5uM,18187
63
60
  rbx/box/setter_config.py,sha256=WHlWjjdHNoBbCdZqYokctTSxvtPqQXGmrgDHyaK4FKk,4985
64
61
  rbx/box/solutions.py,sha256=CmwLS7EJsZ6_4HqU0bKV8oy2Vd6wKwdQS3R9AH3XNZQ,53696
65
- rbx/box/solutions_test.py,sha256=PX1TQoRzNd9mi1SGsG7WFrpqFgNrNX5Kwt0mkwFdoOA,1749
66
62
  rbx/box/state.py,sha256=MMf3DvfQji0jKEliCHct2Tpp_0epL1tvP8HbHNArQIc,166
67
63
  rbx/box/statements/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
- rbx/box/statements/build_statements.py,sha256=-pUQAS8CEnWqHtpKW6wH338rQg3FKmb9qYxilzcwJFA,12693
69
- rbx/box/statements/builders.py,sha256=Qb_rfkFOqghFZfEf2zPSEoDPc-lCBNb5CcPoOkV7HMk,13747
64
+ rbx/box/statements/build_statements.py,sha256=gzhYVtxO0Pk3AgWr9cOXU7dYo_U-eSk_vpt-Ld8UXg8,12841
65
+ rbx/box/statements/builders.py,sha256=t3q1BX1SaELQVZB0tynuhAs_0UI3yzpUcvsQEEaUE-w,13666
70
66
  rbx/box/statements/expander.py,sha256=sdbMtNcJQCbXGIkFIl9h24pGr77vhFLnM31V5AfuduI,1715
71
67
  rbx/box/statements/joiners.py,sha256=jItNXkAbTjFQpPMgfDMW86n3vMTbaE8sgo9I8Yf4Txg,2886
72
68
  rbx/box/statements/latex.py,sha256=ipTGjL4kjAsnqgiH6Pk1PwKFegBumQP4-y0pFAbNN8I,1584
73
69
  rbx/box/statements/latex_jinja.py,sha256=iMx47ynKMjLNcfymzHV24jtWrRVnit0Va9H8yTfgmiA,10379
74
- rbx/box/statements/schema.py,sha256=5_qrY1KztCLSe4t-rJ7zdv3cBjcaO-FnFc45ZRUotfs,5127
70
+ rbx/box/statements/schema.py,sha256=n1OXbcmte-cGQn7PlSGOzBEYi0gRYUNDSubgYFKxo7I,5429
75
71
  rbx/box/stats.py,sha256=rUAnmp7kTgUvIQ56NLpQaIQkazB37MVcUos5en3xUQw,3258
76
72
  rbx/box/stresses.py,sha256=SV0Hx7SPZZEIhwasWDVpTWuMhWWTjfJs2IEW-H0xJZw,12092
77
73
  rbx/box/stressing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -79,9 +75,13 @@ rbx/box/stressing/finder_parser.py,sha256=PnONJD2yun5X5EmHqkaz-rh3DHhn_BkTPHZrIX
79
75
  rbx/box/stressing/generator_parser.py,sha256=oHZryjR3YohgaSO9WEirQ7b2e-98WgZStF0N99W4Thw,7380
80
76
  rbx/box/tasks.py,sha256=VpmQcOEPvcnQ8fh4nrZGnkGDIoJOHZzHoa9x_HNG1P0,11239
81
77
  rbx/box/testcase_extractors.py,sha256=J43eG7vpxc5nP_2yhrXJODkd4EYlV4WiYVbM6hzipY4,11944
82
- rbx/box/testcase_utils.py,sha256=MzrLq038hp-NvSrfej0_1D98akWq39HxbaFOKi9kOWM,6877
78
+ rbx/box/testcase_utils.py,sha256=HoDr_RxWpfviLd2oTj_m2wg1e4XaY9LD-QBqx_QjDI0,6899
83
79
  rbx/box/testcases/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
80
  rbx/box/testcases/main.py,sha256=_I7h_obRcpNLRQ6dDJDIE5NAvTyn5nBOhdsBhRA_PvU,5442
81
+ rbx/box/testing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
+ rbx/box/testing/testing_package.py,sha256=Z0yzwb5w6CKItDH1-yLZaj_MQ1LdJggRTZwvLmPWSXQ,7740
83
+ rbx/box/testing/testing_preset.py,sha256=7TxfL4fT9JetRMRkQ3Iko99N5gzfKz8_lPM0rkkQx_k,1135
84
+ rbx/box/testing/testing_shared.py,sha256=rX7w5VrCzf4l9zYhq3eFW1iHaWDLU-Xkn5oCjnAavhA,2558
85
85
  rbx/box/tooling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
86
86
  rbx/box/tooling/boca/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
87
87
  rbx/box/tooling/boca/main.py,sha256=knl1rpaHIwA63KkzMJMZQrejzMpbTPBhYqGx1IpuNm4,289
@@ -114,18 +114,11 @@ rbx/box/ui/widgets/rich_log_box.py,sha256=mF565c_Y3RYUZ_GJEFj5Eb86SFjsib31wE5qu1
114
114
  rbx/box/ui/widgets/test_output_box.py,sha256=yqeAb-JFvVx1Q7w_qJbDMWQigyGy4ofGECDxQ7P0_2s,3864
115
115
  rbx/box/ui/widgets/two_sided_test_output_box.py,sha256=L-ORiDwd6CP5DFpavrKGBaX0ZHkSoQqbJrGZ4BdFUWc,2289
116
116
  rbx/box/unit.py,sha256=oIXbQDidrt-DlDjhM1C-WW2jBr7xjsZrRBO6YXP3sJo,7891
117
- rbx/box/validators.py,sha256=oqlNhw7jivbbH5l8g3xwihPRy76AM7MA3G4A8nyI_V0,10416
118
- rbx/box/validators_test.py,sha256=WY4Ho-wlsPHc0YNuz0KFVd6KQ9ouuiou3w5_zMOZ4Fs,362
119
- rbx/checker.py,sha256=pj1jO3my48ru-qugbER5onccANCjoR0-PaFe3H3VGEY,4118
120
- rbx/clone.py,sha256=wpHyED0_7ST7LD3vj7HjXhzqEzlwh6dRQvKQVDYhGeU,6744
117
+ rbx/box/validators.py,sha256=h7KPR1MHfZ-P4CH32r9mFOLT4PrH_rFHoFtUEC9KODY,10442
121
118
  rbx/config.py,sha256=Tj0NHSf13fXxbNpif5C4qnaL1k3S-G87OnzuykEAcNQ,8463
122
- rbx/conftest.py,sha256=ouilbOIpvX8jTEdCAiWT85CbdBQKUUf41BjmDI82u-Y,967
123
119
  rbx/console.py,sha256=X8EJy68OROgh6ao3ZcUjZm5Y56VFMzen58ywAuQ7pAU,990
124
- rbx/create.py,sha256=ezUq9KiSA-88ASd8CtjWXw8UB4LCaQ3Gib3OgvsLK-Q,986
125
- rbx/edit.py,sha256=Zqnx_Pt06ijCxV-pZKGCJhjKB-nVO0QCM6xSBwPWGoE,798
126
120
  rbx/grading/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
127
- rbx/grading/caching.py,sha256=Inu9IYtjO6reg7XGCP44AcaJ5Ax1McfkfNwcpjTCzrw,15376
128
- rbx/grading/conftest.py,sha256=820Uw3AE-dwAfwLhXjgq_PixpDI1-JEXsOPYf4VT5H8,971
121
+ rbx/grading/caching.py,sha256=L2Q3C_0LN84hFrIZOGN9FTxq1YdP4Lh3X2PwVQ4tXUE,15442
129
122
  rbx/grading/debug_context.py,sha256=kuAXEI8yRG8xfhS9WKKIRh9X0e5JUD8zvl_cpczJTC8,699
130
123
  rbx/grading/grading_context.py,sha256=TaRyLwPkkxvspQIFUFk8Ok0T8EST2pHMMNoVDx9lbFU,3416
131
124
  rbx/grading/judge/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -144,11 +137,6 @@ rbx/grading/processing_context.py,sha256=Jg9kNnkH3hi2hiE6Gh23QwS89r9Zj230NMl1CUE
144
137
  rbx/grading/profiling.py,sha256=OEdtoAzjYjLfi-QI5Ke7tLZzJeqvGpMB2utQBNuH3E4,3369
145
138
  rbx/grading/steps.py,sha256=JlR72UvEdvJGFZGA0Jd_2qUoEnElhiIOQAzbUrOhidk,30185
146
139
  rbx/grading/steps_with_caching.py,sha256=b6NVZN46IG2r49uQ6u19Jj6AJ_nQFO6_pcKq4dWTwuQ,4579
147
- rbx/grading/steps_with_caching_run_test.py,sha256=Ldrs1VS01TWYpqg1x9LeiF7_TejsE_suL3y1MI5pAlU,26599
148
- rbx/grading_utils.py,sha256=lL2KtSkOsMElqrRoApQTbFcqVOeHVWUDTMCa3IsLpC4,4484
149
- rbx/hydration.py,sha256=WqbgIfCZNwqspVhMuUlx8-sNOYhq_ZWbeZnkcetuAZI,3669
150
- rbx/main.py,sha256=pFZreQhcoq-vIvWuVVeJEa8s_ka24dxF0WmaasarscE,2865
151
- rbx/metadata.py,sha256=4eIHWlwwq-eAbpRDZkCovcGMbwOVVy-5JMmbLtk429w,3116
152
140
  rbx/providers/__init__.py,sha256=gHXg1BTiXJ_0Z_HoVTZrqhi5IIZ57Dhy0pt7K2ETbA4,1378
153
141
  rbx/providers/codeforces.py,sha256=HWQN3Zb9UfXgCfwcNMEk6m1HoXQ-UE2odVfZoPukyCg,2294
154
142
  rbx/providers/provider.py,sha256=CNRB-uJZkNFIWv8xhW2s8PY9EwUSK8Ey1Yvxk4YLvcg,688
@@ -226,24 +214,18 @@ rbx/resources/presets/default/problem/testplan/random.py,sha256=XclCB6pw9NT1ahu9
226
214
  rbx/resources/presets/default/problem/testplan/random.txt,sha256=XDrow4p79owKnjqyvaIVSNTXwWQDe3X1k_9-2zH43O8,34
227
215
  rbx/resources/presets/default/problem/validator.cpp,sha256=I_Vs12xQnJnwkRtCu4EjazdaERms4GktZhME7zGaQjU,337
228
216
  rbx/resources/presets/default/problem/wcmp.cpp,sha256=gbjJe3Vf9-YzHCEqBUq30aI3jMZXhqBDn3jjecYOn-w,902
229
- rbx/resources/presets/default/shared/contest_template.rbx.tex,sha256=-sExA0H7vo08I6P0dT78_xNN5Q9wiu6KZzB75s12Xm4,1293
217
+ rbx/resources/presets/default/shared/contest_template.rbx.tex,sha256=bEbsVybLJ18V7Ez1i5g8H6-5Aru2Bk1qPsDly_c26lw,1301
230
218
  rbx/resources/presets/default/shared/icpc.sty,sha256=04feEwL7LRRvUFopwVAVjxdTvzE5gQtFsSkm6iJ5hLo,8042
231
- rbx/resources/presets/default/shared/problem_template.rbx.tex,sha256=AjziXNWluAGsQiPQ2r477RkrMpNQJ1kcgidU8T_C4KA,1281
219
+ rbx/resources/presets/default/shared/problem_template.rbx.tex,sha256=SfBxSwz1sVBUV5P6JmROXvlIqRfzt7muJwGtZhtCM7E,1427
232
220
  rbx/resources/templates/rbx.h,sha256=Iwtmr2gdDYmZ2VlIurmleBb_uEpriWd4EX0dJta8xUA,2179
233
221
  rbx/resources/templates/template.cpp,sha256=xXWpWo7fa7HfmPNqkmHcmv3i46Wm0ZL-gPmkRfGvLn4,317
234
- rbx/run.py,sha256=8WsEAdj7FwYSc9itfJ977n5HN5CYN63T__HRYI6IB1A,1515
235
- rbx/schema.py,sha256=qcxuuxUJ0KwHR03CEYvdoP1SYW7yes3QyuI_0lnVMl0,1494
236
- rbx/submit.py,sha256=7AMqiPyfQRdeO8UPRZqs_gQ88ws5lJrJ_0u40PoVJbQ,2246
237
222
  rbx/submitors/__init__.py,sha256=sVcRNnuKMZatmpGkQURaEVHK-MfU2U0nH4nOatuqywE,620
238
223
  rbx/submitors/codeforces.py,sha256=s8c7sXfm5k76SKMC8g0Y93-RRf8wY2uWbBtA8ODD5eM,4030
239
224
  rbx/submitors/submitor.py,sha256=8q-Hbdahxt30ciT_R9j_xF6lEPUh9IcfAUnzjQjbvHU,457
240
- rbx/test.py,sha256=lrjIWESMedaDLX_knikPsJT322oI2nvy8weCslEuHLU,11810
241
- rbx/testcase.py,sha256=yKOq3CAJZ1YTmInvnoIs0u1iJnRj_X85XiWbLI-p9d8,1951
242
- rbx/testcase_rendering.py,sha256=nfmv6dSEqd4aR3TsaODwkKGK6AXty_DDKtWf_ejiQpI,2084
243
- rbx/testing_utils.py,sha256=x_PqD8Zd2PkN91NxVHUnSTs044-1WK5KKtttKQBXpFs,2083
244
- rbx/utils.py,sha256=SZW_bqU33CkHRrInnGN36QfQA0dQx2zdWO32fxlDy-w,5264
245
- rbx_cp-0.13.3.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
246
- rbx_cp-0.13.3.dist-info/METADATA,sha256=5q0W492nuXldJJbMFEZPSpsjwsuIF2AN0q-WOxo7RR4,4616
247
- rbx_cp-0.13.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
248
- rbx_cp-0.13.3.dist-info/entry_points.txt,sha256=qBTLBOeifT1F00LWaEewRRE_jQPgvH7BUdJfZ-dYsFU,57
249
- rbx_cp-0.13.3.dist-info/RECORD,,
225
+ rbx/testing_utils.py,sha256=6wvLoGVZfCC-X-y1obf65F3P3HE9CAYbX6tWJXVd1HI,2108
226
+ rbx/utils.py,sha256=lw7NTWtzZbx7Z_Lkg-hGqrUFRAko5y982cw-Wnrtuqs,5501
227
+ rbx_cp-0.13.4.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
228
+ rbx_cp-0.13.4.dist-info/METADATA,sha256=cNYhPo93kZ31r_Cy7zbw6HcKc89Sn4Kk-aYerbrtvGk,4659
229
+ rbx_cp-0.13.4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
230
+ rbx_cp-0.13.4.dist-info/entry_points.txt,sha256=qBTLBOeifT1F00LWaEewRRE_jQPgvH7BUdJfZ-dYsFU,57
231
+ rbx_cp-0.13.4.dist-info/RECORD,,