rbx.cp 0.5.49__py3-none-any.whl → 0.5.50__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/cli.py CHANGED
@@ -747,6 +747,7 @@ async def validate(
747
747
  rich_help_panel='Testing',
748
748
  help='Run unit tests for the validator and checker.',
749
749
  )
750
+ @package.within_problem
750
751
  def unit_tests():
751
752
  from rbx.box import unit
752
753
 
rbx/box/packaging/main.py CHANGED
@@ -64,6 +64,7 @@ async def run_packager(
64
64
 
65
65
 
66
66
  @app.command('polygon', help='Build a package for Polygon.')
67
+ @package.within_problem
67
68
  @syncer.sync
68
69
  async def polygon(
69
70
  verification: environment.VerificationParam,
@@ -74,6 +75,7 @@ async def polygon(
74
75
 
75
76
 
76
77
  @app.command('boca', help='Build a package for BOCA.')
78
+ @package.within_problem
77
79
  @syncer.sync
78
80
  async def boca(
79
81
  verification: environment.VerificationParam,
@@ -84,6 +86,7 @@ async def boca(
84
86
 
85
87
 
86
88
  @app.command('moj', help='Build a package for MOJ.')
89
+ @package.within_problem
87
90
  @syncer.sync
88
91
  async def moj(
89
92
  verification: environment.VerificationParam,
rbx/box/solutions.py CHANGED
@@ -47,7 +47,12 @@ from rbx.box.tasks import (
47
47
  run_solution_on_testcase,
48
48
  )
49
49
  from rbx.box.testcase_extractors import extract_generation_testcases
50
- from rbx.box.testcase_utils import TestcaseEntry, find_built_testcases
50
+ from rbx.box.testcase_utils import (
51
+ TestcaseEntry,
52
+ find_built_testcases,
53
+ parse_interaction,
54
+ print_interaction,
55
+ )
51
56
  from rbx.grading.steps import (
52
57
  Evaluation,
53
58
  Outcome,
@@ -323,6 +328,19 @@ def _produce_solution_items(
323
328
  return res
324
329
 
325
330
 
331
+ def print_best_output(output_files: List[pathlib.Path], empty_warning: bool = False):
332
+ for output_file in output_files:
333
+ if not output_file.is_file():
334
+ continue
335
+ if output_file.suffix == '.pio':
336
+ print_interaction(parse_interaction(output_file))
337
+ else:
338
+ console.console.print(output_file.read_text())
339
+ return
340
+ if empty_warning:
341
+ console.console.print('[warning]Solution produced no output.[/warning]')
342
+
343
+
326
344
  def run_solutions(
327
345
  progress: Optional[StatusProgress] = None,
328
346
  tracked_solutions: Optional[Set[str]] = None,
@@ -528,6 +546,7 @@ def _run_interactive_solutions(
528
546
  output_dir=output_dir,
529
547
  interactor_digest=interactor_digest,
530
548
  verification=verification,
549
+ capture_pipes=True,
531
550
  )
532
551
 
533
552
  yield EvaluationItem(
@@ -589,18 +608,28 @@ async def run_and_print_interactive_solutions(
589
608
  )
590
609
 
591
610
  stdout_path = eval.log.stdout_absolute_path
592
- if print:
611
+ if print and stdout_path is not None:
612
+ if pkg.type == TaskType.COMMUNICATION:
613
+ console.console.rule('Interaction', style='status')
614
+ output_files = [
615
+ stdout_path.with_suffix('.pio'),
616
+ stdout_path.with_suffix('.pout'),
617
+ ]
618
+ print_best_output(output_files, empty_warning=True)
619
+
593
620
  console.console.rule('Output', style='status')
594
- if (
595
- eval.testcase.output is not None
596
- and stdout_path is not None
597
- and stdout_path.is_file()
598
- ):
599
- console.console.print(stdout_path.read_text())
600
- else:
601
- console.console.print('[warning]Solution produced no output.[/warning]')
621
+ output_files = [stdout_path]
622
+ print_best_output(output_files, empty_warning=True)
602
623
  elif stdout_path is not None:
603
- console.console.print(f'[status]Output:[/status] {stdout_path}')
624
+ if stdout_path.with_suffix('.pout').is_file():
625
+ stdout_path = stdout_path.with_suffix('.pout')
626
+
627
+ if stdout_path.is_file():
628
+ console.console.print(f'[status]Output:[/status] {stdout_path}')
629
+ if stdout_path.with_suffix('.pio').is_file():
630
+ console.console.print(
631
+ f'[status]Interaction:[/status] {stdout_path.with_suffix(".pio")}'
632
+ )
604
633
  if eval.log.stderr_absolute_path is not None:
605
634
  console.console.print(
606
635
  f'[status]Stderr:[/status] {eval.log.stderr_absolute_path}'
rbx/box/testcase_utils.py CHANGED
@@ -2,6 +2,8 @@ import pathlib
2
2
  import shutil
3
3
  from typing import List, Optional, Tuple
4
4
 
5
+ import rich
6
+ import rich.text
5
7
  import typer
6
8
  from pydantic import BaseModel
7
9
 
@@ -209,3 +211,13 @@ def parse_interaction(file: pathlib.Path) -> TestcaseInteraction:
209
211
  prefixes=(interactor_prefix, solution_prefix),
210
212
  entries=entries,
211
213
  )
214
+
215
+
216
+ def print_interaction(interaction: TestcaseInteraction):
217
+ for entry in interaction.entries:
218
+ text = rich.text.Text(entry.data)
219
+ if entry.pipe == 0:
220
+ text.stylize('status')
221
+ else:
222
+ text.stylize('info')
223
+ console.console.print(text, end='')
rbx/box/testcases/main.py CHANGED
@@ -90,6 +90,7 @@ async def _generate_for_editing(
90
90
 
91
91
 
92
92
  @app.command('view, v', help='View a testcase in your default editor.')
93
+ @package.within_problem
93
94
  @syncer.sync
94
95
  async def view(
95
96
  tc: Annotated[
@@ -126,6 +127,7 @@ async def view(
126
127
 
127
128
 
128
129
  @app.command('info, i', help='Show information about testcases.')
130
+ @package.within_problem
129
131
  @syncer.sync
130
132
  async def info(
131
133
  pattern: Annotated[
rbx/box/unit.py CHANGED
@@ -29,6 +29,16 @@ class CheckerTestEntry(BaseModel):
29
29
  answer: Optional[pathlib.Path] = None
30
30
  outcome: ExpectedOutcome
31
31
 
32
+ def running_tests_formatted_string(self) -> str:
33
+ res = []
34
+ if self.input:
35
+ res.append(f'[item]{self.input}[/item]')
36
+ if self.output:
37
+ res.append(f'[item]{self.output}[/item]')
38
+ if self.answer:
39
+ res.append(f'[item]{self.answer}[/item]')
40
+ return ', '.join(res)
41
+
32
42
 
33
43
  def _extract_validator_test_entries(
34
44
  tests: List[ValidatorTest],
@@ -91,13 +101,16 @@ async def run_validator_unit_tests(progress: StatusProgress):
91
101
  if val is not None:
92
102
  vals.append(val)
93
103
 
104
+ console.console.rule('Validator tests', style='info')
105
+ if not entries:
106
+ console.console.print(']No validator unit tests found.')
107
+ return
108
+
94
109
  compiled_validators = validators.compile_validators(vals, progress=progress)
95
110
 
96
111
  if progress:
97
112
  progress.update('Running validator unit tests...')
98
113
 
99
- console.console.rule('Validator tests', style='info')
100
-
101
114
  for i, test in enumerate(entries):
102
115
  val = _get_validator_for_test(test)
103
116
  if val is None:
@@ -127,7 +140,10 @@ async def run_validator_unit_tests(progress: StatusProgress):
127
140
  if info.ok:
128
141
  console.console.print(' [status]Actual[/status] VALID')
129
142
  else:
130
- console.console.print(f' [status]Actual[/status] {info.message}')
143
+ console.console.print(' [status]Actual[/status] INVALID')
144
+
145
+ if info.message:
146
+ console.console.print(f' [status]Message[/status] {info.message}')
131
147
 
132
148
 
133
149
  async def run_checker_unit_tests(progress: StatusProgress):
@@ -141,15 +157,19 @@ async def run_checker_unit_tests(progress: StatusProgress):
141
157
  )
142
158
  return
143
159
 
160
+ console.console.rule('Checker tests', style='info')
161
+
162
+ entries = _extract_checker_test_entries(pkg.unitTests.checker)
163
+ if not entries:
164
+ console.console.print('No checker unit tests found.')
165
+ return
166
+
144
167
  compiled_digest = checkers.compile_checker(progress=progress)
145
168
 
146
169
  if progress:
147
170
  progress.update('Running checker unit tests...')
148
171
 
149
- console.console.rule('Checker tests', style='info')
150
-
151
172
  empty_file = package.get_empty_sentinel_path()
152
- entries = _extract_checker_test_entries(pkg.unitTests.checker)
153
173
 
154
174
  for i, test in enumerate(entries):
155
175
  result = await checkers.check(
@@ -169,13 +189,15 @@ async def run_checker_unit_tests(progress: StatusProgress):
169
189
  else '[error]FAIL[/error]'
170
190
  )
171
191
 
172
- console.console.print(f'{markup} Unit test [item]#{i + 1}[/item]')
192
+ console.console.print(
193
+ f'{markup} Unit test [item]#{i + 1}[/item] ({test.running_tests_formatted_string()})'
194
+ )
173
195
  console.console.print(f' [status]Expected[/status] {test.outcome.name}')
174
196
 
175
197
  if not test.outcome.match(result.outcome):
176
198
  console.console.print(f' [status]Actual[/status] {result.outcome.name}')
177
- if result.message:
178
- console.console.print(f' [status]Message[/status] {result.message}')
199
+ if result.message:
200
+ console.console.print(f' [status]Message[/status] {result.message}')
179
201
 
180
202
 
181
203
  @syncer.sync
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rbx.cp
3
- Version: 0.5.49
3
+ Version: 0.5.50
4
4
  Summary:
5
5
  Author: Roberto Sales
6
6
  Requires-Python: >=3.9,<4.0
@@ -5,7 +5,7 @@ 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=eb4tqtVUJYlme_Vkj2TGkUABM7EMS0P1EswhMYjN7BI,11459
8
- rbx/box/cli.py,sha256=5SqJB4tE0vqWWyaweRpA7vSoIp34-AzH23ToR-yHmpk,26463
8
+ rbx/box/cli.py,sha256=0JeJSVTK_5coijsm1b1zKQzuv7RBgexoM3klDeveabY,26487
9
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
@@ -32,7 +32,7 @@ rbx/box/package.py,sha256=YuX_FS6yKx6FaFz0NF0cx3v6jzhqwvsLr3Oprx_TTJA,13645
32
32
  rbx/box/packaging/boca/extension.py,sha256=EQALNEOv4zVDXSKs_dk11n92y7cBZVn8TogIK683lE0,890
33
33
  rbx/box/packaging/boca/packager.py,sha256=CUMoQICrkQQBFElmI9SrvXlFFnpwkTiJ9qbOSJOy6AE,12512
34
34
  rbx/box/packaging/contest_main.py,sha256=nMdgPE4OK_tsnUMdRI1cJwLpgxGrwW_mJjox0oOALWw,2757
35
- rbx/box/packaging/main.py,sha256=RXGcpVZTwqkdLs4wHwoHSiFTXW62jIUS5fnvSKu3Ymw,2998
35
+ rbx/box/packaging/main.py,sha256=WOW0JRYcZRuWOEsfd4AKX5wLqu8Br1TYaEfHjqWmu9Q,3070
36
36
  rbx/box/packaging/moj/packager.py,sha256=Ro_TO3RVCCRAxNcCio0u42TLfW8FnX9IohMChmGlrvo,8499
37
37
  rbx/box/packaging/packager.py,sha256=da2haC1L9cG30myneMrRIAdGubtid0Xmy38BHKPCZZ4,3633
38
38
  rbx/box/packaging/polygon/packager.py,sha256=qTGOUckevdOCt_ES63pN3uhmhDl9JuNcZ1XEnGNq-tU,10833
@@ -46,7 +46,7 @@ rbx/box/retries.py,sha256=tRk2K1bXw2xnwkAj2CsktRHTEhw7YKcPxMQTT6mCy-E,4707
46
46
  rbx/box/sanitizers/warning_stack.py,sha256=RI97_GJgdjTKIXY_r0EKp5h0qQQSDSdNDh5K7zINrqs,2861
47
47
  rbx/box/schema.py,sha256=tOQ1tLHqc_5V-UgrzM44aS8ULAkq-IkeErxjLCFVA8I,16778
48
48
  rbx/box/setter_config.py,sha256=s53talhwM6FTGDCcBhY7IlZ6_6mJ3PMp6V4kTtaSs50,4262
49
- rbx/box/solutions.py,sha256=b4P6JN4eSDFiUKjBYvI38jsf8wLxS8Wi-YwBmm25Rcg,42684
49
+ rbx/box/solutions.py,sha256=eTMpxIvhU3IUF1gfR_y20o_6NZ4hDtMGhTi4ookG9TY,43766
50
50
  rbx/box/solutions_test.py,sha256=TCowbxBG3SvDlFO5-qtBj_M_HrAHe0IJaI1XwoQ1d00,1718
51
51
  rbx/box/state.py,sha256=MMf3DvfQji0jKEliCHct2Tpp_0epL1tvP8HbHNArQIc,166
52
52
  rbx/box/statements/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -62,15 +62,15 @@ rbx/box/stressing/finder_parser.py,sha256=jXpYNa4FyugzmHi3r96Uv4rU1krRQJc5Ihr9jf
62
62
  rbx/box/stressing/generator_parser.py,sha256=oHZryjR3YohgaSO9WEirQ7b2e-98WgZStF0N99W4Thw,7380
63
63
  rbx/box/tasks.py,sha256=oyWtgZvIEIkVV6e-GcJx7x8Z3T5tIDFBZbp0638sLeY,10036
64
64
  rbx/box/testcase_extractors.py,sha256=T5vCW5qERlqitGrFP6RuITEVr9o8XQozNa4AsxfuV_Y,11871
65
- rbx/box/testcase_utils.py,sha256=eeE7pr0vwxTEdHcZcpr9bIQlgIY5qI4-HpqR041LKxQ,6697
65
+ rbx/box/testcase_utils.py,sha256=Ppg_P1Nq48cuKo1XiIi4b8FZkMW8IBp_4Wf1Yf42YuI,7019
66
66
  rbx/box/testcases/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
- rbx/box/testcases/main.py,sha256=sLEgpVCDjRc3tJcU--DNWMmc58KgrkQe4zGzBorO-rk,5394
67
+ rbx/box/testcases/main.py,sha256=_I7h_obRcpNLRQ6dDJDIE5NAvTyn5nBOhdsBhRA_PvU,5442
68
68
  rbx/box/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
69
  rbx/box/ui/captured_log.py,sha256=ptICDPViVnz-_2NfrcB0SSBXNW5L74zI-vAZNN7kSok,11319
70
70
  rbx/box/ui/css/app.tcss,sha256=apd5PkPEvl5jK3kE2qrxPyVED1VnvSsj08QQwzUPwEA,786
71
71
  rbx/box/ui/main.py,sha256=b0rHcBF42W4AOCv7WhtiGf_rUnY0yxpqO5oj3wfR4R4,984
72
72
  rbx/box/ui/run.py,sha256=wMEXrEFdQvMHz2hRKAFIithTnTtaL0kNQZu0jKmb8jI,7060
73
- rbx/box/unit.py,sha256=ziyfgU4gmmNqKucMYYiJksOHkp22pxYpgk7dpX2mSQM,5793
73
+ rbx/box/unit.py,sha256=ySnosNg-b50mJU_9jEpRYm5wiiZxkdhKR9AVQXbtTOE,6478
74
74
  rbx/box/validators.py,sha256=oqlNhw7jivbbH5l8g3xwihPRy76AM7MA3G4A8nyI_V0,10416
75
75
  rbx/box/validators_test.py,sha256=WY4Ho-wlsPHc0YNuz0KFVd6KQ9ouuiou3w5_zMOZ4Fs,362
76
76
  rbx/checker.py,sha256=pj1jO3my48ru-qugbER5onccANCjoR0-PaFe3H3VGEY,4118
@@ -188,8 +188,8 @@ rbx/testcase.py,sha256=yKOq3CAJZ1YTmInvnoIs0u1iJnRj_X85XiWbLI-p9d8,1951
188
188
  rbx/testcase_rendering.py,sha256=nfmv6dSEqd4aR3TsaODwkKGK6AXty_DDKtWf_ejiQpI,2084
189
189
  rbx/testing_utils.py,sha256=ZXMysGXpTtvS1lfLL38FuD5iSIyxi3ARjQePDrUmEtc,2067
190
190
  rbx/utils.py,sha256=6e1eXRzNE-52D0UVtqclePxqR4Haiqt8qWCrSVjnGuE,4585
191
- rbx_cp-0.5.49.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
192
- rbx_cp-0.5.49.dist-info/METADATA,sha256=mNCg5KTbxOIcJGovPqYotTF3kFQXqxcJ-8TRjAK47Pg,3261
193
- rbx_cp-0.5.49.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
194
- rbx_cp-0.5.49.dist-info/entry_points.txt,sha256=qBTLBOeifT1F00LWaEewRRE_jQPgvH7BUdJfZ-dYsFU,57
195
- rbx_cp-0.5.49.dist-info/RECORD,,
191
+ rbx_cp-0.5.50.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
192
+ rbx_cp-0.5.50.dist-info/METADATA,sha256=ScwTLSdZ7ISYKsmPKdWkq1hT0AOfAm25GBzQT9c4u-E,3261
193
+ rbx_cp-0.5.50.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
194
+ rbx_cp-0.5.50.dist-info/entry_points.txt,sha256=qBTLBOeifT1F00LWaEewRRE_jQPgvH7BUdJfZ-dYsFU,57
195
+ rbx_cp-0.5.50.dist-info/RECORD,,