rbx.cp 0.5.42__py3-none-any.whl → 0.5.45__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 (49) hide show
  1. rbx/box/cli.py +8 -0
  2. rbx/box/code.py +76 -3
  3. rbx/box/main.py +0 -4
  4. rbx/box/package.py +16 -2
  5. rbx/box/state.py +1 -0
  6. rbx/box/tasks.py +20 -1
  7. rbx/grading/judge/cacher.py +0 -4
  8. rbx/grading/judge/digester.py +0 -3
  9. rbx/grading/judge/sandbox.py +7 -0
  10. rbx/grading/judge/sandboxes/stupid_sandbox.py +10 -1
  11. rbx/grading/judge/sandboxes/timeit.py +109 -5
  12. rbx/grading/judge/storage.py +0 -4
  13. rbx/main.py +0 -4
  14. {rbx_cp-0.5.42.dist-info → rbx_cp-0.5.45.dist-info}/METADATA +1 -2
  15. {rbx_cp-0.5.42.dist-info → rbx_cp-0.5.45.dist-info}/RECORD +18 -49
  16. {rbx_cp-0.5.42.dist-info → rbx_cp-0.5.45.dist-info}/WHEEL +1 -1
  17. rbx/testdata/box1/gen1.cpp +0 -7
  18. rbx/testdata/box1/gen2.cpp +0 -9
  19. rbx/testdata/box1/genScript.py +0 -2
  20. rbx/testdata/box1/hard-tle.sol.cpp +0 -26
  21. rbx/testdata/box1/ole.cpp +0 -17
  22. rbx/testdata/box1/problem.rbx.yml +0 -39
  23. rbx/testdata/box1/re.sol.cpp +0 -23
  24. rbx/testdata/box1/sol.cpp +0 -22
  25. rbx/testdata/box1/tests/1.in +0 -1
  26. rbx/testdata/box1/tle-and-incorrect.sol.cpp +0 -33
  27. rbx/testdata/box1/tle.sol.cpp +0 -35
  28. rbx/testdata/box1/validator.cpp +0 -11
  29. rbx/testdata/box1/wa.sol.cpp +0 -22
  30. rbx/testdata/caching/executable.py +0 -1
  31. rbx/testdata/compatible +0 -0
  32. rbx/testdata/interactive/checker.cpp +0 -21
  33. rbx/testdata/interactive/gen.cpp +0 -11
  34. rbx/testdata/interactive/interactor.cpp +0 -63
  35. rbx/testdata/interactive/problem.rbx.yml +0 -40
  36. rbx/testdata/interactive/sols/af_ac_pe.cpp +0 -75
  37. rbx/testdata/interactive/sols/af_ac_re.cpp +0 -76
  38. rbx/testdata/interactive/sols/af_ac_too_many_iter.cpp +0 -72
  39. rbx/testdata/interactive/sols/af_inf_cout_with_flush.cpp +0 -79
  40. rbx/testdata/interactive/sols/af_inf_cout_without_flush.cpp +0 -78
  41. rbx/testdata/interactive/sols/af_ml.cpp +0 -78
  42. rbx/testdata/interactive/sols/af_tl_after_ans.cpp +0 -74
  43. rbx/testdata/interactive/sols/af_wa.cpp +0 -74
  44. rbx/testdata/interactive/sols/interactive-binary-search_mm_naive_cin.cpp +0 -17
  45. rbx/testdata/interactive/sols/main.cpp +0 -26
  46. rbx/testdata/interactive/testplan.txt +0 -6
  47. rbx/testdata/interactive/validator.cpp +0 -16
  48. {rbx_cp-0.5.42.dist-info → rbx_cp-0.5.45.dist-info}/LICENSE +0 -0
  49. {rbx_cp-0.5.42.dist-info → rbx_cp-0.5.45.dist-info}/entry_points.txt +0 -0
rbx/box/cli.py CHANGED
@@ -103,6 +103,13 @@ def main(
103
103
  help='Whether to compile and run testlib components with sanitizers enabled. '
104
104
  'If you want to run the solutions with sanitizers enabled, use the "-s" flag in the corresponding run command.',
105
105
  ),
106
+ debug_logs: bool = typer.Option(
107
+ False,
108
+ '--debug-logs',
109
+ '--debug',
110
+ '-d',
111
+ help='Whether to save extra debug logs along with the evaluation results.',
112
+ ),
106
113
  ):
107
114
  state.STATE.run_through_cli = True
108
115
  state.STATE.sanitized = sanitized
@@ -111,6 +118,7 @@ def main(
111
118
  '[warning]Sanitizers are running just for testlib components.\n'
112
119
  'If you want to run the solutions with sanitizers enabled, use the [item]-s[/item] flag in the corresponding run command.[/warning]'
113
120
  )
121
+ state.STATE.debug_logs = debug_logs
114
122
 
115
123
 
116
124
  # @app.command('ui', hidden=True)
rbx/box/code.py CHANGED
@@ -216,6 +216,52 @@ class PreparedRun:
216
216
  metadata: RunLogMetadata
217
217
 
218
218
 
219
+ @dataclasses.dataclass
220
+ class CaptureSpec:
221
+ prefix: str
222
+ output: Optional[DigestOrDest] = None
223
+ merged_capture: Optional[pathlib.Path] = None
224
+
225
+
226
+ def _prepare_for_communication(
227
+ run: PreparedRun,
228
+ stdin: pathlib.Path,
229
+ stdout: pathlib.Path,
230
+ reverse_io: bool = False,
231
+ capture: Optional[CaptureSpec] = None,
232
+ ):
233
+ run.sandbox_params.set_stdio(
234
+ stdin=stdin,
235
+ stdout=stdout,
236
+ )
237
+ run.sandbox_params.reverse_io = reverse_io
238
+ if capture is not None:
239
+ run.sandbox_params.timeit_prefix = capture.prefix
240
+
241
+ if capture.output is not None:
242
+ output_path = PosixPath('capture')
243
+ run.sandbox_params.timeit_dups['do'].append(output_path)
244
+
245
+ run.artifacts.outputs.append(
246
+ GradingFileOutput(
247
+ src=output_path,
248
+ **capture.output.expand(),
249
+ touch=True,
250
+ )
251
+ )
252
+
253
+ if capture.merged_capture is not None:
254
+ merged_output_path = package.get_merged_capture_path().resolve()
255
+ run.sandbox_params.timeit_dups['Do'].append(merged_output_path)
256
+
257
+ run.artifacts.outputs.append(
258
+ GradingFileOutput(
259
+ src=merged_output_path,
260
+ dest=capture.merged_capture,
261
+ )
262
+ )
263
+
264
+
219
265
  def _prepare_run(
220
266
  code: CodeItem,
221
267
  executable: DigestOrSource,
@@ -484,6 +530,7 @@ class CommunicationItem:
484
530
  outputs: Optional[List[GradingFileOutput]] = None
485
531
  extra_args: Optional[str] = None
486
532
  extra_config: Optional[ExecutionConfig] = None
533
+ capture: Optional[DigestOrDest] = None
487
534
 
488
535
  def prepare(self) -> PreparedRun:
489
536
  return _prepare_run(
@@ -500,6 +547,7 @@ class CommunicationItem:
500
547
  async def run_communication(
501
548
  interactor: CommunicationItem,
502
549
  solution: CommunicationItem,
550
+ merged_capture: Optional[pathlib.Path] = None,
503
551
  retry_index: Optional[int] = None,
504
552
  ):
505
553
  fifo_in, fifo_out = package.get_fifos()
@@ -510,10 +558,35 @@ async def run_communication(
510
558
  interactor_prepared.metadata.retryIndex = retry_index
511
559
  solution_prepared.metadata.retryIndex = retry_index
512
560
 
513
- interactor_prepared.sandbox_params.set_stdio(stdin=fifo_out, stdout=fifo_in)
514
- solution_prepared.sandbox_params.set_stdio(stdin=fifo_in, stdout=fifo_out)
561
+ interactor_prefix = 'INTERACTOR:'
562
+ solution_prefix = 'SOLUTION:'
563
+
564
+ if merged_capture is not None:
565
+ package.get_merged_capture_path().write_text(
566
+ f'{interactor_prefix}\n{solution_prefix}\n'
567
+ )
515
568
 
516
- solution_prepared.sandbox_params.reverse_io = True
569
+ _prepare_for_communication(
570
+ interactor_prepared,
571
+ fifo_out,
572
+ fifo_in,
573
+ capture=CaptureSpec(
574
+ prefix=interactor_prefix,
575
+ output=interactor.capture,
576
+ merged_capture=merged_capture,
577
+ ),
578
+ )
579
+ _prepare_for_communication(
580
+ solution_prepared,
581
+ fifo_in,
582
+ fifo_out,
583
+ reverse_io=True,
584
+ capture=CaptureSpec(
585
+ prefix=solution_prefix,
586
+ output=solution.capture,
587
+ merged_capture=merged_capture,
588
+ ),
589
+ )
517
590
 
518
591
  interactor_run_params = steps.CoordinatedRunParams(
519
592
  command=interactor_prepared.command,
rbx/box/main.py CHANGED
@@ -1,6 +1,2 @@
1
1
  # flake8: noqa
2
- from gevent import monkey
3
-
4
- monkey.patch_all()
5
-
6
2
  from rbx.box.cli import app
rbx/box/package.py CHANGED
@@ -393,16 +393,23 @@ def get_compilation_files(code: CodeItem) -> List[Tuple[pathlib.Path, pathlib.Pa
393
393
  return res
394
394
 
395
395
 
396
+ @functools.cache
397
+ def get_shared_dir(root: pathlib.Path = pathlib.Path()) -> pathlib.Path:
398
+ shared_dir = get_problem_cache_dir(root) / '.shared'
399
+ shared_dir.mkdir(parents=True, exist_ok=True)
400
+ return shared_dir
401
+
402
+
396
403
  @functools.cache
397
404
  def get_empty_sentinel_path(root: pathlib.Path = pathlib.Path()) -> pathlib.Path:
398
- path = get_problem_cache_dir(root) / '.empty'
405
+ path = get_shared_dir(root) / '.empty'
399
406
  path.write_text('')
400
407
  return path
401
408
 
402
409
 
403
410
  @functools.cache
404
411
  def get_fifos(root: pathlib.Path = pathlib.Path()) -> Tuple[pathlib.Path, pathlib.Path]:
405
- path = get_problem_cache_dir(root) / '.fifos'
412
+ path = get_shared_dir(root) / '.fifos'
406
413
  shutil.rmtree(path, ignore_errors=True)
407
414
  path.mkdir(parents=True, exist_ok=True)
408
415
  fifo_in = path / 'fifo.in'
@@ -412,6 +419,13 @@ def get_fifos(root: pathlib.Path = pathlib.Path()) -> Tuple[pathlib.Path, pathli
412
419
  return fifo_in, fifo_out
413
420
 
414
421
 
422
+ @functools.cache
423
+ def get_merged_capture_path(root: pathlib.Path = pathlib.Path()) -> pathlib.Path:
424
+ path = get_shared_dir(root) / '.merged_capture'
425
+ path.write_text('')
426
+ return path
427
+
428
+
415
429
  def clear_package_cache():
416
430
  pkgs = [sys.modules[__name__]]
417
431
 
rbx/box/state.py CHANGED
@@ -5,6 +5,7 @@ import dataclasses
5
5
  class State:
6
6
  run_through_cli: bool = False
7
7
  sanitized: bool = False
8
+ debug_logs: bool = False
8
9
 
9
10
 
10
11
  STATE = State()
rbx/box/tasks.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import pathlib
2
2
  from typing import Optional
3
3
 
4
- from rbx.box import checkers, package
4
+ from rbx.box import checkers, package, state
5
5
  from rbx.box.code import CommunicationItem, run_communication, run_item
6
6
  from rbx.box.environment import EnvironmentSandbox, ExecutionConfig, VerificationLevel
7
7
  from rbx.box.retries import Retrier
@@ -49,6 +49,7 @@ async def run_solution_on_testcase(
49
49
  timelimit_override: Optional[int] = None,
50
50
  use_retries: bool = True,
51
51
  use_timelimit: bool = True,
52
+ capture_pipes: bool = False,
52
53
  ) -> Evaluation:
53
54
  if interactor_digest is not None:
54
55
  return await _run_communication_solution_on_testcase(
@@ -63,6 +64,7 @@ async def run_solution_on_testcase(
63
64
  timelimit_override=timelimit_override,
64
65
  use_retries=use_retries,
65
66
  use_timelimit=use_timelimit,
67
+ capture_pipes=capture_pipes,
66
68
  )
67
69
 
68
70
  async def run_fn(retry_index: int) -> Evaluation:
@@ -155,7 +157,10 @@ async def _run_communication_solution_on_testcase(
155
157
  timelimit_override: Optional[int] = None,
156
158
  use_retries: bool = True,
157
159
  use_timelimit: bool = True,
160
+ capture_pipes: bool = False,
158
161
  ) -> Evaluation:
162
+ capture_pipes = capture_pipes or state.STATE.debug_logs
163
+
159
164
  async def run_fn(retry_index: int) -> Evaluation:
160
165
  actual_sandbox = package.get_singleton_sandbox()
161
166
  interactor_sandbox = package.get_singleton_interactor_sandbox()
@@ -185,6 +190,9 @@ async def _run_communication_solution_on_testcase(
185
190
  log_path = output_path.with_suffix('.log')
186
191
  output_path.parent.mkdir(parents=True, exist_ok=True)
187
192
 
193
+ interactor_capture_path = (
194
+ output_path.with_suffix('.pin') if capture_pipes else None
195
+ )
188
196
  interactor_item = CommunicationItem(
189
197
  code=package.get_interactor(),
190
198
  executable=DigestOrSource.create(interactor_digest),
@@ -204,17 +212,28 @@ async def _run_communication_solution_on_testcase(
204
212
  touch=True,
205
213
  )
206
214
  ],
215
+ capture=DigestOrDest.create(interactor_capture_path)
216
+ if interactor_capture_path
217
+ else None,
218
+ )
219
+ solution_capture_path = (
220
+ output_path.with_suffix('.pout') if capture_pipes else None
207
221
  )
208
222
  solution_item = CommunicationItem(
209
223
  code=solution,
210
224
  executable=DigestOrSource.create(compiled_digest),
211
225
  extra_config=extra_config,
226
+ capture=DigestOrDest.create(solution_capture_path)
227
+ if solution_capture_path
228
+ else None,
212
229
  )
213
230
 
231
+ merged_capture_path = output_path.with_suffix('.pio') if capture_pipes else None
214
232
  interactor_run_log, run_log = await run_communication(
215
233
  interactor=interactor_item,
216
234
  solution=solution_item,
217
235
  retry_index=retry_index,
236
+ merged_capture=merged_capture_path,
218
237
  )
219
238
 
220
239
  checker_result = await checkers.check_communication(
@@ -9,8 +9,6 @@ import tempfile
9
9
  import typing
10
10
  from typing import IO, List, Optional
11
11
 
12
- import gevent
13
-
14
12
  from rbx.grading.judge import digester, storage
15
13
 
16
14
  logger = logging.getLogger(__name__)
@@ -318,8 +316,6 @@ class FileCacher:
318
316
  d.update(buf)
319
317
  while len(buf) > 0:
320
318
  written = dst.write(buf)
321
- # Cooperative yield.
322
- gevent.sleep(0)
323
319
  if written is None:
324
320
  break
325
321
  buf = buf[written:]
@@ -2,8 +2,6 @@ import hashlib
2
2
  import pathlib
3
3
  from typing import IO
4
4
 
5
- import gevent
6
-
7
5
 
8
6
  class Digester:
9
7
  """Simple wrapper of hashlib using our preferred hasher."""
@@ -26,7 +24,6 @@ def digest_cooperatively_into_digester(
26
24
  buf = f.read(chunk_size)
27
25
  while len(buf) > 0:
28
26
  digester.update(buf)
29
- gevent.sleep(0)
30
27
  buf = f.read(chunk_size)
31
28
 
32
29
 
@@ -1,4 +1,5 @@
1
1
  import abc
2
+ import collections
2
3
  import dataclasses
3
4
  import io
4
5
  import logging
@@ -114,6 +115,12 @@ class SandboxParams(pydantic.BaseModel):
114
115
  extra_timeout: Optional[int] = None # ms
115
116
  reverse_io: bool = False
116
117
 
118
+ # For timeit
119
+ timeit_dups: Dict[str, List[pathlib.Path]] = dataclasses.field(
120
+ default_factory=lambda: collections.defaultdict(list)
121
+ )
122
+ timeit_prefix: Optional[str] = None
123
+
117
124
  def get_cacheable_params(self) -> Dict[str, Any]:
118
125
  return self.model_dump(mode='json', exclude_unset=True, exclude_none=True)
119
126
 
@@ -105,8 +105,17 @@ class StupidSandbox(SandboxBase):
105
105
  file_args.append(f'-e{self.params.stderr_file}')
106
106
  if self.params.reverse_io:
107
107
  file_args.reverse()
108
+ args.extend(file_args)
108
109
 
109
- return args + file_args
110
+ if self.params.timeit_dups:
111
+ for i, files in self.params.timeit_dups.items():
112
+ assert i.lower() in ['di', 'do', 'de']
113
+ for file in files:
114
+ args.append(f'-{i}{file}')
115
+ if self.params.timeit_prefix:
116
+ args.append(f'-P{self.params.timeit_prefix}')
117
+
118
+ return args
110
119
 
111
120
  def get_root_path(self) -> pathlib.Path:
112
121
  """Return the toplevel path of the sandbox.
@@ -6,7 +6,7 @@ import signal
6
6
  import stat
7
7
  import sys
8
8
  from time import monotonic
9
- from typing import List, Optional
9
+ from typing import Any, Dict, List, Optional, Set, Union
10
10
 
11
11
 
12
12
  @dataclasses.dataclass
@@ -22,12 +22,96 @@ class Options:
22
22
  memory_limit: Optional[int] = None # kb, but passed in args as mb
23
23
  fs_limit: Optional[int] = None # kb
24
24
  files_to_open: List[int] = dataclasses.field(default_factory=list)
25
+ file_duplicates: Dict[int, List[str]] = dataclasses.field(default_factory=dict)
26
+ prefixed: Set[str] = dataclasses.field(default_factory=set)
27
+ prefix: str = ''
25
28
 
26
29
 
27
30
  def exit_with(code: int):
28
31
  sys.exit(code)
29
32
 
30
33
 
34
+ def get_tee_command(files: List[str]) -> str:
35
+ path = (
36
+ os.path.join(os.path.dirname(os.path.realpath(__file__)), 'tee.py')
37
+ + ' '
38
+ + ' '.join(files)
39
+ )
40
+ return sys.executable + ' ' + path
41
+
42
+
43
+ valid_modes = ['a', 'w']
44
+
45
+
46
+ @dataclasses.dataclass
47
+ class Tee:
48
+ file: Any
49
+ prefix: Union[str, bytes] = ''
50
+
51
+
52
+ def create_tee(files, mode, buffer_size=4096, prefix=''):
53
+ """Get a file object that will mirror writes across multiple files objs
54
+
55
+ Options:
56
+ files A list of files and/or file objects. All strings will be
57
+ treated as file paths and opened for writing. Everything
58
+ else is assumed to be a file-like object that implements
59
+ both the write() and flush() methods.
60
+
61
+ mode Which mode to use when opening new files. Valid values
62
+ are 'a' (append) and 'w' (overwrite).
63
+
64
+ buffer_size
65
+ Control the size of the buffer between writes to the
66
+ resulting file object and the list of files.
67
+ """
68
+ if mode not in valid_modes:
69
+ raise IOError(
70
+ 'Only valid modes to create_tee() are: %s' % ', '.join(valid_modes)
71
+ )
72
+
73
+ tee_list = []
74
+ for file in files:
75
+ if isinstance(file, Tee):
76
+ tee_list.append(file)
77
+ else:
78
+ tee_list.append(Tee(file))
79
+ for tee in tee_list:
80
+ if isinstance(tee.file, str):
81
+ tee.file = open(tee.file, f'{mode}b')
82
+ if isinstance(tee.prefix, str):
83
+ tee.prefix = tee.prefix.encode()
84
+
85
+ pipe_read, pipe_write = os.pipe()
86
+ pid = os.fork()
87
+ if pid == 0:
88
+ # Child -- Read bytes from the pipe and write them to the specified
89
+ # files.
90
+ try:
91
+ # Close parent's end of the pipe
92
+ os.close(pipe_write)
93
+
94
+ bytes = os.read(pipe_read, buffer_size)
95
+ while bytes:
96
+ for tee in tee_list:
97
+ if tee.prefix:
98
+ tee.file.write(tee.prefix)
99
+ tee.file.write(bytes)
100
+ tee.file.flush()
101
+ # TODO maybe add in fsync() here if the fileno() method
102
+ # exists on file
103
+
104
+ bytes = os.read(pipe_read, buffer_size)
105
+ except Exception:
106
+ pass
107
+ finally:
108
+ os._exit(255)
109
+ else:
110
+ # Parent -- Return a file object wrapper around the pipe to the
111
+ # child.
112
+ return os.fdopen(pipe_write, 'w', closefd=False)
113
+
114
+
31
115
  def parse_opts() -> Options:
32
116
  options = Options(output_file=sys.argv[1], argv=[])
33
117
  options.files_to_open = []
@@ -50,10 +134,21 @@ def parse_opts() -> Options:
50
134
  elif opt.startswith('-e'):
51
135
  options.stderr_file = opt[2:]
52
136
  options.files_to_open.append(2)
137
+ elif opt.startswith('-d') or opt.startswith('-D'):
138
+ is_prefixed = opt.startswith('-D')
139
+ possibilities = [None, 'o', 'e']
140
+ index = possibilities.index(opt[2])
141
+ if index not in options.file_duplicates:
142
+ options.file_duplicates[index] = []
143
+ options.file_duplicates[index].append(opt[3:])
144
+ if is_prefixed:
145
+ options.prefixed.add(opt[3:])
53
146
  elif opt.startswith('-c'):
54
147
  options.chdir = opt[2:]
55
148
  elif opt.startswith('-f'):
56
149
  options.fs_limit = int(opt[2:])
150
+ elif opt.startswith('-P'):
151
+ options.prefix = opt[2:]
57
152
  else:
58
153
  raise Exception(f'Invalid option {opt}')
59
154
  num_opts += 1
@@ -108,10 +203,18 @@ def redirect_fds(options: Options):
108
203
  if i == 0:
109
204
  # stdin
110
205
  open_args = [os.O_RDONLY]
111
- fd = os.open(
112
- file,
113
- *open_args,
114
- )
206
+ if i in options.file_duplicates:
207
+ dups = [
208
+ Tee(f, prefix=options.prefix if f in options.prefixed else '')
209
+ for f in options.file_duplicates[i]
210
+ ]
211
+ tee = create_tee(dups + [file], 'a', prefix=options.prefix)
212
+ fd = tee.fileno()
213
+ else:
214
+ fd = os.open(
215
+ file,
216
+ *open_args,
217
+ )
115
218
  os.dup2(fd, i)
116
219
  os.close(fd)
117
220
 
@@ -221,3 +324,4 @@ def main():
221
324
 
222
325
  if __name__ == '__main__':
223
326
  main()
327
+ # type: ignore
@@ -6,8 +6,6 @@ import tempfile
6
6
  from abc import ABC, abstractmethod
7
7
  from typing import IO, AnyStr, List, Optional
8
8
 
9
- import gevent
10
-
11
9
  logger = logging.getLogger(__name__)
12
10
 
13
11
  TOMBSTONE = 'x'
@@ -40,11 +38,9 @@ def copyfileobj(
40
38
  if maxlen > 0 and maxlen < len(buffer):
41
39
  buffer = buffer[:maxlen]
42
40
  while len(buffer) > 0:
43
- gevent.sleep(0)
44
41
  written = destination_fobj.write(buffer)
45
42
  buffer = buffer[written:]
46
43
  maxlen -= written
47
- gevent.sleep(0)
48
44
 
49
45
 
50
46
  @dataclasses.dataclass
rbx/main.py CHANGED
@@ -1,8 +1,4 @@
1
1
  # flake8: noqa
2
- from gevent import monkey
3
-
4
- monkey.patch_all()
5
-
6
2
  import typer
7
3
  from typing_extensions import Annotated
8
4
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rbx.cp
3
- Version: 0.5.42
3
+ Version: 0.5.45
4
4
  Summary:
5
5
  Author: Roberto Sales
6
6
  Requires-Python: >=3.9,<4.0
@@ -13,7 +13,6 @@ Classifier: Programming Language :: Python :: 3.13
13
13
  Requires-Dist: chardet (>=5.2.0,<6.0.0)
14
14
  Requires-Dist: fastapi (>=0.115.8,<0.116.0)
15
15
  Requires-Dist: filelock (>=3.14.0,<4.0.0)
16
- Requires-Dist: gevent (>=24.2.1,<25.0.0)
17
16
  Requires-Dist: gitpython (>=3.1.43,<4.0.0)
18
17
  Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
19
18
  Requires-Dist: lark (>=1.2.2,<2.0.0)
@@ -5,8 +5,8 @@ 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
7
  rbx/box/checkers.py,sha256=l_QYatpKHQTSQ-R7DzNjEkDtdo2g9MkdT_3Kr6xgABU,8690
8
- rbx/box/cli.py,sha256=fvVpNoB-Z8liry0Xlg0quIy072-5ncuVmF4uJ8vXLJ4,26131
9
- rbx/box/code.py,sha256=t2FbW2nd9D8Eh4u0rMK6VK6_S1vezxQoDtDHFFNFkas,16807
8
+ rbx/box/cli.py,sha256=J8mqlZLLZO720FNvkdbV2K1-RGFezNYtyY7Mb4aBrT0,26371
9
+ rbx/box/code.py,sha256=Cnts7noJaaoM35DZ9xcJAKXLwsKB4oBebMidqmMMO4M,18795
10
10
  rbx/box/compile.py,sha256=OJLthDQ921w9vyoE6Gk1Df54i5RwtRJ2YG-8XEfefcs,2489
11
11
  rbx/box/conftest.py,sha256=sEmciXSeDC-wmrZ1JSxbsUenKNP_VWW32mrCun2pY3I,1070
12
12
  rbx/box/contest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -26,8 +26,8 @@ rbx/box/generators.py,sha256=081wKmLQpR7rGGxL9RUWULZef-1DpUWg4U8mWrHvTI0,12431
26
26
  rbx/box/generators_test.py,sha256=J7aBfuJhU84MWDWzgReRoOuQw_hVa09B8gTKAvL2XVo,1987
27
27
  rbx/box/lazy_importing_main.py,sha256=6Z8As7qVFFT619xHH9Xt8VCH57NjC4aDxfAgkWiUwT8,116
28
28
  rbx/box/lazy_importing_test.py,sha256=B0-b3y_DkxEmtVfu4NfmVsgVdFl6kRCsEL6GLMHJISo,628
29
- rbx/box/main.py,sha256=oCsk3xr0NsK4v_IEZItBV5QXFINRuOK-W4CVvFSm1V4,90
30
- rbx/box/package.py,sha256=SgwR-s2dm79ZWk4Q1yugALDJj5w74IhxhZ0fV2XK008,13245
29
+ rbx/box/main.py,sha256=Imwc0ZkheOpa5r8S0Xpb8RLQzJgxb9vyuSR4_wab11g,43
30
+ rbx/box/package.py,sha256=YuX_FS6yKx6FaFz0NF0cx3v6jzhqwvsLr3Oprx_TTJA,13645
31
31
  rbx/box/packaging/boca/extension.py,sha256=hQhcbocNfW2ESv5RalS1wf6uvOoOfOnR_gHvbXUbSzY,852
32
32
  rbx/box/packaging/boca/packager.py,sha256=KE-BpFZh8r7ftZJGmD6Zx1bWOTrbNhgS7i9k-yDtfK4,10740
33
33
  rbx/box/packaging/contest_main.py,sha256=nMdgPE4OK_tsnUMdRI1cJwLpgxGrwW_mJjox0oOALWw,2757
@@ -47,7 +47,7 @@ rbx/box/schema.py,sha256=P1jVaeqe4OcotAJOqu3T5WD8DR-amZyyq3cau5rPiM8,17086
47
47
  rbx/box/setter_config.py,sha256=s53talhwM6FTGDCcBhY7IlZ6_6mJ3PMp6V4kTtaSs50,4262
48
48
  rbx/box/solutions.py,sha256=lzvk72PsQOE0TMK6AOk-qNROK0fRAKcGINtokq6gypU,42554
49
49
  rbx/box/solutions_test.py,sha256=TCowbxBG3SvDlFO5-qtBj_M_HrAHe0IJaI1XwoQ1d00,1718
50
- rbx/box/state.py,sha256=cBeEkJXSXLwYmCT0yLq2TjycusKFpjOeW8yPRIi6K-o,137
50
+ rbx/box/state.py,sha256=MMf3DvfQji0jKEliCHct2Tpp_0epL1tvP8HbHNArQIc,166
51
51
  rbx/box/statements/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
52
  rbx/box/statements/build_statements.py,sha256=uHlC3y3PtKaGUd2ZS_zYxi6-AKco6v_yd-lvm6BfrNA,12091
53
53
  rbx/box/statements/builders.py,sha256=L67i-CP6ftDm2wR6VWywTd3ad7-fhWSSMfaN66Gt13s,11201
@@ -59,7 +59,7 @@ rbx/box/stresses.py,sha256=E4JU1JrUcikPA6QEACKnEOBkRocpEhswkF1iE7aRD5U,12147
59
59
  rbx/box/stressing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
60
  rbx/box/stressing/finder_parser.py,sha256=jXpYNa4FyugzmHi3r96Uv4rU1krRQJc5Ihr9jf1cvNo,11918
61
61
  rbx/box/stressing/generator_parser.py,sha256=oHZryjR3YohgaSO9WEirQ7b2e-98WgZStF0N99W4Thw,7380
62
- rbx/box/tasks.py,sha256=g-dHeF97rSEiO41KUN-OIzXP6SkbRAkUnMZ1Xess4sY,8742
62
+ rbx/box/tasks.py,sha256=upcj8aQjJ5Oi0XHD4CVutAvzh-K0gIbpikAhu6_nTMM,9537
63
63
  rbx/box/testcase_extractors.py,sha256=T5vCW5qERlqitGrFP6RuITEVr9o8XQozNa4AsxfuV_Y,11871
64
64
  rbx/box/testcase_utils.py,sha256=qtv7-bJbbblMgINvcf_3YTdD85MTtWpD23KUSZUL1as,4327
65
65
  rbx/box/testcases/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -83,14 +83,14 @@ rbx/grading/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
83
83
  rbx/grading/caching.py,sha256=tnCQl08kUC0IYx5XKxfvaUGJIvEC_C2LPJHNv90clOw,12029
84
84
  rbx/grading/conftest.py,sha256=iN9LUG1IQqhK5JjkctcP68v6675oYsiD2sQSgyLMTqw,960
85
85
  rbx/grading/judge/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
86
- rbx/grading/judge/cacher.py,sha256=W4bdPIvI8tXOl8A7B4Ncuzi9-zXCp0DX40i1XKQGOAU,17761
87
- rbx/grading/judge/digester.py,sha256=m6o-kjwyFOXKdImUXtVbdMHhwrgrXk8FDnJFVefnTIw,951
88
- rbx/grading/judge/sandbox.py,sha256=EhaO9lY_DewQFHojHUVZCgEeKU6bVKR73KBjL2NBNy8,23841
86
+ rbx/grading/judge/cacher.py,sha256=TDgYDhehnJIv64EFiXxPAtVADD8q9WcJa_BE9TsE-JM,17669
87
+ rbx/grading/judge/digester.py,sha256=gtOIe_iL4PEWA7OKelW1gjSI-nBvbOpDPJGV8VQyjSg,912
88
+ rbx/grading/judge/sandbox.py,sha256=Pc1JAh_ZZ46m-S10rmoYCA7ZWGpLCYB0UnhdzSFMDyY,24054
89
89
  rbx/grading/judge/sandboxes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
90
90
  rbx/grading/judge/sandboxes/isolate.py,sha256=9xgBuNfAvGtO2zME1FXRah2rcPvzDShsPG0TTuX_UDU,25649
91
- rbx/grading/judge/sandboxes/stupid_sandbox.py,sha256=xmYp-Vfr9pp0KUOHt63kqcbEBLntGuW5MykH_L8lS50,10256
92
- rbx/grading/judge/sandboxes/timeit.py,sha256=CxWNslAiz1ildDXqU5Z_5rrQTHBvjixaaLRG5MZTesU,6889
93
- rbx/grading/judge/storage.py,sha256=FirqjwDqb0m0h2OTFyWrZL7CQ4XjZNxhqB4JpnDIhZY,9485
91
+ rbx/grading/judge/sandboxes/stupid_sandbox.py,sha256=RDnCA4EmEgA2D0MOuD1y7eTRX_jKNRhVQkmUAb2dsgg,10606
92
+ rbx/grading/judge/sandboxes/timeit.py,sha256=HR_5CRyuY4OHZ1rTcEXZ796UfqlAJGX8HiZpgxOApkk,10475
93
+ rbx/grading/judge/storage.py,sha256=3vv0HvtenbUZBH33CB5ZzX66ppL22G6munBaAA9BgwQ,9418
94
94
  rbx/grading/judge/test.py,sha256=ll0Iw7zyOpGdKPD_PGH7dvUkb4stQLu-ikbQnqJvuAc,944
95
95
  rbx/grading/judge/testiso.py,sha256=v14DtkWiZFJ9AKMzrb0_vZKPWDt8jz8iIw1Z2O-Advk,1397
96
96
  rbx/grading/steps.py,sha256=jpGsUMvyquaZraZlwf5YqxfQLK-F2OateFpJ8ZheQO8,25219
@@ -98,7 +98,7 @@ rbx/grading/steps_with_caching.py,sha256=nez2YwgauGXKRjhk6tQxTDGQ-HEk7KfZOeAPhsx
98
98
  rbx/grading/steps_with_caching_run_test.py,sha256=mh4DRInrOGhnQFWD1SlcjDm_HvcSDFTDMSpAlG-Q5SI,15570
99
99
  rbx/grading_utils.py,sha256=lL2KtSkOsMElqrRoApQTbFcqVOeHVWUDTMCa3IsLpC4,4484
100
100
  rbx/hydration.py,sha256=WqbgIfCZNwqspVhMuUlx8-sNOYhq_ZWbeZnkcetuAZI,3669
101
- rbx/main.py,sha256=hbXMb6ofV4cowEnFt9-mSa3qenXthuKTkv9ECS4-c9w,2912
101
+ rbx/main.py,sha256=pFZreQhcoq-vIvWuVVeJEa8s_ka24dxF0WmaasarscE,2865
102
102
  rbx/metadata.py,sha256=4eIHWlwwq-eAbpRDZkCovcGMbwOVVy-5JMmbLtk429w,3116
103
103
  rbx/providers/__init__.py,sha256=gHXg1BTiXJ_0Z_HoVTZrqhi5IIZ57Dhy0pt7K2ETbA4,1378
104
104
  rbx/providers/codeforces.py,sha256=HWQN3Zb9UfXgCfwcNMEk6m1HoXQ-UE2odVfZoPukyCg,2294
@@ -158,41 +158,10 @@ rbx/submitors/submitor.py,sha256=8q-Hbdahxt30ciT_R9j_xF6lEPUh9IcfAUnzjQjbvHU,457
158
158
  rbx/test.py,sha256=tZyTrXDK8MLR-1TyCRxiOiNz-PhlXVpshfUGphakkT4,11830
159
159
  rbx/testcase.py,sha256=yKOq3CAJZ1YTmInvnoIs0u1iJnRj_X85XiWbLI-p9d8,1951
160
160
  rbx/testcase_rendering.py,sha256=nfmv6dSEqd4aR3TsaODwkKGK6AXty_DDKtWf_ejiQpI,2084
161
- rbx/testdata/box1/gen1.cpp,sha256=Yx4uxlEtCeuC7NjrnRotONJBldiR5HSD6jvvVyjjh1I,91
162
- rbx/testdata/box1/gen2.cpp,sha256=hRxLtUfj5ZvCrWF0G2is6-np9cVBPsP6Dj32-QLp3Bk,139
163
- rbx/testdata/box1/genScript.py,sha256=HkMDSw7_ttj_2rpnZnlNMYGrj_PWzZzMDCUbCgXraVI,42
164
- rbx/testdata/box1/hard-tle.sol.cpp,sha256=SnnhfKIngu6-xzTvHJ51stSPvXCsCKeHJnKr4hwzNZ8,389
165
- rbx/testdata/box1/ole.cpp,sha256=7brjB5CWBDWOmRgwSOIQ8E65SGIJRrg7jQ4ClMYLmxY,253
166
- rbx/testdata/box1/problem.rbx.yml,sha256=pA21zLlyyqM_iQP3vVrCBWVAMf8tJ5vy5y7T3UYwr-0,801
167
- rbx/testdata/box1/re.sol.cpp,sha256=A6s7E-_2lG3ZRViecYy5vI6SElBOtpbhZUMcMQPIyQU,426
168
- rbx/testdata/box1/sol.cpp,sha256=fSaVcFEq0_cYP-z2RfCvyTP4MwoE4nexwFDBgRpE_Fw,421
169
- rbx/testdata/box1/tests/1.in,sha256=UciUkcfyYz8ZrSF_cy2DKt4L13PRmy8eh-Dlw7RbKdM,4
170
- rbx/testdata/box1/tle-and-incorrect.sol.cpp,sha256=BM7iFwuYE4jD4Q16-pOD0RwQxxYZF-t-VwVgVcrEgao,582
171
- rbx/testdata/box1/tle.sol.cpp,sha256=k3mboV4p_aNtM3VOm1vvxlVUiNfSEM1TP8hr-gnttYI,630
172
- rbx/testdata/box1/validator.cpp,sha256=EWiKEWB6Nvke3SjBWHnkhkKJjwOqY_WX5kuXLxibABY,196
173
- rbx/testdata/box1/wa.sol.cpp,sha256=qsHmvtLJOFI_sdvUT6ITqk7FJYqhrRTCmEIRdy4gSGE,407
174
- rbx/testdata/caching/executable.py,sha256=WKRHNf_fprFJd1Fq1ubmQtR3mZzTYVNwKPLWuZ4HrWg,10
175
- rbx/testdata/compatible,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
176
- rbx/testdata/interactive/checker.cpp,sha256=ILPhx0x6XyahJs_zuMkB9D_6swWs7PJE2dALO4wBXFE,516
177
- rbx/testdata/interactive/gen.cpp,sha256=XF8NezWJy2XFxp2O03eiSUZUH6uHfFIPuvsZ5mqohc8,235
178
- rbx/testdata/interactive/interactor.cpp,sha256=2kcX4W9P2iqnNUTya2Cckoj-NO8jEIZoDAjTrPdpn8A,1319
179
- rbx/testdata/interactive/problem.rbx.yml,sha256=LY0Ti-ZHLJCIwYwQ1dcX0WsAwAk4WwHIjLkzUD7DfX8,889
180
- rbx/testdata/interactive/sols/af_ac_pe.cpp,sha256=GYDSmcyoZVtDbLlvMmJhMweb3jutgkjnZjHqaI9tJZE,1369
181
- rbx/testdata/interactive/sols/af_ac_re.cpp,sha256=mlD0izWJIxwvbSLq3zkdBAZRfo8cOoaEty-w7swqJMk,1376
182
- rbx/testdata/interactive/sols/af_ac_too_many_iter.cpp,sha256=k1bYYxDlXHz_RVnPeWyfTRzCctSctfxIsLc6l0nHCKM,1306
183
- rbx/testdata/interactive/sols/af_inf_cout_with_flush.cpp,sha256=591Vfc7AqxgcR6fUMkb8mOS_jX8lXUnXnnghx3e2tks,1449
184
- rbx/testdata/interactive/sols/af_inf_cout_without_flush.cpp,sha256=11fjgkxdaZvsT_0g4mtjHaaWjH4ciD3MduVJyv62-0Q,1425
185
- rbx/testdata/interactive/sols/af_ml.cpp,sha256=h9FfzvtUdZFpJ95dTIf5JBJElIUy4R6wnnhcmalvBPo,1438
186
- rbx/testdata/interactive/sols/af_tl_after_ans.cpp,sha256=oLXUMn9gZ06hA19UE5rxhnUl-cJ8tI_7J8bxqQ670dU,1334
187
- rbx/testdata/interactive/sols/af_wa.cpp,sha256=zlE6aAVIcQvrdH-KUYLXsHOc8CgcuJmUNS-BxhNbL5Q,1364
188
- rbx/testdata/interactive/sols/interactive-binary-search_mm_naive_cin.cpp,sha256=90ZUuIWehGmn4_L3wX_J4nRps9W1Po_kZrEJuWxUOIQ,281
189
- rbx/testdata/interactive/sols/main.cpp,sha256=whWhcJfHP6QJ1DGaqcoDc_MDbqG_gfpD4hNAUT8vAa8,394
190
- rbx/testdata/interactive/testplan.txt,sha256=ZPoU7O5nAasROa2evnaR3gHGDZsiKZ3PUTbtUHhe8rs,69
191
- rbx/testdata/interactive/validator.cpp,sha256=KCxrwDqiBf8z6Ml1Xk9XSZbEtH35Ud7gy9ux-Ek2cPY,301
192
161
  rbx/testing_utils.py,sha256=ZXMysGXpTtvS1lfLL38FuD5iSIyxi3ARjQePDrUmEtc,2067
193
162
  rbx/utils.py,sha256=6e1eXRzNE-52D0UVtqclePxqR4Haiqt8qWCrSVjnGuE,4585
194
- rbx_cp-0.5.42.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
195
- rbx_cp-0.5.42.dist-info/METADATA,sha256=Eglv646z3n9611spOrS3jjBwzhgIv4iODSJ1LiGujR4,3302
196
- rbx_cp-0.5.42.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
197
- rbx_cp-0.5.42.dist-info/entry_points.txt,sha256=qBTLBOeifT1F00LWaEewRRE_jQPgvH7BUdJfZ-dYsFU,57
198
- rbx_cp-0.5.42.dist-info/RECORD,,
163
+ rbx_cp-0.5.45.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
164
+ rbx_cp-0.5.45.dist-info/METADATA,sha256=C1zyfAGCq-sfkXX8y52EA2XJIjBgD5X_N4vPE5oDrDk,3261
165
+ rbx_cp-0.5.45.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
166
+ rbx_cp-0.5.45.dist-info/entry_points.txt,sha256=qBTLBOeifT1F00LWaEewRRE_jQPgvH7BUdJfZ-dYsFU,57
167
+ rbx_cp-0.5.45.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.1
2
+ Generator: poetry-core 2.1.2
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,7 +0,0 @@
1
- #include <bits/stdc++.h>
2
-
3
- using namespace std;
4
-
5
- int32_t main() {
6
- cout << "123" << endl;
7
- }