rbx.cp 0.5.37__py3-none-any.whl → 0.5.39__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/annotations.py CHANGED
@@ -1,4 +1,3 @@
1
- import importlib
2
1
  import importlib.resources
3
2
  import pathlib
4
3
  import re
rbx/box/code.py CHANGED
@@ -47,7 +47,7 @@ class SanitizationLevel(Enum):
47
47
 
48
48
  def should_sanitize(self) -> bool:
49
49
  cfg = setter_config.get_setter_config()
50
- if cfg.sanitizers.enabled:
50
+ if cfg.sanitizers.enabled or state.STATE.sanitized:
51
51
  return self.value >= SanitizationLevel.PREFER.value
52
52
  return self.value >= SanitizationLevel.FORCE.value
53
53
 
@@ -3,7 +3,7 @@ from typing import Annotated, List, Optional
3
3
  import typer
4
4
 
5
5
  from rbx import annotations, console
6
- from rbx.box import builder, cd, environment, package
6
+ from rbx.box import cd, environment, package
7
7
  from rbx.box.contest.build_contest_statements import build_statement
8
8
  from rbx.box.contest.contest_package import (
9
9
  find_contest_package_or_die,
@@ -44,6 +44,8 @@ def build(
44
44
  contest = find_contest_package_or_die()
45
45
  # At most run the validators, only in samples.
46
46
  if samples:
47
+ from rbx.box import builder
48
+
47
49
  for problem in contest.problems:
48
50
  console.console.print(
49
51
  f'Processing problem [item]{problem.short_name}[/item]...'
rbx/box/generators.py CHANGED
@@ -16,7 +16,6 @@ from rbx.box.schema import (
16
16
  GeneratorCall,
17
17
  Testcase,
18
18
  )
19
- from rbx.box.stressing import generator_parser
20
19
  from rbx.box.testcase_extractors import (
21
20
  GenerationMetadata,
22
21
  GenerationTestcaseEntry,
@@ -119,6 +118,8 @@ def compile_generators(
119
118
 
120
119
 
121
120
  def expand_generator_call(call: GeneratorCall) -> GeneratorCall:
121
+ from rbx.box.stressing import generator_parser
122
+
122
123
  vars = package.find_problem_package_or_die().expanded_vars
123
124
  generator_for_args = generator_parser.Generator(vars)
124
125
  parsed_args = generator_parser.parse(call.args or '')
@@ -0,0 +1,7 @@
1
+ import sys
2
+
3
+ from rbx.box import main # noqa
4
+
5
+ if __name__ == '__main__':
6
+ for m in sys.modules:
7
+ print(m)
@@ -0,0 +1,25 @@
1
+ import subprocess
2
+ import sys
3
+ from pathlib import Path
4
+
5
+ LAZY_MODULES = {
6
+ 'gitpython',
7
+ 'questionary',
8
+ 'fastapi',
9
+ 'requests',
10
+ 'pydantic_xml',
11
+ 'rbx.box.packaging.polygon.packager',
12
+ 'rbx.box.stresses',
13
+ }
14
+
15
+
16
+ def test_rich_not_imported_unnecessary():
17
+ file_path = Path(__file__).parent / 'lazy_importing_main.py'
18
+ result = subprocess.run(
19
+ [sys.executable, '-m', 'coverage', 'run', str(file_path)],
20
+ capture_output=True,
21
+ encoding='utf-8',
22
+ )
23
+ modules = result.stdout.splitlines()
24
+ modules = [module for module in modules if module in LAZY_MODULES]
25
+ assert not modules
rbx/box/main.py CHANGED
@@ -18,11 +18,9 @@ from typing import Annotated, List, Optional
18
18
  import rich
19
19
  import rich.prompt
20
20
  import typer
21
- import questionary
22
21
 
23
22
  from rbx import annotations, config, console, utils
24
23
  from rbx.box import (
25
- builder,
26
24
  cd,
27
25
  setter_config,
28
26
  state,
@@ -33,7 +31,6 @@ from rbx.box import (
33
31
  package,
34
32
  compile,
35
33
  presets,
36
- stresses,
37
34
  validators,
38
35
  )
39
36
  from rbx.box.contest import main as contest
@@ -58,43 +55,70 @@ app.add_typer(
58
55
  setter_config.app,
59
56
  name='config, cfg',
60
57
  cls=annotations.AliasGroup,
61
- help='Manage setter configuration.',
58
+ help='Manage setter configuration (sub-command).',
59
+ rich_help_panel='Configuration',
62
60
  )
63
61
  app.add_typer(
64
62
  build_statements.app,
65
63
  name='statements, st',
66
64
  cls=annotations.AliasGroup,
67
- help='Manage statements.',
65
+ help='Manage statements (sub-command).',
66
+ rich_help_panel='Deploying',
68
67
  )
69
68
  app.add_typer(
70
69
  download.app,
71
70
  name='download',
72
71
  cls=annotations.AliasGroup,
73
- help='Download an asset from supported repositories.',
72
+ help='Download an asset from supported repositories (sub-command).',
73
+ rich_help_panel='Management',
74
74
  )
75
75
  app.add_typer(
76
- presets.app, name='presets', cls=annotations.AliasGroup, help='Manage presets.'
76
+ presets.app,
77
+ name='presets',
78
+ cls=annotations.AliasGroup,
79
+ help='Manage presets (sub-command).',
80
+ rich_help_panel='Configuration',
77
81
  )
78
82
  app.add_typer(
79
83
  packaging.app,
80
84
  name='package, pkg',
81
85
  cls=annotations.AliasGroup,
82
- help='Build problem packages.',
86
+ help='Build problem packages (sub-command).',
87
+ rich_help_panel='Deploying',
83
88
  )
84
89
  app.add_typer(
85
- contest.app, name='contest', cls=annotations.AliasGroup, help='Contest management.'
90
+ contest.app,
91
+ name='contest',
92
+ cls=annotations.AliasGroup,
93
+ help='Manage contests (sub-command).',
94
+ rich_help_panel='Management',
86
95
  )
87
96
  app.add_typer(
88
97
  testcases.app,
89
98
  name='testcases, tc, t',
90
99
  cls=annotations.AliasGroup,
91
- help='Testcase management.',
100
+ help='Manage testcases (sub-command).',
101
+ rich_help_panel='Management',
92
102
  )
93
103
 
94
104
 
95
105
  @app.callback()
96
- def main():
106
+ def main(
107
+ sanitized: bool = typer.Option(
108
+ False,
109
+ '--sanitized',
110
+ '-s',
111
+ help='Whether to compile and run testlib components with sanitizers enabled. '
112
+ 'If you want to run the solutions with sanitizers enabled, use the "-s" flag in the corresponding run command.',
113
+ ),
114
+ ):
97
115
  state.STATE.run_through_cli = True
116
+ state.STATE.sanitized = sanitized
117
+ if sanitized:
118
+ console.console.print(
119
+ '[warning]Sanitizers are running just for testlib components.\n'
120
+ 'If you want to run the solutions with sanitizers enabled, use the [item]-s[/item] flag in the corresponding run command.[/warning]'
121
+ )
98
122
 
99
123
 
100
124
  # @app.command('ui', hidden=True)
@@ -103,7 +127,11 @@ def main():
103
127
  # ui_pkg.start()
104
128
 
105
129
 
106
- @app.command('edit, e', help='Open problem.rbx.yml in your default editor.')
130
+ @app.command(
131
+ 'edit, e',
132
+ rich_help_panel='Configuration',
133
+ help='Open problem.rbx.yml in your default editor.',
134
+ )
107
135
  @package.within_problem
108
136
  def edit():
109
137
  console.console.print('Opening problem definition in editor...')
@@ -113,13 +141,21 @@ def edit():
113
141
  config.open_editor(package.find_problem_yaml() or pathlib.Path())
114
142
 
115
143
 
116
- @app.command('build, b', help='Build all tests for the problem.')
144
+ @app.command(
145
+ 'build, b', rich_help_panel='Deploying', help='Build all tests for the problem.'
146
+ )
117
147
  @package.within_problem
118
148
  def build(verification: environment.VerificationParam):
149
+ from rbx.box import builder
150
+
119
151
  builder.build(verification=verification)
120
152
 
121
153
 
122
- @app.command('run, r', help='Build and run solution(s).')
154
+ @app.command(
155
+ 'run, r',
156
+ rich_help_panel='Testing',
157
+ help='Build and run solution(s).',
158
+ )
123
159
  @package.within_problem
124
160
  def run(
125
161
  verification: environment.VerificationParam,
@@ -189,6 +225,8 @@ def run(
189
225
  console.console.print('[error]No solutions selected. Exiting.[/error]')
190
226
  raise typer.Exit(1)
191
227
 
228
+ from rbx.box import builder
229
+
192
230
  if not builder.build(verification=verification, output=check):
193
231
  return
194
232
 
@@ -298,6 +336,7 @@ def _time_impl(check: bool, detailed: bool) -> Optional[int]:
298
336
 
299
337
  @app.command(
300
338
  'time, t',
339
+ rich_help_panel='Testing',
301
340
  help='Estimate a time limit for the problem based on a time limit formula and timings of accepted solutions.',
302
341
  )
303
342
  @package.within_problem
@@ -322,6 +361,8 @@ def time(
322
361
  )
323
362
  check = False
324
363
 
364
+ from rbx.box import builder
365
+
325
366
  verification = VerificationLevel.ALL_SOLUTIONS.value
326
367
  if not builder.build(verification=verification, output=check):
327
368
  return None
@@ -330,7 +371,9 @@ def time(
330
371
 
331
372
 
332
373
  @app.command(
333
- 'irun, ir', help='Build and run solution(s) by passing testcases in the CLI.'
374
+ 'irun, ir',
375
+ rich_help_panel='Testing',
376
+ help='Build and run solution(s) by passing testcases in the CLI.',
334
377
  )
335
378
  @package.within_problem
336
379
  def irun(
@@ -442,7 +485,11 @@ def irun(
442
485
  )
443
486
 
444
487
 
445
- @app.command('create, c', help='Create a new problem package.')
488
+ @app.command(
489
+ 'create, c',
490
+ rich_help_panel='Management',
491
+ help='Create a new problem package.',
492
+ )
446
493
  def create(
447
494
  name: str,
448
495
  preset: Annotated[
@@ -464,7 +511,11 @@ def create(
464
511
  creation.create(name)
465
512
 
466
513
 
467
- @app.command('stress', help='Run a stress test.')
514
+ @app.command(
515
+ 'stress',
516
+ rich_help_panel='Testing',
517
+ help='Run a stress test.',
518
+ )
468
519
  @package.within_problem
469
520
  def stress(
470
521
  name: Annotated[
@@ -522,6 +573,8 @@ def stress(
522
573
  )
523
574
  raise typer.Exit(1)
524
575
 
576
+ from rbx.box import stresses
577
+
525
578
  with utils.StatusProgress('Running stress...') as s:
526
579
  report = stresses.run_stress(
527
580
  name,
@@ -555,6 +608,8 @@ def stress(
555
608
  and group.generatorScript.path.suffix == '.txt'
556
609
  }
557
610
 
611
+ import questionary
612
+
558
613
  testgroup = questionary.select(
559
614
  'Choose the testgroup to add the tests to.\nOnly test groups that have a .txt generatorScript are shown below: ',
560
615
  choices=list(groups_by_name) + ['(create new script)', '(skip)'],
@@ -614,7 +669,11 @@ def stress(
614
669
  break
615
670
 
616
671
 
617
- @app.command('compile', help='Compile an asset given its path.')
672
+ @app.command(
673
+ 'compile',
674
+ rich_help_panel='Testing',
675
+ help='Compile an asset given its path.',
676
+ )
618
677
  @package.within_problem
619
678
  def compile_command(
620
679
  path: Annotated[
@@ -635,6 +694,8 @@ def compile_command(
635
694
  ),
636
695
  ):
637
696
  if path is None:
697
+ import questionary
698
+
638
699
  path = questionary.path("What's the path to your asset?").ask()
639
700
  if path is None:
640
701
  console.console.print('[error]No path specified.[/error]')
@@ -643,7 +704,11 @@ def compile_command(
643
704
  compile.any(path, sanitized, warnings)
644
705
 
645
706
 
646
- @app.command('validate', help='Run the validator in a one-off fashion, interactively.')
707
+ @app.command(
708
+ 'validate',
709
+ rich_help_panel='Testing',
710
+ help='Run the validator in a one-off fashion, interactively.',
711
+ )
647
712
  @package.within_problem
648
713
  def validate(
649
714
  path: Annotated[
@@ -676,7 +741,11 @@ def validate(
676
741
  validators.print_validation_report([info])
677
742
 
678
743
 
679
- @app.command('environment, env', help='Set or show the current box environment.')
744
+ @app.command(
745
+ 'environment, env',
746
+ rich_help_panel='Configuration',
747
+ help='Set or show the current box environment.',
748
+ )
680
749
  def environment_command(
681
750
  env: Annotated[Optional[str], typer.Argument()] = None,
682
751
  install_from: Annotated[
@@ -721,6 +790,7 @@ def environment_command(
721
790
 
722
791
  @app.command(
723
792
  'activate',
793
+ rich_help_panel='Configuration',
724
794
  help='Activate the environment of the current preset used by the package.',
725
795
  )
726
796
  @cd.within_closest_package
@@ -755,7 +825,11 @@ def activate():
755
825
  console.console.print(f'[success]Preset [item]{preset.name}[/item] is activated.')
756
826
 
757
827
 
758
- @app.command('languages', help='List the languages available in this environment')
828
+ @app.command(
829
+ 'languages',
830
+ rich_help_panel='Configuration',
831
+ help='List the languages available in this environment',
832
+ )
759
833
  def languages():
760
834
  env = environment.get_environment()
761
835
 
@@ -771,7 +845,11 @@ def languages():
771
845
  console.console.print()
772
846
 
773
847
 
774
- @app.command('clear, clean', help='Clears cache and build directories.')
848
+ @app.command(
849
+ 'clear, clean',
850
+ rich_help_panel='Management',
851
+ help='Clears cache and build directories.',
852
+ )
775
853
  @cd.within_closest_package
776
854
  def clear():
777
855
  console.console.print('Cleaning cache and build directories...')
@@ -14,7 +14,6 @@ from rbx.box.packaging.packager import (
14
14
  BuiltContestStatement,
15
15
  BuiltProblemPackage,
16
16
  )
17
- from rbx.box.packaging.polygon.packager import PolygonContestPackager, PolygonPackager
18
17
 
19
18
  app = typer.Typer(no_args_is_help=True, cls=annotations.AliasGroup)
20
19
 
@@ -77,6 +76,11 @@ def run_contest_packager(
77
76
  def polygon(
78
77
  verification: environment.VerificationParam,
79
78
  ):
79
+ from rbx.box.packaging.polygon.packager import (
80
+ PolygonContestPackager,
81
+ PolygonPackager,
82
+ )
83
+
80
84
  run_contest_packager(
81
85
  PolygonContestPackager, PolygonPackager, verification=verification
82
86
  )
rbx/box/packaging/main.py CHANGED
@@ -5,11 +5,9 @@ from typing import Type
5
5
  import typer
6
6
 
7
7
  from rbx import annotations, console
8
- from rbx.box import builder, environment, package
8
+ from rbx.box import environment, package
9
9
  from rbx.box.package import get_build_path
10
- from rbx.box.packaging.boca.packager import BocaPackager
11
10
  from rbx.box.packaging.packager import BasePackager, BuiltStatement
12
- from rbx.box.packaging.polygon.packager import PolygonPackager
13
11
  from rbx.box.statements.build_statements import build_statement
14
12
 
15
13
  app = typer.Typer(no_args_is_help=True, cls=annotations.AliasGroup)
@@ -19,6 +17,8 @@ def run_packager(
19
17
  packager_cls: Type[BasePackager],
20
18
  verification: environment.VerificationParam,
21
19
  ) -> pathlib.Path:
20
+ from rbx.box import builder
21
+
22
22
  if not builder.verify(verification=verification):
23
23
  console.console.print(
24
24
  '[error]Build or verification failed, check the report.[/error]'
@@ -58,6 +58,8 @@ def run_packager(
58
58
  def polygon(
59
59
  verification: environment.VerificationParam,
60
60
  ):
61
+ from rbx.box.packaging.polygon.packager import PolygonPackager
62
+
61
63
  run_packager(PolygonPackager, verification=verification)
62
64
 
63
65
 
@@ -65,4 +67,6 @@ def polygon(
65
67
  def boca(
66
68
  verification: environment.VerificationParam,
67
69
  ):
70
+ from rbx.box.packaging.boca.packager import BocaPackager
71
+
68
72
  run_packager(BocaPackager, verification=verification)
@@ -3,8 +3,6 @@ import shutil
3
3
  import tempfile
4
4
  from typing import Annotated, Iterable, List, Optional, Sequence, Union
5
5
 
6
- import git
7
- import questionary
8
6
  import rich
9
7
  import rich.prompt
10
8
  import typer
@@ -306,6 +304,8 @@ def optionally_install_environment_from_preset(
306
304
  if env_path.is_file():
307
305
  if digest_file(preset_env_path) == digest_file(env_path):
308
306
  return
307
+ import questionary
308
+
309
309
  overwrite = questionary.confirm(
310
310
  'Preset environment file has changed. Overwrite?',
311
311
  default=False,
@@ -371,6 +371,8 @@ def _install(root: pathlib.Path = pathlib.Path(), force: bool = False):
371
371
 
372
372
 
373
373
  def install_from_remote(fetch_info: PresetFetchInfo, force: bool = False) -> str:
374
+ import git
375
+
374
376
  assert fetch_info.fetch_uri is not None
375
377
  with tempfile.TemporaryDirectory() as d:
376
378
  console.console.print(
@@ -484,6 +486,8 @@ def update(
484
486
 
485
487
  for preset_name in presets:
486
488
  if preset_name == LOCAL:
489
+ import questionary
490
+
487
491
  if not questionary.confirm(
488
492
  'Updating local preset will remove all custom changes you made to the preset.',
489
493
  default=False,
rbx/box/setter_config.py CHANGED
@@ -1,5 +1,4 @@
1
1
  import functools
2
- import importlib
3
2
  import importlib.resources
4
3
  import pathlib
5
4
  import shlex
rbx/box/solutions.py CHANGED
@@ -7,7 +7,6 @@ import shutil
7
7
  from collections.abc import Iterator
8
8
  from typing import Dict, Iterable, List, Optional, Set, Tuple
9
9
 
10
- import questionary
11
10
  import rich
12
11
  import rich.live
13
12
  import rich.markup
@@ -636,13 +635,22 @@ async def run_and_print_interactive_solutions(
636
635
 
637
636
  for item in items:
638
637
  sol = pkg.solutions[item.solution_index]
639
- with utils.no_progress(progress):
640
- _print_solution_header(sol, console.console, is_irun=True)
638
+
639
+ if progress:
640
+ progress.update(f'Running [item]{sol.path}[/item]...')
641
641
 
642
642
  eval = await item.eval()
643
643
 
644
+ with utils.no_progress(progress):
645
+ console.console.print(get_testcase_markup_verdict(eval), end=' ')
646
+ _print_solution_header(sol, console.console, is_irun=True)
647
+ _print_solution_outcome(
648
+ sol, [eval], console.console, verification, subset=True
649
+ )
650
+
644
651
  stdout_path = eval.log.stdout_absolute_path
645
652
  if print:
653
+ console.console.rule('Output', style='status')
646
654
  if (
647
655
  eval.testcase.output is not None
648
656
  and stdout_path is not None
@@ -674,6 +682,8 @@ def pick_solutions(tracked_solutions: Optional[Set[str]]) -> List[str]:
674
682
  tracked_solutions = set(str(sol.path) for sol in pkg.solutions)
675
683
 
676
684
  # Store in a separate list to maintain order with the package declaration.
685
+ import questionary
686
+
677
687
  choices = [
678
688
  questionary.Choice(title=_get_solution_repr(sol), value=str(sol.path))
679
689
  for sol in pkg.solutions
@@ -779,14 +789,17 @@ def _print_solution_outcome(
779
789
  evals: List[Evaluation],
780
790
  console: rich.console.Console,
781
791
  verification: VerificationLevel = VerificationLevel.NONE,
792
+ subset: bool = False,
782
793
  ) -> bool:
783
794
  pkg = package.find_problem_package_or_die()
784
795
 
785
796
  has_plain_tle = False
797
+ all_verdicts = set()
786
798
  bad_verdicts = set()
787
799
  no_tle_bad_verdicts = set()
788
800
  has_sanitizer_warnings = False
789
801
  for eval in evals:
802
+ all_verdicts.add(eval.result.outcome)
790
803
  if eval.result.outcome != Outcome.ACCEPTED:
791
804
  bad_verdicts.add(eval.result.outcome)
792
805
  if (
@@ -807,18 +820,27 @@ def _print_solution_outcome(
807
820
  matched_bad_verdicts = bad_verdicts - unmatched_bad_verdicts
808
821
  expected_outcome_is_bad = not solution.outcome.match(Outcome.ACCEPTED)
809
822
 
810
- if unmatched_bad_verdicts or (expected_outcome_is_bad and not matched_bad_verdicts):
823
+ has_failed = unmatched_bad_verdicts or (
824
+ expected_outcome_is_bad and not matched_bad_verdicts and not subset
825
+ )
826
+ if has_failed:
811
827
  console.print('[error]FAILED[/error]', end=' ')
812
828
  else:
813
829
  console.print('[success]OK[/success]', end=' ')
814
830
 
815
- console.print(f'Expected: {solution.outcome}', end='')
816
-
817
- if unmatched_bad_verdicts:
818
- unmatched_bad_verdicts_names = set(v.name for v in unmatched_bad_verdicts)
819
- console.print(f', got: {" ".join(unmatched_bad_verdicts_names)}', end='')
820
- elif expected_outcome_is_bad and not matched_bad_verdicts:
821
- console.print(f', got: {Outcome.ACCEPTED.name}', end='')
831
+ if has_failed or not subset:
832
+ console.print(f'Expected: {solution.outcome}', end='')
833
+ elif subset:
834
+ all_verdicts_names = ' '.join(v.name for v in all_verdicts)
835
+ console.print(f'Got: {all_verdicts_names}', end='')
836
+
837
+ if has_failed or not subset:
838
+ # Only print verdicts if not subset.
839
+ if unmatched_bad_verdicts:
840
+ unmatched_bad_verdicts_names = set(v.name for v in unmatched_bad_verdicts)
841
+ console.print(f', got: {" ".join(unmatched_bad_verdicts_names)}', end='')
842
+ elif expected_outcome_is_bad and not matched_bad_verdicts and not subset:
843
+ console.print(f', got: {Outcome.ACCEPTED.name}', end='')
822
844
 
823
845
  console.print()
824
846
  evals_time = _get_evals_time_in_ms(evals)
rbx/box/state.py CHANGED
@@ -4,6 +4,7 @@ import dataclasses
4
4
  @dataclasses.dataclass
5
5
  class State:
6
6
  run_through_cli: bool = False
7
+ sanitized: bool = False
7
8
 
8
9
 
9
10
  STATE = State()
@@ -6,7 +6,7 @@ from typing import Annotated, Dict, List, Optional, Tuple
6
6
  import typer
7
7
 
8
8
  from rbx import annotations, console
9
- from rbx.box import builder, environment, package
9
+ from rbx.box import environment, package
10
10
  from rbx.box.schema import Package
11
11
  from rbx.box.statements.builders import (
12
12
  BUILDER_LIST,
@@ -333,6 +333,8 @@ def build(
333
333
  ):
334
334
  # At most run the validators, only in samples.
335
335
  if samples:
336
+ from rbx.box import builder
337
+
336
338
  if not builder.build(
337
339
  verification=verification,
338
340
  groups=set(['samples']),
@@ -11,12 +11,6 @@ from pydantic import BaseModel
11
11
 
12
12
  from rbx import console, utils
13
13
  from rbx.box.schema import Package, Primitive, Testcase
14
- from rbx.box.statements.latex import (
15
- MAX_PDFLATEX_RUNS,
16
- Latex,
17
- decode_latex_output,
18
- should_rerun,
19
- )
20
14
  from rbx.box.statements.latex_jinja import (
21
15
  JinjaDictWrapper,
22
16
  render_latex_template,
@@ -355,6 +349,13 @@ class TeX2PDFBuilder(StatementBuilder):
355
349
  item: StatementBuilderItem,
356
350
  verbose: bool = False,
357
351
  ) -> bytes:
352
+ from rbx.box.statements.latex import (
353
+ MAX_PDFLATEX_RUNS,
354
+ Latex,
355
+ decode_latex_output,
356
+ should_rerun,
357
+ )
358
+
358
359
  latex = Latex(input.decode())
359
360
  latex_result = latex.build_pdf(context.root)
360
361
  pdf = latex_result.pdf
@@ -10,12 +10,6 @@ from rbx.box.statements.builders import (
10
10
  StatementBuilderContest,
11
11
  StatementCodeLanguage,
12
12
  )
13
- from rbx.box.statements.latex import (
14
- MAX_PDFLATEX_RUNS,
15
- Latex,
16
- decode_latex_output,
17
- should_rerun,
18
- )
19
13
  from rbx.box.statements.schema import Joiner, JoinerType, JoinTexToPDF, StatementType
20
14
 
21
15
 
@@ -84,6 +78,13 @@ class TeX2PDFJoiner(StatementJoiner):
84
78
  contest: StatementBuilderContest,
85
79
  verbose: bool = False,
86
80
  ) -> bytes:
81
+ from rbx.box.statements.latex import (
82
+ MAX_PDFLATEX_RUNS,
83
+ Latex,
84
+ decode_latex_output,
85
+ should_rerun,
86
+ )
87
+
87
88
  latex = Latex(input.decode())
88
89
  latex_result = latex.build_pdf(context.root)
89
90
  pdf = latex_result.pdf
rbx/config.py CHANGED
@@ -1,5 +1,4 @@
1
1
  import functools
2
- import importlib
3
2
  import importlib.resources
4
3
  import os
5
4
  import pathlib
@@ -8,7 +7,6 @@ import subprocess
8
7
  import tempfile
9
8
  from typing import Any, Dict, List, Optional
10
9
 
11
- import requests
12
10
  import typer
13
11
  from pydantic import BaseModel
14
12
 
@@ -109,6 +107,8 @@ def get_app_file(path: pathlib.Path) -> pathlib.Path:
109
107
 
110
108
 
111
109
  def _download_checker(name: str, save_at: pathlib.Path):
110
+ import requests
111
+
112
112
  console.print(f'Downloading checker {name}...')
113
113
  r = requests.get(
114
114
  f'https://raw.githubusercontent.com/MikeMirzayanov/testlib/master/checkers/{name}'
@@ -121,6 +121,8 @@ def _download_checker(name: str, save_at: pathlib.Path):
121
121
 
122
122
 
123
123
  def _download_testlib(save_at: pathlib.Path):
124
+ import requests
125
+
124
126
  console.print('Downloading testlib.h...')
125
127
  r = requests.get(
126
128
  'https://raw.githubusercontent.com/MikeMirzayanov/testlib/master/testlib.h'
@@ -136,6 +138,8 @@ def _download_testlib(save_at: pathlib.Path):
136
138
 
137
139
 
138
140
  def _download_jngen(save_at: pathlib.Path):
141
+ import requests
142
+
139
143
  console.print('Downloading jngen.h...')
140
144
  r = requests.get('https://raw.githubusercontent.com/ifsmirnov/jngen/master/jngen.h')
141
145
 
@@ -149,6 +153,8 @@ def _download_jngen(save_at: pathlib.Path):
149
153
 
150
154
 
151
155
  def _download_bits_stdcpp(save_at: pathlib.Path):
156
+ import requests
157
+
152
158
  console.print('Downloading bits/stdc++.h...')
153
159
  r = requests.get(
154
160
  'https://raw.githubusercontent.com/tekfyl/bits-stdc-.h-for-mac/master/stdc%2B%2B.h'
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import importlib
4
3
  import importlib.resources
5
4
  import logging
6
5
  import os
rbx/testing_utils.py CHANGED
@@ -1,4 +1,3 @@
1
- import importlib
2
1
  import importlib.resources
3
2
  import pathlib
4
3
 
rbx/utils.py CHANGED
@@ -13,7 +13,6 @@ import rich.status
13
13
  import ruyaml
14
14
  import typer
15
15
  import yaml
16
- from fastapi.encoders import jsonable_encoder
17
16
  from pydantic import BaseModel
18
17
  from rich import text
19
18
  from rich.highlighter import JSONHighlighter
@@ -74,9 +73,7 @@ def model_json(model: BaseModel) -> str:
74
73
  def model_to_yaml(model: BaseModel) -> str:
75
74
  path = ensure_schema(model.__class__)
76
75
  return f'# yaml-language-server: $schema={path}\n\n' + yaml.dump(
77
- jsonable_encoder(
78
- model.model_dump(mode='json', exclude_unset=True, exclude_none=True)
79
- ),
76
+ model.model_dump(mode='json', exclude_unset=True, exclude_none=True),
80
77
  sort_keys=False,
81
78
  allow_unicode=True,
82
79
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rbx.cp
3
- Version: 0.5.37
3
+ Version: 0.5.39
4
4
  Summary:
5
5
  Author: Roberto Sales
6
6
  Requires-Python: >=3.9,<4.0
@@ -1,11 +1,11 @@
1
1
  rbx/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- rbx/annotations.py,sha256=Z3jBUyZoXkrz34jko3Rft0bnMME6nWb0vsV5I3HlgR0,3064
2
+ rbx/annotations.py,sha256=LXbVOSkE9kwcxEirsOMo10cEnvol854QvaCBIjhWyE8,3047
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=qIXgV-div21Tw8knwCrTtHyDCgYwBrJc0I5b9KhZuKM,3577
6
6
  rbx/box/cd.py,sha256=9a_SOnzoJBXxxffp4Wbf3UKXIwKuN3Hvj7K6SocALwE,1194
7
7
  rbx/box/checkers.py,sha256=VpgDzevOK7hrffG2zJGxquNiu-a9Fl3wquLn7xadcK0,6285
8
- rbx/box/code.py,sha256=UFy7jOeTvxtIu9pdVUDv2-D6IW-beJGPC3uCanIKZh0,13412
8
+ rbx/box/code.py,sha256=zkYWHXV4PxuAm3_4VtW9fptLQ34euI8BTAKNukXWCig,13437
9
9
  rbx/box/compile.py,sha256=OJLthDQ921w9vyoE6Gk1Df54i5RwtRJ2YG-8XEfefcs,2489
10
10
  rbx/box/conftest.py,sha256=sEmciXSeDC-wmrZ1JSxbsUenKNP_VWW32mrCun2pY3I,1070
11
11
  rbx/box/contest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -14,40 +14,42 @@ rbx/box/contest/contest_package.py,sha256=OaUbpBtkhkgOPzJ1ccI_Vq4FMSaJvZm3gMOKfV
14
14
  rbx/box/contest/contest_utils.py,sha256=TDE7I6YQJlu4dQd68wzOp019bNgqiT0RlM-LMQMjL9w,301
15
15
  rbx/box/contest/main.py,sha256=oL-GbyLKdpMjIWiSuWTQgRhQ9hcb7DuNn0axkunx0io,7436
16
16
  rbx/box/contest/schema.py,sha256=JMAig5WpaOahNgAHxA9vX4zYeVYDxpjKP_PFGvmmkE0,4954
17
- rbx/box/contest/statements.py,sha256=Pe4uo1hxvEON8O11VAzsOP3DxUel0vmwiAmolh4ltEs,2910
17
+ rbx/box/contest/statements.py,sha256=lzfGc_9NtFpN_TlRIP8jRg9QXmPjbdC6uI4B7NRrNKs,2938
18
18
  rbx/box/creation.py,sha256=Evz7K6JoarD-4JJQsZsgoxU9FgCF9Z7-LfuroG4Cqls,2444
19
19
  rbx/box/deferred.py,sha256=II3X9e87JCOZtmspnHh-n4PFqh-FsH_oc0XJHZ9ZYVQ,691
20
20
  rbx/box/download.py,sha256=MFP-R26JiYGAP89I0TK-0fYc69Fsd20tsBqgtRCy5AE,2234
21
21
  rbx/box/environment.py,sha256=47NtyuVC6zSQKAtQaXPEXvqcD-KJiuWRpWF8pYvcG4c,11158
22
22
  rbx/box/extensions.py,sha256=Von8kIeXvNFTkGlMRMTvL2HIHPwlkuiMswr-ydbGV1w,519
23
23
  rbx/box/formatting.py,sha256=3phFRHzqVXj4Ok1yDhCq6Clbw6KlqwJNpMhs--oTWFI,405
24
- rbx/box/generators.py,sha256=nJx4U0Cd5DgHIf1n-06c03hyLi5AVdH9tvi0Hnh8iQ8,12158
24
+ rbx/box/generators.py,sha256=6hm1G4BHmq6Nmbbm2aXHewgVntEjQ5HJtPu6z-sTVrY,12163
25
25
  rbx/box/generators_test.py,sha256=ZRqdolU7YE8HXjxr0met5oGn4DCJ5erdsMt5cSOoXIw,1945
26
- rbx/box/main.py,sha256=0lrPLJTGvatcGZCYgLRKKaRkWKEFmNKyA48Shm-uof8,24308
26
+ rbx/box/lazy_importing_main.py,sha256=6Z8As7qVFFT619xHH9Xt8VCH57NjC4aDxfAgkWiUwT8,116
27
+ rbx/box/lazy_importing_test.py,sha256=B0-b3y_DkxEmtVfu4NfmVsgVdFl6kRCsEL6GLMHJISo,628
28
+ rbx/box/main.py,sha256=fvT4tslHFKOvOebcukrhKc4-E1OT4hkvlObuzGuOJ4I,25975
27
29
  rbx/box/package.py,sha256=80SDHvSzfraCUYutMn_kwsFsmmrSZiaeRHhhrWGmIY4,12081
28
30
  rbx/box/packaging/boca/extension.py,sha256=hQhcbocNfW2ESv5RalS1wf6uvOoOfOnR_gHvbXUbSzY,852
29
31
  rbx/box/packaging/boca/packager.py,sha256=FOhSRg5K5Y4qNB0WyTR3DKgrpObf9I0JbyGpJHOtxpo,10673
30
- rbx/box/packaging/contest_main.py,sha256=Hbxh7geNqrePs5tWhPgdg5W2qhaW5yoreK_VP0Sm19k,2727
31
- rbx/box/packaging/main.py,sha256=ly_wBtJUmeC4JxrtTq0bPofGXhtSN7rpghWqPYyjYhE,2237
32
+ rbx/box/packaging/contest_main.py,sha256=nMdgPE4OK_tsnUMdRI1cJwLpgxGrwW_mJjox0oOALWw,2757
33
+ rbx/box/packaging/main.py,sha256=xd6nohKwkKH1ltyVO_uWwydlx47NkJOpkuTtIk46GVw,2271
32
34
  rbx/box/packaging/packager.py,sha256=suCT_SLnWa915rV2j8VFqzH43HGKRTr9mGGlrvj45aw,3267
33
35
  rbx/box/packaging/polygon/packager.py,sha256=HNpxP2nclLChSnrQtkT7tLwDdXHl1dzXMIF5RZwr9M4,10811
34
36
  rbx/box/packaging/polygon/test.py,sha256=bgEju5PwudgyfwxXJagm8fM6CJVlWM6l_-2q1V-oKaQ,3069
35
37
  rbx/box/packaging/polygon/xml_schema.py,sha256=-r24bCeRMGLrGGoT9FIgmqr87xHL-JzrFaR6bztbYtw,2703
36
- rbx/box/presets/__init__.py,sha256=jivkMH5lWuNpwg4HExpacgPo7RqaENqmrE86aq3CJ6A,18643
38
+ rbx/box/presets/__init__.py,sha256=BwmjBw8wF8yiZFjCYBjMk-HGMZaRwhlfszbWAj3B0vw,18689
37
39
  rbx/box/presets/fetch.py,sha256=F-BCOlvEBEyDqtOhiDuGPn4EDtA4Bwm-fqHJ7zZGlW8,1975
38
40
  rbx/box/presets/lock_schema.py,sha256=6sRPnyePOC8yy-5WcD5JRZdDJHf8loqbvpQ1IPiOU9s,349
39
41
  rbx/box/presets/schema.py,sha256=mZmSPkQsw7eQM0lQN6er1MO_LiW1ObwwAZFDK0F5fxE,1962
40
42
  rbx/box/retries.py,sha256=z7cIh1QmLVUsTr3Attt_28dbwNg6KWTwpulcWCFwMPo,4667
41
43
  rbx/box/sanitizers/warning_stack.py,sha256=RI97_GJgdjTKIXY_r0EKp5h0qQQSDSdNDh5K7zINrqs,2861
42
44
  rbx/box/schema.py,sha256=I7Uh_KXBqAX8fHZr4s9LGPEFHxyBttoLSq_hYJefwto,14581
43
- rbx/box/setter_config.py,sha256=ZM7_G2tbaixaFr0NvRaXkowwfxSWF2Gb4XHBsr2Prpc,4279
44
- rbx/box/solutions.py,sha256=mXW1o3uGNFYmQhfZJzIxfs7nCR7WfWtJtLypLFGriuE,44014
45
+ rbx/box/setter_config.py,sha256=s53talhwM6FTGDCcBhY7IlZ6_6mJ3PMp6V4kTtaSs50,4262
46
+ rbx/box/solutions.py,sha256=IggS2QdOkHuz6G7i2eI32ILT7G5FZL0cy49xnPtAGb8,44818
45
47
  rbx/box/solutions_test.py,sha256=txjAg-n_pkHHolw4WF4foBrpJAL-llAXw6fUIrGURMc,1716
46
- rbx/box/state.py,sha256=yTpjfASpnSXkRB3JiDNvCg5b9JNnNxuYT4uMcbdr59s,109
48
+ rbx/box/state.py,sha256=cBeEkJXSXLwYmCT0yLq2TjycusKFpjOeW8yPRIi6K-o,137
47
49
  rbx/box/statements/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
- rbx/box/statements/build_statements.py,sha256=qR6WxUNvSQTBs241qH-qDRbD8IoN_hKeZ2TwY7NXJBQ,12024
49
- rbx/box/statements/builders.py,sha256=pKevMe3GwiXN_k0L2l155sY1rSLneSs0DLJ5T7WhxKQ,11152
50
- rbx/box/statements/joiners.py,sha256=ZbxomnMjEFT8yf5WSWUB4tBa3DL3AhjGEuh8uqHyDdg,2837
50
+ rbx/box/statements/build_statements.py,sha256=S23fqp6kmw97PAfk5zn2MVK8BhH1wjRMm2-kKdAOwlI,12052
51
+ rbx/box/statements/builders.py,sha256=L67i-CP6ftDm2wR6VWywTd3ad7-fhWSSMfaN66Gt13s,11201
52
+ rbx/box/statements/joiners.py,sha256=jItNXkAbTjFQpPMgfDMW86n3vMTbaE8sgo9I8Yf4Txg,2886
51
53
  rbx/box/statements/latex.py,sha256=LkcHwXjMFxbw--Gj9T1VkFKQFsXhY9dN7xZHpZycNW8,1346
52
54
  rbx/box/statements/latex_jinja.py,sha256=7WBfn1h8DpqCAmSE6Av64HfURMnJ2AO4QX1CD72sz5E,7096
53
55
  rbx/box/statements/schema.py,sha256=ES8EUE9JE_uJlDwQx1kZd_5nQJyABtlnjP5IjbWaJ-0,3897
@@ -68,7 +70,7 @@ rbx/box/validators.py,sha256=WX6PR-eVXm9ghv0cJYYhoe9eyQJDZrkXoK6p_Ya_BY0,10106
68
70
  rbx/box/validators_test.py,sha256=hriR6rD32Ouu64eKYYTPLZVvqMxXj7Q2h1l_JAefL7U,344
69
71
  rbx/checker.py,sha256=pj1jO3my48ru-qugbER5onccANCjoR0-PaFe3H3VGEY,4118
70
72
  rbx/clone.py,sha256=wpHyED0_7ST7LD3vj7HjXhzqEzlwh6dRQvKQVDYhGeU,6744
71
- rbx/config.py,sha256=78xKH0zddEF32uIbIs10snqvACx20DmzjQTCex7w95Y,8136
73
+ rbx/config.py,sha256=0Mzlh5Ud4Ju7o7uyyRYhQpg8sMP7psUns_xlou6Bopk,8187
72
74
  rbx/conftest.py,sha256=ouilbOIpvX8jTEdCAiWT85CbdBQKUUf41BjmDI82u-Y,967
73
75
  rbx/console.py,sha256=X8EJy68OROgh6ao3ZcUjZm5Y56VFMzen58ywAuQ7pAU,990
74
76
  rbx/create.py,sha256=ezUq9KiSA-88ASd8CtjWXw8UB4LCaQ3Gib3OgvsLK-Q,986
@@ -82,7 +84,7 @@ rbx/grading/judge/digester.py,sha256=m6o-kjwyFOXKdImUXtVbdMHhwrgrXk8FDnJFVefnTIw
82
84
  rbx/grading/judge/sandbox.py,sha256=0h3YCmGabf9OfORJgx6v2Bed4kE-i8FyuZkPux-sDVk,23569
83
85
  rbx/grading/judge/sandboxes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
86
  rbx/grading/judge/sandboxes/isolate.py,sha256=9xgBuNfAvGtO2zME1FXRah2rcPvzDShsPG0TTuX_UDU,25649
85
- rbx/grading/judge/sandboxes/stupid_sandbox.py,sha256=NKSJWw_1HALjwGVIYQr_R1-s1tb6I25lzDLnPPsYANg,10154
87
+ rbx/grading/judge/sandboxes/stupid_sandbox.py,sha256=NBhBO4YnU5xmfRltv1OtdnEuZT0zn32Sdtpzz40UxvE,10137
86
88
  rbx/grading/judge/sandboxes/timeit.py,sha256=xScfasI2lsSQGZVpIZ7qBZfi0IaKC-1k8wO5qFp7UoM,6634
87
89
  rbx/grading/judge/storage.py,sha256=FirqjwDqb0m0h2OTFyWrZL7CQ4XjZNxhqB4JpnDIhZY,9485
88
90
  rbx/grading/judge/test.py,sha256=ll0Iw7zyOpGdKPD_PGH7dvUkb4stQLu-ikbQnqJvuAc,944
@@ -166,10 +168,10 @@ rbx/testdata/box1/validator.cpp,sha256=EWiKEWB6Nvke3SjBWHnkhkKJjwOqY_WX5kuXLxibA
166
168
  rbx/testdata/box1/wa.sol.cpp,sha256=qsHmvtLJOFI_sdvUT6ITqk7FJYqhrRTCmEIRdy4gSGE,407
167
169
  rbx/testdata/caching/executable.py,sha256=WKRHNf_fprFJd1Fq1ubmQtR3mZzTYVNwKPLWuZ4HrWg,10
168
170
  rbx/testdata/compatible,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
169
- rbx/testing_utils.py,sha256=ZZLKMUHlZ4HwsuNY50jqSBJ9HhpnFdba7opjDsvXE1U,2084
170
- rbx/utils.py,sha256=AITbkWpWtSp-x3Xept_aObfj_jPL7XL0JJoz5-F9Fp8,4671
171
- rbx_cp-0.5.37.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
172
- rbx_cp-0.5.37.dist-info/METADATA,sha256=-52cZu24PhrGmSfudYYYgw2R-Pfxlmk5YAa1BB96Vw0,3263
173
- rbx_cp-0.5.37.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
174
- rbx_cp-0.5.37.dist-info/entry_points.txt,sha256=qBTLBOeifT1F00LWaEewRRE_jQPgvH7BUdJfZ-dYsFU,57
175
- rbx_cp-0.5.37.dist-info/RECORD,,
171
+ rbx/testing_utils.py,sha256=ZXMysGXpTtvS1lfLL38FuD5iSIyxi3ARjQePDrUmEtc,2067
172
+ rbx/utils.py,sha256=6e1eXRzNE-52D0UVtqclePxqR4Haiqt8qWCrSVjnGuE,4585
173
+ rbx_cp-0.5.39.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
174
+ rbx_cp-0.5.39.dist-info/METADATA,sha256=Rwolc3QtBp6a9xSnOTeCjDO_yLy4JTB9CG5IAL2GTFE,3263
175
+ rbx_cp-0.5.39.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
176
+ rbx_cp-0.5.39.dist-info/entry_points.txt,sha256=qBTLBOeifT1F00LWaEewRRE_jQPgvH7BUdJfZ-dYsFU,57
177
+ rbx_cp-0.5.39.dist-info/RECORD,,