rbx.cp 0.5.65__py3-none-any.whl → 0.5.66__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
@@ -32,7 +32,6 @@ from rbx.box.packaging import main as packaging
32
32
  from rbx.box.schema import CodeItem, ExpectedOutcome, TestcaseGroup
33
33
  from rbx.box.solutions import (
34
34
  estimate_time_limit,
35
- expand_solutions,
36
35
  get_exact_matching_solutions,
37
36
  get_matching_solutions,
38
37
  pick_solutions,
@@ -137,6 +136,13 @@ def ui():
137
136
  ui_pkg.start()
138
137
 
139
138
 
139
+ @app.command('diff', hidden=True)
140
+ def diff(path1: pathlib.Path, path2: pathlib.Path):
141
+ from rbx.box.ui import main as ui_pkg
142
+
143
+ ui_pkg.start_differ(path1, path2)
144
+
145
+
140
146
  @app.command('serve', hidden=True)
141
147
  def serve():
142
148
  from textual_serve.server import Server
@@ -243,7 +249,7 @@ async def run(
243
249
  tracked_solutions = set(
244
250
  await pick_solutions(
245
251
  tracked_solutions,
246
- extra_solutions=await expand_solutions(solutions or []),
252
+ extra_solutions=solutions,
247
253
  )
248
254
  )
249
255
  if not tracked_solutions:
@@ -479,7 +485,7 @@ async def irun(
479
485
  tracked_solutions = set(
480
486
  await pick_solutions(
481
487
  tracked_solutions,
482
- extra_solutions=await expand_solutions(solutions or []),
488
+ extra_solutions=solutions,
483
489
  )
484
490
  )
485
491
  if not tracked_solutions:
rbx/box/package.py CHANGED
@@ -150,6 +150,19 @@ def get_problem_cache_dir(root: pathlib.Path = pathlib.Path()) -> pathlib.Path:
150
150
  return cache_dir
151
151
 
152
152
 
153
+ @functools.cache
154
+ def get_problem_remote_dir(
155
+ platform: Optional[str] = None, root: pathlib.Path = pathlib.Path()
156
+ ) -> pathlib.Path:
157
+ remote_dir = get_problem_cache_dir(root) / '.remote'
158
+ remote_dir.mkdir(parents=True, exist_ok=True)
159
+
160
+ if platform is not None:
161
+ remote_dir = remote_dir / platform
162
+ remote_dir.mkdir(parents=True, exist_ok=True)
163
+ return remote_dir
164
+
165
+
153
166
  @functools.cache
154
167
  def get_problem_storage_dir(root: pathlib.Path = pathlib.Path()) -> pathlib.Path:
155
168
  storage_dir = get_problem_cache_dir(root) / '.storage'
@@ -4,6 +4,7 @@ import hashlib
4
4
  import os
5
5
  import pathlib
6
6
  import re
7
+ import shutil
7
8
  import typing
8
9
  from typing import Any, NoReturn, Optional, Tuple
9
10
 
@@ -248,13 +249,50 @@ class BocaUploader:
248
249
  '[error]Persistent error while uploading problem to BOCA website.[/error]'
249
250
  )
250
251
  console.console.print(
251
- '[warning]This might be caused by PHP max upload size limit (which usually defaults to 2MBF).[/warning]'
252
+ '[warning]This might be caused by PHP max upload size limit (which usually defaults to 2MB).[/warning]'
252
253
  )
253
254
  console.console.print(
254
255
  '[warning]Check [item]https://www.php.net/manual/en/ini.core.php#ini.sect.file-uploads[/item] for more information.[/warning]'
255
256
  )
256
257
  raise typer.Exit(1)
257
258
 
259
+ def download_run(self, run_number: int, site_number: int, into_dir: pathlib.Path):
260
+ url = f'{self.base_url}/admin/runedit.php?runnumber={run_number}&runsitenumber={site_number}'
261
+ _, html = self.open(
262
+ url,
263
+ error_msg=f'Error while downloading BOCA run [item]{run_number}-{site_number}[/item]',
264
+ )
265
+
266
+ soup = BeautifulSoup(html, 'html.parser')
267
+ rows = soup.select('tr')
268
+
269
+ href: Optional[str] = None
270
+ filename: Optional[pathlib.Path] = None
271
+
272
+ for row in rows:
273
+ row_text = row.select('td')[0].text.strip().lower()
274
+ if row_text != "team's code:":
275
+ continue
276
+ link_col = row.select_one('td:nth-of-type(2) a:nth-of-type(1)')
277
+ if link_col is None:
278
+ continue
279
+ href = str(link_col.attrs['href'])
280
+ filename = pathlib.Path(link_col.text.strip())
281
+ break
282
+
283
+ if href is None or filename is None:
284
+ self.raw_error(
285
+ "Error while downloading run:\nNo link to team's code found."
286
+ )
287
+
288
+ link = self.br.find_link(url=href)
289
+ tmp_file, _ = self.br.retrieve(link.absolute_url)
290
+ if tmp_file is None:
291
+ self.raw_error('Error while downloading run:\nDownloaded file is None.')
292
+ final_path = into_dir / filename.with_stem(f'{run_number}-{site_number}')
293
+ shutil.move(tmp_file, final_path)
294
+ return final_path
295
+
258
296
 
259
297
  @functools.lru_cache
260
298
  def get_boca_uploader(
rbx/box/solutions.py CHANGED
@@ -159,12 +159,10 @@ def compile_solutions(
159
159
 
160
160
  compiled_solutions = {}
161
161
 
162
- for solution in pkg.solutions:
163
- if (
164
- tracked_solutions is not None
165
- and str(solution.path) not in tracked_solutions
166
- ):
167
- continue
162
+ if tracked_solutions is None:
163
+ tracked_solutions = set(str(sol.path) for sol in pkg.solutions)
164
+
165
+ for solution in expand_solutions(list(tracked_solutions)):
168
166
  if progress:
169
167
  progress.update(f'Compiling solution {href(solution.path)}...')
170
168
  try:
@@ -254,11 +252,7 @@ def _get_solutions_for_skeleton(
254
252
  if verification.value >= VerificationLevel.ALL_SOLUTIONS.value or is_fast(sol)
255
253
  ]
256
254
  if tracked_solutions is not None:
257
- solutions = [
258
- solution
259
- for solution in solutions
260
- if str(solution.path) in tracked_solutions
261
- ]
255
+ solutions = expand_solutions(list(tracked_solutions))
262
256
  return solutions
263
257
 
264
258
 
@@ -726,28 +720,78 @@ def _get_solution_repr(sol: Solution) -> List[Tuple[str, str]]:
726
720
  ]
727
721
 
728
722
 
729
- async def expand_solutions(sols: List[str]) -> List[Solution]:
723
+ # TODO: refactor this function
724
+ def _expand_remote_sol(sol: str) -> Optional[str]:
725
+ from rbx.box.packaging.boca import upload as boca_upload
726
+
727
+ # Only BOCA supported for now.
728
+ assert sol.startswith('@')
729
+ sol = sol[1:]
730
+ if '-' in sol:
731
+ run_number, site_number = sol.split('-', 1)
732
+ run_number = int(run_number)
733
+ site_number = int(site_number)
734
+ else:
735
+ run_number = int(sol)
736
+ site_number = 1
737
+
738
+ expected_glob = (
739
+ package.get_problem_remote_dir('boca') / f'{run_number}-{site_number}.*'
740
+ )
741
+ expected_glob = expected_glob.relative_to(pathlib.Path.cwd())
742
+ for path in pathlib.Path.cwd().glob(str(expected_glob)):
743
+ if path.is_file():
744
+ relpath = path.resolve().relative_to(pathlib.Path.cwd())
745
+ console.console.print(f'Retrieving {href(relpath)} from cache...')
746
+ return str(relpath)
747
+
748
+ boca_uploader = boca_upload.get_boca_uploader()
749
+ boca_uploader.login()
750
+ sol_path = boca_uploader.download_run(
751
+ run_number, site_number, package.get_problem_remote_dir('boca')
752
+ )
753
+ console.console.print(f'Downloaded {href(sol_path)} from BOCA...')
754
+ return str(sol_path.resolve().relative_to(pathlib.Path.cwd()))
755
+
756
+
757
+ def _expand_remote_sols(sols: List[str]) -> List[str]:
758
+ res = []
759
+ for sol in sols:
760
+ if not sol.startswith('@'):
761
+ res.append(sol)
762
+ continue
763
+ expanded = _expand_remote_sol(sol)
764
+ if expanded is None:
765
+ continue
766
+ res.append(expanded)
767
+ return res
768
+
769
+
770
+ def expand_solutions(sols: List[str]) -> List[Solution]:
730
771
  pkg = package.find_problem_package_or_die()
731
- seen_sols = set(str(sol.path) for sol in pkg.solutions)
772
+ seen_sols = {str(sol.path): sol for sol in pkg.solutions}
732
773
 
733
- # Dedup sols.
734
- sols = [sol for sol in sols if str(sol) not in seen_sols]
774
+ # Download remote sols.
775
+ sols = _expand_remote_sols(sols)
735
776
 
736
777
  # Ensure sols exist.
737
778
  sols = [sol for sol in sols if pathlib.Path(sol).is_file()]
738
779
 
739
- return [
740
- Solution(path=pathlib.Path(sol), outcome=ExpectedOutcome.ACCEPTED)
741
- for sol in sols
742
- ]
780
+ res = []
781
+ for sol in sols:
782
+ if sol in seen_sols:
783
+ res.append(seen_sols[sol])
784
+ else:
785
+ res.append(
786
+ Solution(path=pathlib.Path(sol), outcome=ExpectedOutcome.ACCEPTED)
787
+ )
788
+ return res
743
789
 
744
790
 
745
791
  async def pick_solutions(
746
792
  tracked_solutions: Optional[Set[str]],
747
- extra_solutions: Optional[Iterable[Solution]] = None,
793
+ extra_solutions: Optional[List[str]] = None,
748
794
  ) -> List[str]:
749
- extra_sols = set(extra_solutions) if extra_solutions is not None else set()
750
-
751
795
  pkg = package.find_problem_package_or_die()
752
796
  # Store in a separate list to maintain order with the package declaration.
753
797
  import questionary
@@ -763,13 +807,15 @@ async def pick_solutions(
763
807
 
764
808
  seen_sols = set(str(sol.path) for sol in pkg.solutions)
765
809
 
766
- if extra_sols:
810
+ if extra_solutions is not None:
767
811
  # Add only new solutions.
768
812
  choices.extend(
769
813
  questionary.Choice(
770
- title=_get_solution_repr(sol), value=str(sol.path), checked=True
814
+ title=_get_solution_repr(sol),
815
+ value=str(sol.path),
816
+ checked=True,
771
817
  )
772
- for sol in extra_sols
818
+ for sol in expand_solutions(extra_solutions)
773
819
  if str(sol.path) not in seen_sols
774
820
  )
775
821
 
rbx/box/ui/css/app.tcss CHANGED
@@ -21,6 +21,20 @@ OptionList {
21
21
  border: solid $accent;
22
22
  }
23
23
 
24
+ DiffBox {
25
+ border: solid $accent;
26
+ height: 1fr;
27
+ width: 1fr;
28
+ Markdown {
29
+ height: 1fr;
30
+ width: 1fr;
31
+
32
+ .code_inline {
33
+ background: $background;
34
+ }
35
+ }
36
+ }
37
+
24
38
  Button {
25
39
  width: 1fr;
26
40
  background: $accent;
rbx/box/ui/main.py CHANGED
@@ -1,3 +1,4 @@
1
+ import pathlib
1
2
  from typing import Type
2
3
 
3
4
  from textual.app import App, ComposeResult
@@ -5,6 +6,7 @@ from textual.containers import Center
5
6
  from textual.screen import Screen
6
7
  from textual.widgets import Footer, Header, OptionList
7
8
 
9
+ from rbx.box.ui.screens.differ import DifferScreen
8
10
  from rbx.box.ui.screens.run_explorer import RunExplorerScreen
9
11
  from rbx.box.ui.screens.test_explorer import TestExplorerScreen
10
12
 
@@ -35,6 +37,25 @@ class rbxApp(App):
35
37
  self.push_screen(screen_cls())
36
38
 
37
39
 
40
+ class rbxDifferApp(App):
41
+ TITLE = 'rbx differ'
42
+ CSS_PATH = 'css/app.tcss'
43
+ BINDINGS = [('q', 'quit', 'Quit')]
44
+
45
+ def __init__(self, path1: pathlib.Path, path2: pathlib.Path):
46
+ super().__init__()
47
+ self.path1 = path1
48
+ self.path2 = path2
49
+
50
+ def on_mount(self):
51
+ self.push_screen(DifferScreen(self.path1, self.path2))
52
+
53
+
38
54
  def start():
39
55
  app = rbxApp()
40
56
  app.run()
57
+
58
+
59
+ def start_differ(path1: pathlib.Path, path2: pathlib.Path):
60
+ app = rbxDifferApp(path1, path2)
61
+ app.run()
@@ -0,0 +1,29 @@
1
+ import pathlib
2
+
3
+ from textual.app import ComposeResult
4
+ from textual.containers import Vertical
5
+ from textual.screen import Screen
6
+ from textual.widgets import Footer, Header
7
+
8
+ from rbx.box.ui.widgets.diff_box import DiffBox
9
+
10
+
11
+ class DifferScreen(Screen):
12
+ BINDINGS = [
13
+ ('q', 'quit', 'Quit'),
14
+ ]
15
+
16
+ def __init__(self, path1: pathlib.Path, path2: pathlib.Path):
17
+ super().__init__()
18
+ self.path1 = path1
19
+ self.path2 = path2
20
+
21
+ def compose(self) -> ComposeResult:
22
+ yield Header()
23
+ yield Footer()
24
+ with Vertical():
25
+ yield DiffBox()
26
+
27
+ def on_mount(self):
28
+ diff = self.query_one(DiffBox)
29
+ diff.paths = (self.path1, self.path2)
@@ -0,0 +1,38 @@
1
+ import difflib
2
+ import pathlib
3
+ from typing import Optional, Tuple
4
+
5
+ from rich.markdown import Markdown
6
+ from textual.app import ComposeResult
7
+ from textual.reactive import reactive
8
+ from textual.widget import Widget
9
+ from textual.widgets import RichLog
10
+
11
+
12
+ def compute_diff(file1: pathlib.Path, file2: pathlib.Path) -> str:
13
+ lines1 = file1.read_text().splitlines(keepends=True)
14
+ lines2 = file2.read_text().splitlines(keepends=True)
15
+ return ''.join(difflib.ndiff(lines1, lines2))
16
+
17
+
18
+ class DiffBox(Widget, can_focus=False):
19
+ paths: reactive[Optional[Tuple[pathlib.Path, pathlib.Path]]] = reactive(None)
20
+
21
+ def __init__(self):
22
+ super().__init__()
23
+
24
+ def compose(self) -> ComposeResult:
25
+ md = RichLog()
26
+ md.border_title = 'Differ'
27
+ yield md
28
+
29
+ async def watch_paths(self, paths: Optional[Tuple[pathlib.Path, pathlib.Path]]):
30
+ log = self.query_one(RichLog)
31
+ log.clear()
32
+ if paths is None:
33
+ return
34
+ file1, file2 = paths
35
+ md = Markdown(
36
+ f'```diff\n{compute_diff(file1, file2)}\n```', code_theme='monokai'
37
+ )
38
+ log.write(md)
rbx/box/unit.py CHANGED
@@ -148,8 +148,6 @@ async def run_validator_unit_tests(progress: StatusProgress):
148
148
 
149
149
  async def run_checker_unit_tests(progress: StatusProgress):
150
150
  pkg = package.find_problem_package_or_die()
151
- if not pkg.unitTests.checker:
152
- return
153
151
 
154
152
  if not package.get_checker():
155
153
  console.console.print(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rbx.cp
3
- Version: 0.5.65
3
+ Version: 0.5.66
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=KGaqXHnv2hCumZS2VdMezFfwFEQcSq0rt05_KZtuQAo,1570
7
7
  rbx/box/checkers.py,sha256=aGciafGNQ39UqndTEJRT3J8ngv_UigYxOT30yMzCwEI,12752
8
- rbx/box/cli.py,sha256=gCgXxUA243WmG7hXuDeGb0D9tF11dwzPtxobzKQM2DA,27445
8
+ rbx/box/cli.py,sha256=pURRvZSYS9fZCAheAFi6Dk1FHN4bw_xwT6n32U00WDQ,27532
9
9
  rbx/box/code.py,sha256=2oC1JbZiwfeg53ZICPig-KJYchqFRIZz-inlM-cLc7Q,19911
10
10
  rbx/box/compile.py,sha256=OJLthDQ921w9vyoE6Gk1Df54i5RwtRJ2YG-8XEfefcs,2489
11
11
  rbx/box/conftest.py,sha256=sEmciXSeDC-wmrZ1JSxbsUenKNP_VWW32mrCun2pY3I,1070
@@ -31,10 +31,10 @@ rbx/box/lazy_importing_main.py,sha256=6Z8As7qVFFT619xHH9Xt8VCH57NjC4aDxfAgkWiUwT
31
31
  rbx/box/lazy_importing_test.py,sha256=B0-b3y_DkxEmtVfu4NfmVsgVdFl6kRCsEL6GLMHJISo,628
32
32
  rbx/box/main.py,sha256=a8CYi77kOywPFly4-ucEIJLXQW-1NFp91kK2fA42YTE,86
33
33
  rbx/box/naming.py,sha256=pOG37X_wQM9CCSYwJIUf-b-ZHEs_nchO7wQEdP_quJg,1367
34
- rbx/box/package.py,sha256=pRsA5UsKNnD2uJcm8x01uQHUbCxoLbJvhoeqf3nyrew,14290
34
+ rbx/box/package.py,sha256=0di0idKhnyLI3I5MR9lAyXgX-hu5vOW23VyfKpOg-9E,14684
35
35
  rbx/box/packaging/boca/extension.py,sha256=EQALNEOv4zVDXSKs_dk11n92y7cBZVn8TogIK683lE0,890
36
36
  rbx/box/packaging/boca/packager.py,sha256=kiCcP9roRCiDU0Xr5PDKO83W1yN6cyg-EKMF9fxE0EY,11950
37
- rbx/box/packaging/boca/upload.py,sha256=y3DNMLNZyAwMdfBLUZRzxnr8cHwLegpH_NtgKW2Zwvw,9260
37
+ rbx/box/packaging/boca/upload.py,sha256=ItCqL9Ae2afwvU8mPoo95XXddTFMH3dlsMBnQ4cq3hw,10734
38
38
  rbx/box/packaging/contest_main.py,sha256=UsRfIdNmOf0iLUbzgjxzyECfMuCQINstG1SCClGHaUQ,2808
39
39
  rbx/box/packaging/main.py,sha256=kLFcMz0xOTZgtJh6P0Rr-zfq0NCbvx7HiQQ_0YmsvGg,3826
40
40
  rbx/box/packaging/moj/packager.py,sha256=FjghOe5CPlaF1GqK0NZgWVV_eYWpdTmz88bh04yeAyI,8708
@@ -52,7 +52,7 @@ rbx/box/retries.py,sha256=cZcNYLVHFDbhbeqMzxITgo8SYY8qzyxm0tIYcmWl1Ek,4877
52
52
  rbx/box/sanitizers/warning_stack.py,sha256=RI97_GJgdjTKIXY_r0EKp5h0qQQSDSdNDh5K7zINrqs,2861
53
53
  rbx/box/schema.py,sha256=y736-wZdGw56T6eDC_m7NAm2XRUdauBXJRQkQO79fpc,16264
54
54
  rbx/box/setter_config.py,sha256=9iObg6BwxQhFAhIOk31Jc0BDDpRYVGf3SyLIOsWIltM,4393
55
- rbx/box/solutions.py,sha256=LQio9FJL51XlEZ20QohWpgTbBiyTN7tZ72eY-K3p3DY,49981
55
+ rbx/box/solutions.py,sha256=peTeu4JrXUFy5yX1V9x-YCG8d8XOVxlMUI-FriQtYlc,51519
56
56
  rbx/box/solutions_test.py,sha256=PX1TQoRzNd9mi1SGsG7WFrpqFgNrNX5Kwt0mkwFdoOA,1749
57
57
  rbx/box/state.py,sha256=MMf3DvfQji0jKEliCHct2Tpp_0epL1tvP8HbHNArQIc,166
58
58
  rbx/box/statements/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -73,11 +73,12 @@ rbx/box/testcases/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
73
73
  rbx/box/testcases/main.py,sha256=_I7h_obRcpNLRQ6dDJDIE5NAvTyn5nBOhdsBhRA_PvU,5442
74
74
  rbx/box/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
75
  rbx/box/ui/captured_log.py,sha256=HPoV6LZohuECmjoqOdM_xFZbpICzQnI4n3rF-lf_b1Q,11634
76
- rbx/box/ui/css/app.tcss,sha256=LuP8dRgjk8zg68AV0cIty8RepGkTXR264AxRpflsSto,1845
77
- rbx/box/ui/main.py,sha256=0PENSCpk3zLLiG39lfdPSdLx3lCEIAXM_xpzyaDnQKs,1144
76
+ rbx/box/ui/css/app.tcss,sha256=gNNB1sG0mwMleZxP285RVvNy7SksLR3cnZejiPoWoOA,2115
77
+ rbx/box/ui/main.py,sha256=uTFqHvRHuNIz_ZNkvIS68Z1tpQYdl77iX8gHbfn6YOk,1680
78
78
  rbx/box/ui/screens/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
79
79
  rbx/box/ui/screens/build.py,sha256=DtABbf8mJNLn0tCjs5SA9wYBlbxble5-1JKQDlqzphk,156
80
80
  rbx/box/ui/screens/command.py,sha256=s29xHhvdQhgr9_E7LjggoKmSw3UuQQrJV3UQNnK97Mk,976
81
+ rbx/box/ui/screens/differ.py,sha256=Sp6xQwsFiqMl0tvbdhiPdh8AWUNPT8jshce3H7DhPrw,702
81
82
  rbx/box/ui/screens/error.py,sha256=k6Rs5maR_APKepMtPcDMSXo6BDKrP-pAnFFJgqmXDKE,496
82
83
  rbx/box/ui/screens/run.py,sha256=eKIfFRi-VbqKDxlhZDuOEdVl91XCndnmNIZyj_LMV0c,6028
83
84
  rbx/box/ui/screens/run_explorer.py,sha256=Q6VUhiqBaKr70bqA7pV5qKIQamLqUBCtxZnX2tDkap0,2651
@@ -87,12 +88,13 @@ rbx/box/ui/screens/test_explorer.py,sha256=p_MQmTvmNsB5j2E-CwN8G1mS756aWSMWGonkw
87
88
  rbx/box/ui/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
88
89
  rbx/box/ui/utils/run_ui.py,sha256=457xNZteBTb82Rcg5Cr3AmgBIHLOmRrF4BKmCRyxq3Q,3113
89
90
  rbx/box/ui/widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
91
+ rbx/box/ui/widgets/diff_box.py,sha256=4OxgwOvdm9nSVUKeKLzOQBlBweFu8LiTfp6g4ZkS5nM,1125
90
92
  rbx/box/ui/widgets/file_log.py,sha256=3wlrmkWR-EMibwlwXOJ5sGpTFwFEkRaGYo5fdmf8L3w,1704
91
93
  rbx/box/ui/widgets/interaction_box.py,sha256=WDHmpO5ck21y6hNdUVxvJ81jEg9TVJh39hFJUc5-Dos,1572
92
94
  rbx/box/ui/widgets/rich_log_box.py,sha256=mF565c_Y3RYUZ_GJEFj5Eb86SFjsib31wE5qu1K0UBM,91
93
95
  rbx/box/ui/widgets/test_output_box.py,sha256=yqeAb-JFvVx1Q7w_qJbDMWQigyGy4ofGECDxQ7P0_2s,3864
94
96
  rbx/box/ui/widgets/two_sided_test_output_box.py,sha256=L-ORiDwd6CP5DFpavrKGBaX0ZHkSoQqbJrGZ4BdFUWc,2289
95
- rbx/box/unit.py,sha256=PY96t8qnsHLsoJVanbDnrIx-s8Dada9Fj_v375MhvTw,6477
97
+ rbx/box/unit.py,sha256=4pkuGQ9MpRMuKznXr1hcRls_dWLZyQ_UMHOpZSesuXw,6428
96
98
  rbx/box/validators.py,sha256=oqlNhw7jivbbH5l8g3xwihPRy76AM7MA3G4A8nyI_V0,10416
97
99
  rbx/box/validators_test.py,sha256=WY4Ho-wlsPHc0YNuz0KFVd6KQ9ouuiou3w5_zMOZ4Fs,362
98
100
  rbx/checker.py,sha256=pj1jO3my48ru-qugbER5onccANCjoR0-PaFe3H3VGEY,4118
@@ -212,8 +214,8 @@ rbx/testcase.py,sha256=yKOq3CAJZ1YTmInvnoIs0u1iJnRj_X85XiWbLI-p9d8,1951
212
214
  rbx/testcase_rendering.py,sha256=nfmv6dSEqd4aR3TsaODwkKGK6AXty_DDKtWf_ejiQpI,2084
213
215
  rbx/testing_utils.py,sha256=x_PqD8Zd2PkN91NxVHUnSTs044-1WK5KKtttKQBXpFs,2083
214
216
  rbx/utils.py,sha256=SfR844_i0ebRDMkmS_w1YdZiWPc6h2RGADygewlWRbA,4845
215
- rbx_cp-0.5.65.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
216
- rbx_cp-0.5.65.dist-info/METADATA,sha256=TBx0q_SnA7K1cbAXvTbdgdLbCgTq7phrGbGBJSiKefk,3604
217
- rbx_cp-0.5.65.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
218
- rbx_cp-0.5.65.dist-info/entry_points.txt,sha256=qBTLBOeifT1F00LWaEewRRE_jQPgvH7BUdJfZ-dYsFU,57
219
- rbx_cp-0.5.65.dist-info/RECORD,,
217
+ rbx_cp-0.5.66.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
218
+ rbx_cp-0.5.66.dist-info/METADATA,sha256=jWKVFB_mcg1jfCuJqlpCGFb7MK1xCome8u0JzoNlgzI,3604
219
+ rbx_cp-0.5.66.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
220
+ rbx_cp-0.5.66.dist-info/entry_points.txt,sha256=qBTLBOeifT1F00LWaEewRRE_jQPgvH7BUdJfZ-dYsFU,57
221
+ rbx_cp-0.5.66.dist-info/RECORD,,