rbx.cp 0.5.48__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/schema.py CHANGED
@@ -356,8 +356,8 @@ class LimitModifiers(BaseModel):
356
356
  class ValidatorTest(BaseModel):
357
357
  model_config = ConfigDict(extra='forbid')
358
358
 
359
- input: pathlib.Path = Field(
360
- description='The input file to be used as unit test input for the validator.'
359
+ glob: str = Field(
360
+ description='A glob pattern for the input files to be used as unit test input for the validator.'
361
361
  )
362
362
  outcome: ValidatorOutcome = Field(
363
363
  default=ValidatorOutcome.VALID,
@@ -373,17 +373,12 @@ class ValidatorTest(BaseModel):
373
373
  class CheckerTest(BaseModel):
374
374
  model_config = ConfigDict(extra='forbid')
375
375
 
376
- input: Optional[pathlib.Path] = Field(
377
- default=None,
378
- description='The input file to be used as unit test input for the checker. If not specified, will pass an empty file.',
379
- )
380
- output: Optional[pathlib.Path] = Field(
381
- default=None,
382
- description='The solution output file to be used as unit test output for the checker. If not specified, will pass an empty file.',
383
- )
384
- answer: Optional[pathlib.Path] = Field(
385
- default=None,
386
- description='The answer file to be used as unit test answer for the checker. If not specified, will pass an empty file.',
376
+ glob: str = Field(
377
+ description="""
378
+ A glob pattern for the files to be used as unit test input for the checker.
379
+ This glob should simultaneously match the input, output, and answer files (.in, .out, .ans).
380
+ If one of them is not present, an empty file will be used instead.
381
+ """,
387
382
  )
388
383
 
389
384
  outcome: ExpectedOutcome = Field(
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
@@ -1,14 +1,89 @@
1
- from typing import List, Optional
1
+ import pathlib
2
+ from typing import List, Optional, Set
2
3
 
3
4
  import syncer
5
+ from pydantic import BaseModel
4
6
 
5
7
  from rbx import console
6
8
  from rbx.box import checkers, package, validators
7
- from rbx.box.schema import CodeItem, Testcase, ValidatorOutcome, ValidatorTest
9
+ from rbx.box.schema import (
10
+ CheckerTest,
11
+ CodeItem,
12
+ ExpectedOutcome,
13
+ Testcase,
14
+ ValidatorOutcome,
15
+ ValidatorTest,
16
+ )
8
17
  from rbx.utils import StatusProgress
9
18
 
10
19
 
11
- def _get_validator_for_test(test: ValidatorTest) -> Optional[CodeItem]:
20
+ class ValidatorTestEntry(BaseModel):
21
+ input: pathlib.Path
22
+ outcome: ValidatorOutcome
23
+ validator: Optional[CodeItem]
24
+
25
+
26
+ class CheckerTestEntry(BaseModel):
27
+ input: Optional[pathlib.Path] = None
28
+ output: Optional[pathlib.Path] = None
29
+ answer: Optional[pathlib.Path] = None
30
+ outcome: ExpectedOutcome
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
+
42
+
43
+ def _extract_validator_test_entries(
44
+ tests: List[ValidatorTest],
45
+ ) -> List[ValidatorTestEntry]:
46
+ res: List[ValidatorTestEntry] = []
47
+ for test in tests:
48
+ for input in pathlib.Path().glob(str(test.glob)):
49
+ if not input.is_file():
50
+ continue
51
+ res.append(
52
+ ValidatorTestEntry(
53
+ input=input, outcome=test.outcome, validator=test.validator
54
+ )
55
+ )
56
+ return sorted(res, key=lambda x: x.input.name)
57
+
58
+
59
+ def _extract_checker_test_entries(tests: List[CheckerTest]) -> List[CheckerTestEntry]:
60
+ res: List[CheckerTestEntry] = []
61
+ seen: Set[pathlib.Path] = set()
62
+ for test in tests:
63
+ for file in pathlib.Path().glob(str(test.glob)):
64
+ if not file.is_file():
65
+ continue
66
+ if file.suffix not in ['.in', '.out', '.ans']:
67
+ continue
68
+ basefile = file.with_suffix('')
69
+ if basefile in seen:
70
+ continue
71
+ seen.add(basefile)
72
+ input = basefile.with_suffix('.in')
73
+ output = basefile.with_suffix('.out')
74
+ answer = basefile.with_suffix('.ans')
75
+ res.append(
76
+ CheckerTestEntry(
77
+ input=input if input.is_file() else None,
78
+ output=output if output.is_file() else None,
79
+ answer=answer if answer.is_file() else None,
80
+ outcome=test.outcome,
81
+ )
82
+ )
83
+ return res
84
+
85
+
86
+ def _get_validator_for_test(test: ValidatorTestEntry) -> Optional[CodeItem]:
12
87
  pkg = package.find_problem_package_or_die()
13
88
  if test.validator is not None:
14
89
  return test.validator
@@ -18,20 +93,25 @@ def _get_validator_for_test(test: ValidatorTest) -> Optional[CodeItem]:
18
93
  async def run_validator_unit_tests(progress: StatusProgress):
19
94
  pkg = package.find_problem_package_or_die()
20
95
 
96
+ entries = _extract_validator_test_entries(pkg.unitTests.validator)
97
+
21
98
  vals: List[CodeItem] = []
22
- for test in pkg.unitTests.validator:
99
+ for test in entries:
23
100
  val = _get_validator_for_test(test)
24
101
  if val is not None:
25
102
  vals.append(val)
26
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
+
27
109
  compiled_validators = validators.compile_validators(vals, progress=progress)
28
110
 
29
111
  if progress:
30
112
  progress.update('Running validator unit tests...')
31
113
 
32
- console.console.rule('Validator tests', style='info')
33
-
34
- for i, test in enumerate(pkg.unitTests.validator):
114
+ for i, test in enumerate(entries):
35
115
  val = _get_validator_for_test(test)
36
116
  if val is None:
37
117
  console.console.print(
@@ -60,7 +140,10 @@ async def run_validator_unit_tests(progress: StatusProgress):
60
140
  if info.ok:
61
141
  console.console.print(' [status]Actual[/status] VALID')
62
142
  else:
63
- 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}')
64
147
 
65
148
 
66
149
  async def run_checker_unit_tests(progress: StatusProgress):
@@ -74,16 +157,21 @@ async def run_checker_unit_tests(progress: StatusProgress):
74
157
  )
75
158
  return
76
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
+
77
167
  compiled_digest = checkers.compile_checker(progress=progress)
78
168
 
79
169
  if progress:
80
170
  progress.update('Running checker unit tests...')
81
171
 
82
- console.console.rule('Checker tests', style='info')
83
-
84
172
  empty_file = package.get_empty_sentinel_path()
85
173
 
86
- for i, test in enumerate(pkg.unitTests.checker):
174
+ for i, test in enumerate(entries):
87
175
  result = await checkers.check(
88
176
  compiled_digest,
89
177
  run_log=None,
@@ -101,13 +189,15 @@ async def run_checker_unit_tests(progress: StatusProgress):
101
189
  else '[error]FAIL[/error]'
102
190
  )
103
191
 
104
- 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
+ )
105
195
  console.console.print(f' [status]Expected[/status] {test.outcome.name}')
106
196
 
107
197
  if not test.outcome.match(result.outcome):
108
198
  console.console.print(f' [status]Actual[/status] {result.outcome.name}')
109
- if result.message:
110
- console.console.print(f' [status]Message[/status] {result.message}')
199
+ if result.message:
200
+ console.console.print(f' [status]Message[/status] {result.message}')
111
201
 
112
202
 
113
203
  @syncer.sync
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rbx.cp
3
- Version: 0.5.48
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
@@ -44,9 +44,9 @@ rbx/box/presets/lock_schema.py,sha256=6sRPnyePOC8yy-5WcD5JRZdDJHf8loqbvpQ1IPiOU9
44
44
  rbx/box/presets/schema.py,sha256=mZmSPkQsw7eQM0lQN6er1MO_LiW1ObwwAZFDK0F5fxE,1962
45
45
  rbx/box/retries.py,sha256=tRk2K1bXw2xnwkAj2CsktRHTEhw7YKcPxMQTT6mCy-E,4707
46
46
  rbx/box/sanitizers/warning_stack.py,sha256=RI97_GJgdjTKIXY_r0EKp5h0qQQSDSdNDh5K7zINrqs,2861
47
- rbx/box/schema.py,sha256=P1jVaeqe4OcotAJOqu3T5WD8DR-amZyyq3cau5rPiM8,17086
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=veyBuz_7AbDFbdWi02jq_zLwXEkmgt0djXgVJU-OYCU,3755
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.48.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
192
- rbx_cp-0.5.48.dist-info/METADATA,sha256=LDeC-APwbLHB8kxUUmbWjS_pwbTSfIbOweMWlYRTU-M,3261
193
- rbx_cp-0.5.48.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
194
- rbx_cp-0.5.48.dist-info/entry_points.txt,sha256=qBTLBOeifT1F00LWaEewRRE_jQPgvH7BUdJfZ-dYsFU,57
195
- rbx_cp-0.5.48.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,,