rbx.cp 0.13.4__py3-none-any.whl → 0.13.6__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 (42) hide show
  1. rbx/box/checkers.py +2 -9
  2. rbx/box/cli.py +0 -1
  3. rbx/box/code.py +27 -80
  4. rbx/box/environment.py +16 -6
  5. rbx/box/generators.py +26 -3
  6. rbx/box/global_package.py +1 -1
  7. rbx/box/header.py +26 -8
  8. rbx/box/package.py +0 -14
  9. rbx/box/setter_config.py +11 -0
  10. rbx/box/solutions.py +12 -4
  11. rbx/box/tasks.py +9 -4
  12. rbx/box/testing/testing_package.py +69 -2
  13. rbx/box/ui/screens/run_explorer.py +0 -8
  14. rbx/box/ui/utils/run_ui.py +7 -3
  15. rbx/box/ui/widgets/test_output_box.py +1 -1
  16. rbx/box/unit.py +4 -4
  17. rbx/box/validators.py +3 -1
  18. rbx/grading/caching.py +65 -15
  19. rbx/grading/judge/cacher.py +5 -3
  20. rbx/grading/judge/program.py +300 -0
  21. rbx/grading/judge/sandbox.py +30 -200
  22. rbx/grading/judge/sandboxes/stupid_sandbox.py +234 -240
  23. rbx/grading/judge/sandboxes/tee.py +31 -0
  24. rbx/grading/judge/storage.py +7 -1
  25. rbx/grading/steps.py +89 -201
  26. rbx/grading/steps_with_caching.py +15 -6
  27. rbx/resources/presets/default/problem/problem.rbx.yml +0 -2
  28. rbx/resources/templates/rbx.h +43 -2
  29. rbx/testing_utils.py +7 -0
  30. rbx/utils.py +104 -6
  31. {rbx_cp-0.13.4.dist-info → rbx_cp-0.13.6.dist-info}/METADATA +1 -1
  32. {rbx_cp-0.13.4.dist-info → rbx_cp-0.13.6.dist-info}/RECORD +35 -40
  33. rbx/grading/judge/sandboxes/isolate.py +0 -695
  34. rbx/grading/judge/sandboxes/timeit.py +0 -358
  35. rbx/grading/judge/test.py +0 -38
  36. rbx/grading/judge/testiso.py +0 -54
  37. rbx/grading/processing_context.py +0 -71
  38. rbx/resources/envs/isolate.rbx.yml +0 -36
  39. rbx/resources/presets/default/problem/sols/slow.cpp +0 -15
  40. {rbx_cp-0.13.4.dist-info → rbx_cp-0.13.6.dist-info}/LICENSE +0 -0
  41. {rbx_cp-0.13.4.dist-info → rbx_cp-0.13.6.dist-info}/WHEEL +0 -0
  42. {rbx_cp-0.13.4.dist-info → rbx_cp-0.13.6.dist-info}/entry_points.txt +0 -0
rbx/grading/steps.py CHANGED
@@ -1,15 +1,12 @@
1
1
  import asyncio
2
- import contextlib
3
2
  import dataclasses
4
3
  import functools
5
- import os
6
4
  import pathlib
7
5
  import re
8
6
  import shlex
9
7
  import shutil
10
8
  import subprocess
11
9
  import sys
12
- import tempfile
13
10
  from enum import Enum
14
11
  from typing import IO, Any, Dict, Iterable, List, Optional, Tuple, Union
15
12
 
@@ -20,9 +17,9 @@ from rich.text import Text
20
17
  from rbx import utils
21
18
  from rbx.config import get_bits_stdcpp, get_jngen, get_testlib
22
19
  from rbx.console import console
23
- from rbx.grading import grading_context, processing_context
20
+ from rbx.grading import grading_context
24
21
  from rbx.grading.judge.cacher import FileCacher
25
- from rbx.grading.judge.sandbox import SandboxBase, SandboxParams
22
+ from rbx.grading.judge.sandbox import SandboxBase, SandboxLog, SandboxParams
26
23
  from rbx.grading.judge.storage import copyfileobj
27
24
  from rbx.grading.limits import Limits
28
25
 
@@ -81,6 +78,7 @@ class DigestHolder(BaseModel):
81
78
 
82
79
  class GradingLogsHolder(BaseModel):
83
80
  run: Optional['RunLog'] = None
81
+ interactor_run: Optional['RunLog'] = None
84
82
  preprocess: Optional[List['PreprocessLog']] = None
85
83
  cached: bool = False
86
84
 
@@ -238,6 +236,7 @@ class RunLog(BaseModel):
238
236
  sandbox: str = ''
239
237
  warnings: bool = False
240
238
  metadata: Optional[RunLogMetadata] = None
239
+ exitindex: int = 0
241
240
 
242
241
  def get_run_language(self) -> Optional[str]:
243
242
  if self.metadata is None:
@@ -394,16 +393,18 @@ def _expand_part(part: str, sandbox: SandboxBase) -> List[str]:
394
393
  return [part]
395
394
 
396
395
 
397
- def _get_java_memory_limits(sandbox: SandboxBase) -> Tuple[int, int]:
398
- max_memory = sandbox.params.address_space
396
+ def _get_java_memory_limits(params: SandboxParams) -> Tuple[int, int]:
397
+ max_memory = params.address_space
399
398
  if max_memory is None:
400
399
  max_memory = 2048
401
400
  return max_memory, min(512, int(max_memory * 0.9))
402
401
 
403
402
 
404
- def _split_and_expand(command: str, sandbox: SandboxBase) -> List[str]:
403
+ def _split_and_expand(
404
+ command: str, sandbox: SandboxBase, params: SandboxParams
405
+ ) -> List[str]:
405
406
  res = []
406
- max_mem, init_mem = _get_java_memory_limits(sandbox)
407
+ max_mem, init_mem = _get_java_memory_limits(params)
407
408
  parts = shlex.split(command.format(memory=max_mem, initialMemory=init_mem))
408
409
  for part in parts:
409
410
  res.extend(_expand_part(part, sandbox))
@@ -594,7 +595,7 @@ def _maybe_complain_about_sanitization(command: str) -> None:
594
595
  raise typer.Exit(1)
595
596
 
596
597
 
597
- def _check_for_sanitizer_warnings_in_line(line: str) -> bool:
598
+ def check_for_sanitizer_warnings_in_line(line: str) -> bool:
598
599
  line = line.lower()
599
600
  return 'runtime error:' in line or '==error' in line
600
601
 
@@ -607,7 +608,7 @@ def _check_for_sanitizer_warnings(
607
608
  if not sandbox.file_exists(stderr_file):
608
609
  return False
609
610
  with sandbox.get_file(stderr_file) as f:
610
- return any(_check_for_sanitizer_warnings_in_line(line.decode()) for line in f)
611
+ return any(check_for_sanitizer_warnings_in_line(line.decode()) for line in f)
611
612
 
612
613
 
613
614
  _WARNING_RE = re.compile(r'([^:]+):\d+:\d+:[ ]+warning:.*')
@@ -640,6 +641,36 @@ def _check_for_compilation_warnings(
640
641
  )
641
642
 
642
643
 
644
+ def _build_run_log(
645
+ sandbox_log: SandboxLog,
646
+ sandbox: SandboxBase,
647
+ params: SandboxParams,
648
+ metadata: Optional[RunLogMetadata] = None,
649
+ ) -> RunLog:
650
+ execution_time = sandbox_log.execution_time
651
+ if execution_time is not None and (
652
+ sandbox_log.exitstatus == SandboxBase.EXIT_TIMEOUT
653
+ or sandbox_log.exitstatus == SandboxBase.EXIT_TIMEOUT_WALL
654
+ ):
655
+ execution_time = max(execution_time, (params.timeout or 0.0) / 1000)
656
+
657
+ run_log = RunLog(
658
+ exitcode=sandbox_log.exitcode,
659
+ exitstatus=sandbox_log.exitstatus,
660
+ time=execution_time,
661
+ memory=sandbox_log.memory_used,
662
+ metadata=metadata,
663
+ sandbox=sandbox_log.dump_other_logs(),
664
+ exitindex=sandbox_log.exit_index,
665
+ )
666
+ if metadata is not None and metadata.is_sanitized:
667
+ run_log.warnings = _check_for_sanitizer_warnings(
668
+ sandbox,
669
+ params.stderr_file,
670
+ )
671
+ return run_log
672
+
673
+
643
674
  def compile(
644
675
  commands: List[str],
645
676
  params: SandboxParams,
@@ -656,29 +687,20 @@ def compile(
656
687
  return True
657
688
 
658
689
  logs: List[PreprocessLog] = []
659
- sandbox.set_params(
660
- params.model_copy(deep=True)
661
- ) # Copy to allow further modification.
690
+ params = params.model_copy(deep=True) # Copy to allow further modification.
662
691
 
663
692
  for i, command in enumerate(commands):
664
693
  _maybe_complain_about_sanitization(command)
665
- cmd = _split_and_expand(command, sandbox)
694
+ cmd = _split_and_expand(command, sandbox, params)
666
695
  stdout_file = pathlib.PosixPath(f'compile-{i}.stdout')
667
696
  stderr_file = pathlib.PosixPath(f'compile-{i}.stderr')
668
- sandbox.params.set_stdall(stdout=stdout_file, stderr=stderr_file)
697
+ params.set_stdall(stdout=stdout_file, stderr=stderr_file)
669
698
 
670
699
  # Remove memory constraints for Java.
671
700
  if is_java_like_command(get_exe_from_command(command)):
672
- sandbox.params.address_space = None
701
+ params.address_space = None
673
702
 
674
- if not sandbox.execute_without_std(cmd):
675
- console.print(
676
- '[error]Sandbox crashed while processing command:[/error]',
677
- utils.highlight_json_obj(cmd),
678
- '[error]and logs[/error]',
679
- sandbox.debug_message(),
680
- )
681
- return False
703
+ sandbox_log = sandbox.run(cmd, params)
682
704
 
683
705
  std_outputs = [
684
706
  sandbox.get_file_to_string(stderr_file, maxlen=None)
@@ -691,13 +713,13 @@ def compile(
691
713
 
692
714
  log = PreprocessLog(
693
715
  cmd=cmd,
694
- exitcode=sandbox.get_exit_code(),
695
- exitstatus=sandbox.get_exit_status(),
696
- time=sandbox.get_execution_time(),
697
- memory=sandbox.get_memory_used(),
716
+ exitcode=sandbox_log.exitcode,
717
+ exitstatus=sandbox_log.exitstatus,
718
+ time=sandbox_log.execution_time,
719
+ memory=sandbox_log.memory_used,
698
720
  warnings=_check_for_compilation_warnings(sandbox, stderr_file),
699
721
  log='\n'.join(std_outputs),
700
- sandbox=sandbox.get_detailed_logs(),
722
+ sandbox=sandbox_log.dump_other_logs(),
701
723
  )
702
724
  logs.append(log)
703
725
 
@@ -730,48 +752,19 @@ async def run(
730
752
 
731
753
  _process_input_artifacts(artifacts, sandbox)
732
754
  _process_fifos(artifacts, sandbox)
733
- cmd = _split_and_expand(command, sandbox)
734
- sandbox.set_params(
735
- params.model_copy(deep=True)
736
- ) # Copy to allow further modification.
755
+ cmd = _split_and_expand(command, sandbox, params)
756
+ params = params.model_copy(deep=True) # Copy to allow further modification.
737
757
 
738
758
  # Remove memory constraints for Java.
739
759
  if is_java_like_command(get_exe_from_command(command)):
740
- sandbox.params.address_space = None
760
+ params.address_space = None
741
761
 
742
- sandbox.pid_event.set_loop(asyncio.get_event_loop())
743
- if not await asyncio.to_thread(sandbox.execute_without_std, cmd):
744
- console.print(
745
- '[error]Sandbox crashed while processing command:[/error]',
746
- utils.highlight_json_obj(cmd),
747
- '[error]and logs[/error]',
748
- sandbox.debug_message(),
749
- )
750
- return None
762
+ sandbox_log = await asyncio.to_thread(sandbox.run, cmd, params)
751
763
 
752
764
  if not _process_output_artifacts(artifacts, sandbox):
753
765
  return None
754
766
 
755
- execution_time = sandbox.get_execution_time()
756
- if execution_time is not None and (
757
- sandbox.get_exit_status() == SandboxBase.EXIT_TIMEOUT
758
- or sandbox.get_exit_status() == SandboxBase.EXIT_TIMEOUT_WALL
759
- ):
760
- execution_time = max(execution_time, (params.timeout or 0.0) / 1000)
761
-
762
- run_log = RunLog(
763
- exitcode=sandbox.get_exit_code(),
764
- exitstatus=sandbox.get_exit_status(),
765
- time=sandbox.get_execution_time(),
766
- memory=sandbox.get_memory_used(),
767
- metadata=metadata,
768
- sandbox=sandbox.get_detailed_logs(),
769
- )
770
- if metadata is not None and metadata.is_sanitized:
771
- run_log.warnings = _check_for_sanitizer_warnings(
772
- sandbox,
773
- params.stderr_file,
774
- )
767
+ run_log = _build_run_log(sandbox_log, sandbox, params, metadata)
775
768
  if artifacts.logs is not None:
776
769
  artifacts.logs.run = run_log.model_copy()
777
770
  return run_log
@@ -781,45 +774,53 @@ async def run(
781
774
  class CoordinatedRunParams:
782
775
  command: str
783
776
  params: SandboxParams
784
- sandbox: SandboxBase
785
- artifacts: GradingArtifacts
786
777
  metadata: Optional[RunLogMetadata] = None
787
778
 
788
779
 
789
780
  async def run_coordinated(
790
781
  interactor: CoordinatedRunParams,
791
782
  solution: CoordinatedRunParams,
783
+ artifacts: GradingArtifacts,
784
+ sandbox: SandboxBase,
785
+ merged_capture: Optional[pathlib.Path] = None,
792
786
  ) -> Tuple[Optional[RunLog], Optional[RunLog]]:
793
- def run_one(params: CoordinatedRunParams) -> asyncio.Task[Optional[RunLog]]:
794
- return asyncio.create_task(
795
- run(
796
- params.command,
797
- params.params,
798
- params.sandbox,
799
- params.artifacts,
800
- params.metadata,
801
- )
802
- )
787
+ sandbox.reset()
803
788
 
804
- # Use interactor PID as the process group id.
805
- interactor_task = run_one(interactor)
806
- solution.sandbox.params.pgid = await interactor.sandbox.get_pid()
807
- solution_task = run_one(solution)
789
+ _process_input_artifacts(artifacts, sandbox)
790
+ _process_fifos(artifacts, sandbox)
808
791
 
809
- await processing_context.wait_all([interactor.sandbox, solution.sandbox])
792
+ interactor_cmd = _split_and_expand(interactor.command, sandbox, interactor.params)
793
+ solution_cmd = _split_and_expand(solution.command, sandbox, solution.params)
810
794
 
811
- return await asyncio.gather(interactor_task, solution_task)
795
+ interactor_params = interactor.params.model_copy(deep=True)
796
+ solution_params = solution.params.model_copy(deep=True)
812
797
 
798
+ if is_java_like_command(get_exe_from_command(solution.command)):
799
+ solution_params.address_space = None
800
+
801
+ solution_sandbox_log, interactor_sandbox_log = sandbox.run_communication(
802
+ solution_cmd,
803
+ solution_params,
804
+ interactor_cmd,
805
+ interactor_params,
806
+ merged_capture,
807
+ )
813
808
 
814
- def _normalize_checked_words(s: str) -> Tuple[str, ...]:
815
- return tuple(s.split())
809
+ if not _process_output_artifacts(artifacts, sandbox):
810
+ return None, None
816
811
 
812
+ solution_log = _build_run_log(
813
+ solution_sandbox_log, sandbox, solution.params, solution.metadata
814
+ )
815
+ interactor_log = _build_run_log(
816
+ interactor_sandbox_log, sandbox, interactor.params, interactor.metadata
817
+ )
817
818
 
818
- def _wcmp_check(expected: str, output: str) -> Outcome:
819
- if _normalize_checked_words(expected) == _normalize_checked_words(output):
820
- return Outcome.ACCEPTED
819
+ if artifacts.logs is not None:
820
+ artifacts.logs.run = solution_log
821
+ artifacts.logs.interactor_run = interactor_log
821
822
 
822
- return Outcome.WRONG_ANSWER
823
+ return solution_log, interactor_log
823
824
 
824
825
 
825
826
  def get_checker_sandbox_params() -> SandboxParams:
@@ -830,116 +831,3 @@ def get_checker_sandbox_params() -> SandboxParams:
830
831
  params.add_mapped_directory(pathlib.Path('/usr'))
831
832
  params.add_mapped_directory(pathlib.Path('/etc'))
832
833
  return params
833
-
834
-
835
- def _check(
836
- sandbox: SandboxBase,
837
- testcase: TestcaseIO,
838
- output_path: pathlib.Path,
839
- should_use_python_checker: bool = False,
840
- ) -> CheckerResult:
841
- if testcase.output is None:
842
- # No output to compare.
843
- return CheckerResult(outcome=Outcome.ACCEPTED)
844
-
845
- if should_use_python_checker:
846
- # Use default wcmp checker.
847
- expected = testcase.output.read_text()
848
- output = output_path.read_text()
849
-
850
- return CheckerResult(outcome=_wcmp_check(expected, output))
851
-
852
- sandbox.params.set_stdall(
853
- stdin=None,
854
- stdout=pathlib.PosixPath('stdout.txt'),
855
- stderr=pathlib.PosixPath('stderr.txt'),
856
- )
857
-
858
- sandbox.create_file_from_string(
859
- pathlib.PosixPath('expected.txt'), testcase.output.read_text(), override=True
860
- )
861
- sandbox.create_file_from_string(
862
- pathlib.PosixPath('output.txt'), output_path.read_text(), override=True
863
- )
864
- sandbox.create_file_from_string(
865
- pathlib.PosixPath('input.txt'),
866
- testcase.input.read_text() if testcase.input is not None else '',
867
- override=True,
868
- )
869
-
870
- if not sandbox.execute_without_std(
871
- ['./checker', 'input.txt', 'output.txt', 'expected.txt'],
872
- ):
873
- console.print(
874
- '[error]Sandbox crashed while running checker.[/error]',
875
- '[error]and logs[/error]',
876
- sandbox.debug_message(),
877
- )
878
- return CheckerResult(outcome=Outcome.INTERNAL_ERROR)
879
-
880
- checker_stderr = sandbox.get_file_to_string(
881
- pathlib.PosixPath('stderr.txt'), maxlen=None
882
- )
883
- if sandbox.get_exit_code() in [1, 2]:
884
- return CheckerResult(outcome=Outcome.WRONG_ANSWER, message=checker_stderr)
885
- if sandbox.get_exit_code() == 3:
886
- return CheckerResult(outcome=Outcome.JUDGE_FAILED, message=checker_stderr)
887
- return CheckerResult(outcome=Outcome.ACCEPTED, message=checker_stderr)
888
-
889
-
890
- # Always assume a `checker` executable in the sandbox if should use checker.
891
- def evaluate(
892
- sandbox: SandboxBase,
893
- testcase: TestcaseIO,
894
- log: Optional[TestcaseLog],
895
- artifacts: GradingArtifacts,
896
- should_use_python_checker: bool = False,
897
- ) -> Evaluation:
898
- if log is None:
899
- return Evaluation(
900
- testcase=testcase,
901
- log=TestcaseLog(),
902
- result=CheckerResult(outcome=Outcome.INTERNAL_ERROR),
903
- )
904
- if log.exitstatus != SandboxBase.EXIT_OK:
905
- return Evaluation(
906
- testcase=testcase,
907
- log=log,
908
- result=CheckerResult(outcome=Outcome.RUNTIME_ERROR),
909
- )
910
-
911
- if not testcase.output:
912
- # No output to compare.
913
- return Evaluation(
914
- testcase=testcase, log=log, result=CheckerResult(outcome=Outcome.ACCEPTED)
915
- )
916
-
917
- _process_input_artifacts(artifacts, sandbox)
918
- if log.stdout_absolute_path is None:
919
- return Evaluation(
920
- testcase=testcase,
921
- log=log,
922
- result=CheckerResult(outcome=Outcome.INTERNAL_ERROR, message='No output'),
923
- )
924
-
925
- checker_result = _check(
926
- sandbox,
927
- testcase,
928
- log.stdout_absolute_path,
929
- should_use_python_checker=should_use_python_checker,
930
- )
931
- return Evaluation(
932
- testcase=testcase,
933
- log=log,
934
- result=checker_result,
935
- )
936
-
937
-
938
- @contextlib.contextmanager
939
- def make_fifos():
940
- with tempfile.TemporaryDirectory() as temp_dir:
941
- fifo_in = pathlib.PosixPath(temp_dir) / 'fifo.in'
942
- fifo_out = pathlib.PosixPath(temp_dir) / 'fifo.out'
943
- os.mkfifo(fifo_in)
944
- os.mkfifo(fifo_out)
945
- yield fifo_in, fifo_out
@@ -1,3 +1,4 @@
1
+ import pathlib
1
2
  from typing import Any, Dict, List, Optional, Tuple
2
3
 
3
4
  from rbx.grading import grading_context, profiling, steps
@@ -88,10 +89,12 @@ async def run(
88
89
  async def run_coordinated(
89
90
  interactor: steps.CoordinatedRunParams,
90
91
  solution: steps.CoordinatedRunParams,
92
+ artifacts: GradingArtifacts,
93
+ sandbox: SandboxBase,
91
94
  dependency_cache: DependencyCache,
95
+ merged_capture: Optional[pathlib.Path] = None,
92
96
  ) -> Tuple[Optional[RunLog], Optional[RunLog]]:
93
- interactor.artifacts.logs = GradingLogsHolder()
94
- solution.artifacts.logs = GradingLogsHolder()
97
+ artifacts.logs = GradingLogsHolder()
95
98
 
96
99
  cacheable_params = {
97
100
  **_get_prefixed_cacheable_params(
@@ -114,18 +117,24 @@ async def run_coordinated(
114
117
  cached_profile = profiling.Profiler('steps.run_coordinated[cached]', start=True)
115
118
  with dependency_cache(
116
119
  [interactor.command, solution.command],
117
- [interactor.artifacts, solution.artifacts],
120
+ [artifacts],
118
121
  cacheable_params,
119
122
  ) as is_cached:
120
123
  if not is_cached:
121
124
  with profiling.Profiler('steps.run_coordinated'):
122
125
  profiling.add_to_counter('steps.run_coordinated')
123
- await steps.run_coordinated(interactor, solution)
126
+ await steps.run_coordinated(
127
+ interactor,
128
+ solution,
129
+ artifacts,
130
+ sandbox,
131
+ merged_capture=merged_capture,
132
+ )
124
133
  else:
125
134
  cached_profile.stop()
126
135
  profiling.add_to_counter('steps.run_coordinated[cached]')
127
136
 
128
137
  return (
129
- interactor.artifacts.logs.run,
130
- solution.artifacts.logs.run,
138
+ artifacts.logs.interactor_run,
139
+ artifacts.logs.run,
131
140
  )
@@ -19,8 +19,6 @@ solutions:
19
19
  outcome: "ACCEPTED"
20
20
  - path: "sols/wa.cpp"
21
21
  outcome: "WRONG_ANSWER"
22
- - path: "sols/slow.cpp"
23
- outcome: "TLE_OR_RTE" # Can be TLE too
24
22
  statements:
25
23
  - name: "statement-en"
26
24
  title: "New Problem"
@@ -1,5 +1,7 @@
1
1
  #ifndef _RBX_H
2
2
  #define _RBX_H
3
+ #include <cstdint>
4
+ #include <limits>
3
5
  #include <optional>
4
6
  #include <stdexcept>
5
7
  #include <string>
@@ -9,7 +11,7 @@ std::optional<std::string> getStringVar(std::string name) {
9
11
  return std::nullopt;
10
12
  }
11
13
 
12
- std::optional<int> getIntVar(std::string name) {
14
+ std::optional<int64_t> getIntVar(std::string name) {
13
15
  //<rbx::int_var>
14
16
  return std::nullopt;
15
17
  }
@@ -26,7 +28,46 @@ std::optional<bool> getBoolVar(std::string name) {
26
28
 
27
29
  template <typename T> T getVar(std::string name);
28
30
 
29
- template <> int getVar<int>(std::string name) {
31
+ template <> int32_t getVar<int32_t>(std::string name) {
32
+ auto opt = getIntVar(name);
33
+ if (!opt.has_value()) {
34
+ throw std::runtime_error("Variable " + name +
35
+ " is not an integer or could not be found");
36
+ }
37
+ if (opt.value() < std::numeric_limits<int32_t>::min() ||
38
+ opt.value() > std::numeric_limits<int32_t>::max()) {
39
+ throw std::runtime_error("Variable " + name + " of value " +
40
+ std::to_string(opt.value()) +
41
+ " does not fit in int32_t");
42
+ }
43
+ return opt.value();
44
+ }
45
+
46
+ template <> uint32_t getVar<uint32_t>(std::string name) {
47
+ auto opt = getIntVar(name);
48
+ if (!opt.has_value()) {
49
+ throw std::runtime_error("Variable " + name +
50
+ " is not an integer or could not be found");
51
+ }
52
+ if (opt.value() < std::numeric_limits<uint32_t>::min() ||
53
+ opt.value() > std::numeric_limits<uint32_t>::max()) {
54
+ throw std::runtime_error("Variable " + name + " of value " +
55
+ std::to_string(opt.value()) +
56
+ " does not fit in uint32_t");
57
+ }
58
+ return opt.value();
59
+ }
60
+
61
+ template <> int64_t getVar<int64_t>(std::string name) {
62
+ auto opt = getIntVar(name);
63
+ if (!opt.has_value()) {
64
+ throw std::runtime_error("Variable " + name +
65
+ " is not an integer or could not be found");
66
+ }
67
+ return opt.value();
68
+ }
69
+
70
+ template <> uint64_t getVar<uint64_t>(std::string name) {
30
71
  auto opt = getIntVar(name);
31
72
  if (!opt.has_value()) {
32
73
  throw std::runtime_error("Variable " + name +
rbx/testing_utils.py CHANGED
@@ -16,6 +16,13 @@ def get_testdata_path() -> pathlib.Path:
16
16
  return file.parent
17
17
 
18
18
 
19
+ def get_resources_path() -> pathlib.Path:
20
+ with importlib.resources.as_file(
21
+ importlib.resources.files('rbx') / 'resources' / 'default_setter_config.yml'
22
+ ) as file:
23
+ return file.parent
24
+
25
+
19
26
  def clear_all_functools_cache():
20
27
  from rbx.box import environment, header, package
21
28