rbx.cp 0.5.29__tar.gz → 0.5.31__tar.gz

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 (171) hide show
  1. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/PKG-INFO +1 -1
  2. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/pyproject.toml +1 -1
  3. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/code.py +58 -1
  4. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/contest/schema.py +5 -5
  5. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/creation.py +10 -0
  6. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/extensions.py +2 -2
  7. rbx_cp-0.5.31/rbx/box/formatting.py +10 -0
  8. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/generators.py +12 -10
  9. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/generators_test.py +1 -1
  10. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/main.py +14 -0
  11. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/schema.py +36 -28
  12. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/setter_config.py +7 -7
  13. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/solutions.py +34 -24
  14. rbx_cp-0.5.31/rbx/box/state.py +9 -0
  15. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/statements/schema.py +6 -4
  16. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/judge/sandboxes/stupid_sandbox.py +0 -1
  17. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/LICENSE +0 -0
  18. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/README.md +0 -0
  19. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/__init__.py +0 -0
  20. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/annotations.py +0 -0
  21. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/autoenum.py +0 -0
  22. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/__init__.py +0 -0
  23. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/builder.py +0 -0
  24. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/cd.py +0 -0
  25. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/checkers.py +0 -0
  26. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/compile.py +0 -0
  27. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/conftest.py +0 -0
  28. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/contest/__init__.py +0 -0
  29. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/contest/build_contest_statements.py +0 -0
  30. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/contest/contest_package.py +0 -0
  31. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/contest/contest_utils.py +0 -0
  32. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/contest/main.py +0 -0
  33. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/contest/statements.py +0 -0
  34. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/deferred.py +0 -0
  35. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/download.py +0 -0
  36. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/environment.py +0 -0
  37. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/package.py +0 -0
  38. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/packaging/boca/extension.py +0 -0
  39. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/packaging/boca/packager.py +0 -0
  40. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/packaging/contest_main.py +0 -0
  41. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/packaging/main.py +0 -0
  42. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/packaging/packager.py +0 -0
  43. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/packaging/polygon/packager.py +0 -0
  44. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/packaging/polygon/test.py +0 -0
  45. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/packaging/polygon/xml_schema.py +0 -0
  46. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/presets/__init__.py +0 -0
  47. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/presets/fetch.py +0 -0
  48. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/presets/lock_schema.py +0 -0
  49. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/presets/schema.py +0 -0
  50. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/retries.py +0 -0
  51. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/sanitizers/warning_stack.py +0 -0
  52. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/solutions_test.py +0 -0
  53. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/statements/__init__.py +0 -0
  54. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/statements/build_statements.py +0 -0
  55. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/statements/builders.py +0 -0
  56. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/statements/joiners.py +0 -0
  57. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/statements/latex.py +0 -0
  58. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/statements/latex_jinja.py +0 -0
  59. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/stresses.py +0 -0
  60. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/stressing/__init__.py +0 -0
  61. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/stressing/finder_parser.py +0 -0
  62. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/stressing/generator_parser.py +0 -0
  63. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/testcases.py +0 -0
  64. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/ui/__init__.py +0 -0
  65. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/ui/captured_log.py +0 -0
  66. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/ui/css/app.tcss +0 -0
  67. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/ui/main.py +0 -0
  68. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/ui/run.py +0 -0
  69. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/validators.py +0 -0
  70. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/box/validators_test.py +0 -0
  71. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/checker.py +0 -0
  72. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/clone.py +0 -0
  73. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/config.py +0 -0
  74. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/conftest.py +0 -0
  75. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/console.py +0 -0
  76. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/create.py +0 -0
  77. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/edit.py +0 -0
  78. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/__init__.py +0 -0
  79. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/caching.py +0 -0
  80. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/conftest.py +0 -0
  81. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/judge/__init__.py +0 -0
  82. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/judge/cacher.py +0 -0
  83. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/judge/digester.py +0 -0
  84. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/judge/sandbox.py +0 -0
  85. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/judge/sandboxes/__init__.py +0 -0
  86. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/judge/sandboxes/isolate.py +0 -0
  87. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/judge/sandboxes/timeit.py +0 -0
  88. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/judge/storage.py +0 -0
  89. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/judge/test.py +0 -0
  90. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/judge/testiso.py +0 -0
  91. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/steps.py +0 -0
  92. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/steps_with_caching.py +0 -0
  93. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading/steps_with_caching_run_test.py +0 -0
  94. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/grading_utils.py +0 -0
  95. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/hydration.py +0 -0
  96. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/main.py +0 -0
  97. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/metadata.py +0 -0
  98. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/providers/__init__.py +0 -0
  99. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/providers/codeforces.py +0 -0
  100. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/providers/provider.py +0 -0
  101. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/checkers/boilerplate.cpp +0 -0
  102. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/default_config.json +0 -0
  103. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/default_setter_config.mac.yml +0 -0
  104. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/default_setter_config.yml +0 -0
  105. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/envs/default.rbx.yml +0 -0
  106. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/envs/isolate.rbx.yml +0 -0
  107. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/checker.sh +0 -0
  108. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/compare +0 -0
  109. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/compile/c +0 -0
  110. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/compile/cc +0 -0
  111. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/compile/cpp +0 -0
  112. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/compile/java +0 -0
  113. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/compile/kt +0 -0
  114. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/compile/pas +0 -0
  115. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/compile/py2 +0 -0
  116. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/compile/py3 +0 -0
  117. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/run/c +0 -0
  118. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/run/cc +0 -0
  119. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/run/cpp +0 -0
  120. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/run/java +0 -0
  121. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/run/kt +0 -0
  122. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/run/py2 +0 -0
  123. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/packagers/boca/run/py3 +0 -0
  124. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/contest/contest.rbx.yml +0 -0
  125. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/contest/statement/contest.rbx.tex +0 -0
  126. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/contest/statement/olymp.sty +0 -0
  127. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/contest/statement/template.rbx.tex +0 -0
  128. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/preset.rbx.yml +0 -0
  129. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/.gitignore +0 -0
  130. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/gen.cpp +0 -0
  131. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/problem.rbx.yml +0 -0
  132. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/random.py +0 -0
  133. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/random.txt +0 -0
  134. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/sols/main.cpp +0 -0
  135. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/sols/slow.cpp +0 -0
  136. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/sols/wa.cpp +0 -0
  137. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/statement/olymp.sty +0 -0
  138. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/statement/projecao.png +0 -0
  139. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/statement/statement.rbx.tex +0 -0
  140. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/statement/template.rbx.tex +0 -0
  141. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/tests/samples/000.in +0 -0
  142. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/tests/samples/001.in +0 -0
  143. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/validator.cpp +0 -0
  144. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/presets/default/problem/wcmp.cpp +0 -0
  145. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/resources/templates/template.cpp +0 -0
  146. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/run.py +0 -0
  147. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/schema.py +0 -0
  148. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/submit.py +0 -0
  149. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/submitors/__init__.py +0 -0
  150. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/submitors/codeforces.py +0 -0
  151. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/submitors/submitor.py +0 -0
  152. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/test.py +0 -0
  153. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testcase.py +0 -0
  154. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testcase_rendering.py +0 -0
  155. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/box1/gen1.cpp +0 -0
  156. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/box1/gen2.cpp +0 -0
  157. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/box1/genScript.py +0 -0
  158. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/box1/hard-tle.sol.cpp +0 -0
  159. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/box1/ole.cpp +0 -0
  160. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/box1/problem.rbx.yml +0 -0
  161. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/box1/re.sol.cpp +0 -0
  162. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/box1/sol.cpp +0 -0
  163. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/box1/tests/1.in +0 -0
  164. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/box1/tle-and-incorrect.sol.cpp +0 -0
  165. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/box1/tle.sol.cpp +0 -0
  166. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/box1/validator.cpp +0 -0
  167. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/box1/wa.sol.cpp +0 -0
  168. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/caching/executable.py +0 -0
  169. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testdata/compatible +0 -0
  170. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/testing_utils.py +0 -0
  171. {rbx_cp-0.5.29 → rbx_cp-0.5.31}/rbx/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: rbx.cp
3
- Version: 0.5.29
3
+ Version: 0.5.31
4
4
  Summary:
5
5
  Author: Roberto Sales
6
6
  Requires-Python: >=3.9,<4.0
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "rbx.cp"
3
- version = "0.5.29"
3
+ version = "0.5.31"
4
4
  description = ""
5
5
  packages = [
6
6
  {include = "rbx"}
@@ -1,5 +1,6 @@
1
1
  import pathlib
2
2
  import re
3
+ import resource
3
4
  import shlex
4
5
  from enum import Enum
5
6
  from pathlib import PosixPath
@@ -10,7 +11,7 @@ import rich.text
10
11
  import typer
11
12
 
12
13
  from rbx import console
13
- from rbx.box import download, package, setter_config
14
+ from rbx.box import download, package, setter_config, state
14
15
  from rbx.box.environment import (
15
16
  ExecutionConfig,
16
17
  get_compilation_config,
@@ -22,6 +23,7 @@ from rbx.box.environment import (
22
23
  get_sandbox_params_from_config,
23
24
  merge_execution_configs,
24
25
  )
26
+ from rbx.box.formatting import get_formatted_memory
25
27
  from rbx.box.sanitizers import warning_stack
26
28
  from rbx.box.schema import CodeItem
27
29
  from rbx.grading import steps_with_caching
@@ -150,6 +152,57 @@ def _ignore_warning_in_cxx_input(input: GradingFileInput):
150
152
  input.src = preprocessed_path
151
153
 
152
154
 
155
+ def _format_stack_limit(limit: int) -> str:
156
+ if limit == resource.RLIM_INFINITY:
157
+ return 'unlimited'
158
+ return get_formatted_memory(limit)
159
+
160
+
161
+ def _check_stack_limit():
162
+ if not state.STATE.run_through_cli:
163
+ return
164
+ soft, hard = resource.RLIM_INFINITY, resource.RLIM_INFINITY
165
+
166
+ TARGET = 256 * 1024 * 1024 # 256 MiB
167
+ try:
168
+ soft, hard = resource.getrlimit(resource.RLIMIT_STACK)
169
+ except Exception:
170
+ pass
171
+
172
+ if soft != hard or (soft != resource.RLIM_INFINITY and soft < TARGET):
173
+ soft_fmt = _format_stack_limit(soft)
174
+ hard_fmt = _format_stack_limit(hard)
175
+ console.console.print(
176
+ f'[error]Stack limit is too low (limit is set as [item]{soft_fmt}[/item], but configured user capacity is [item]{hard_fmt}[/item]).[/error]'
177
+ )
178
+ console.console.print(
179
+ '[error]It is not safe to develop problems in [item]rbx[/item] with this configuration.[/error]'
180
+ )
181
+ console.console.print(
182
+ 'To solve this, add the following lines to the end of your [item]~/.bashrc[/item] or [item]~/.zshrc[/item] file (or equivalent shell configuration file):'
183
+ )
184
+
185
+ target_text = TARGET
186
+ if hard != resource.RLIM_INFINITY:
187
+ target_text = min(hard, TARGET)
188
+ console.console.print(
189
+ """
190
+ ```
191
+ export RBX_BIN_PATH=`which rbx`
192
+ function rbx() {
193
+ ulimit -s %s && $RBX_BIN_PATH $@
194
+ }
195
+ ```
196
+ """
197
+ % target_text
198
+ )
199
+ console.console.print()
200
+ console.console.print(
201
+ 'You can read more about this in [item]https://rsalesc.github.io/rbx/stack-limit/[/item].'
202
+ )
203
+ raise typer.Exit(1)
204
+
205
+
153
206
  # Compile code item and return its digest in the storage.
154
207
  def compile_item(
155
208
  code: CodeItem,
@@ -157,6 +210,8 @@ def compile_item(
157
210
  force_warnings: bool = False,
158
211
  verbose: bool = False,
159
212
  ) -> str:
213
+ _check_stack_limit()
214
+
160
215
  generator_path = PosixPath(code.path)
161
216
 
162
217
  if not generator_path.is_file():
@@ -268,6 +323,8 @@ def run_item(
268
323
  extra_config: Optional[ExecutionConfig] = None,
269
324
  retry_index: Optional[int] = None,
270
325
  ) -> Optional[RunLog]:
326
+ _check_stack_limit()
327
+
271
328
  language = find_language_name(code)
272
329
  execution_options = get_execution_config(language)
273
330
  if extra_config is not None:
@@ -19,7 +19,7 @@ class ProblemStatementOverride(BaseModel):
19
19
  model_config = ConfigDict(extra='forbid')
20
20
 
21
21
  configure: List[ConversionStep] = Field(
22
- [],
22
+ default=[],
23
23
  discriminator='type',
24
24
  description="""
25
25
  Configure how certain conversion steps should happen when applied to the statement file.
@@ -33,7 +33,7 @@ configure them in case they are applied.
33
33
  class ContestStatement(BaseModel):
34
34
  model_config = ConfigDict(extra='forbid')
35
35
 
36
- language: str = Field('en', description='Language code for this statement.')
36
+ language: str = Field(default='en', description='Language code for this statement.')
37
37
 
38
38
  title: str = Field(description='Title of the contest in this language.')
39
39
 
@@ -50,7 +50,7 @@ class ContestStatement(BaseModel):
50
50
  type: StatementType = Field(description='Type of the input statement file.')
51
51
 
52
52
  joiner: Optional[Joiner] = Field(
53
- None,
53
+ default=None,
54
54
  description="""
55
55
  Joiner to be used to build the statement.
56
56
 
@@ -98,7 +98,7 @@ Can be glob pattern as well, such as `imgs/*.png`.
98
98
  # Vars to be re-used in the statement.
99
99
  # - It will be available as \VAR{vars} variable in the contest-level box statement.
100
100
  vars: Dict[str, Primitive] = Field(
101
- {}, description='Variables to be re-used across the package.'
101
+ default={}, description='Variables to be re-used across the package.'
102
102
  )
103
103
 
104
104
  @property
@@ -147,7 +147,7 @@ class Contest(BaseModel):
147
147
  # Vars to be re-used in the statements.
148
148
  # - It will be available as \VAR{vars} variable in the contest-level box statement.
149
149
  vars: Dict[str, Primitive] = Field(
150
- {}, description='Variables to be re-used across the package.'
150
+ default={}, description='Variables to be re-used across the package.'
151
151
  )
152
152
 
153
153
  @property
@@ -6,6 +6,7 @@ import typer
6
6
 
7
7
  from rbx import console
8
8
  from rbx.box import presets
9
+ from rbx.box.contest.contest_package import find_contest_yaml
9
10
  from rbx.box.presets.fetch import get_preset_fetch_info
10
11
 
11
12
 
@@ -26,6 +27,15 @@ def create(
26
27
  ] = None,
27
28
  path: Optional[pathlib.Path] = None,
28
29
  ):
30
+ if find_contest_yaml() is not None:
31
+ console.console.print(
32
+ '[error]Cannot [item]rbx create[/item] a problem inside a contest.[/error]'
33
+ )
34
+ console.console.print(
35
+ '[error]Instead, use [item]rbx contest add[/item] to add a problem to a contest.[/error]'
36
+ )
37
+ raise typer.Exit(1)
38
+
29
39
  preset = preset or 'default'
30
40
  console.console.print(f'Creating new problem [item]{name}[/item]...')
31
41
 
@@ -8,11 +8,11 @@ from rbx.box.packaging.boca.extension import BocaExtension, BocaLanguageExtensio
8
8
  # Extension abstractions.
9
9
  class Extensions(BaseModel):
10
10
  boca: Optional[BocaExtension] = Field(
11
- None, description='Environment-level extensions for BOCA packaging.'
11
+ default=None, description='Environment-level extensions for BOCA packaging.'
12
12
  )
13
13
 
14
14
 
15
15
  class LanguageExtensions(BaseModel):
16
16
  boca: Optional[BocaLanguageExtension] = Field(
17
- None, description='Language-level extensions for BOCA packaging.'
17
+ default=None, description='Language-level extensions for BOCA packaging.'
18
18
  )
@@ -0,0 +1,10 @@
1
+ def get_formatted_memory(memory_in_bytes: int, mib_decimal_places: int = 0) -> str:
2
+ if memory_in_bytes < 1024 * 1024:
3
+ if memory_in_bytes < 1024:
4
+ return f'{memory_in_bytes} B'
5
+ return f'{memory_in_bytes / 1024:.0f} KiB'
6
+ return f'{memory_in_bytes / (1024 * 1024):.{mib_decimal_places}f} MiB'
7
+
8
+
9
+ def get_formatted_time(time_in_ms: int) -> str:
10
+ return f'{time_in_ms} ms'
@@ -47,11 +47,11 @@ def _get_group_output(
47
47
  return group_path / f'{subgroup_prefix}{i:03d}.out'
48
48
 
49
49
 
50
- def _fill_output_for_testcase(testcase: Testcase) -> Testcase:
50
+ def _fill_output_for_defined_testcase(testcase: Testcase) -> Testcase:
51
51
  res = testcase.model_copy()
52
52
  if res.outputPath is not None:
53
53
  return res
54
- output_path = res.inputPath.with_suffix('.out')
54
+ output_path = res.inputPath.with_suffix('.ans')
55
55
  if output_path.is_file():
56
56
  res.outputPath = output_path
57
57
  return res
@@ -61,7 +61,7 @@ def _copy_testcase_over(
61
61
  testcase: Testcase,
62
62
  dest: Testcase,
63
63
  ):
64
- testcase = _fill_output_for_testcase(testcase)
64
+ testcase = _fill_output_for_defined_testcase(testcase)
65
65
  dest.inputPath.parent.mkdir(parents=True, exist_ok=True)
66
66
  shutil.copy(
67
67
  str(testcase.inputPath),
@@ -195,7 +195,7 @@ def run_testcase_visitor(visitor: TestcaseVisitor):
195
195
  pkg = package.find_problem_package_or_die()
196
196
 
197
197
  def _explore_subgroup(
198
- subgroup: TestcaseSubgroup, subgroup_index: int, prefix: List[str]
198
+ subgroup: TestcaseSubgroup, subgroup_index: Optional[int], prefix: List[str]
199
199
  ):
200
200
  assert prefix and len(prefix) >= 1 and len(prefix) <= 2
201
201
  group_path = prefix[0]
@@ -212,8 +212,10 @@ def run_testcase_visitor(visitor: TestcaseVisitor):
212
212
  def _copied_to(i: int) -> Testcase:
213
213
  group_fs_path = package.get_build_testgroup_path(group_path)
214
214
  group_prefix = ''
215
+ if subgroup_index is not None:
216
+ group_prefix = f'{subgroup_index}-'
215
217
  if len(prefix) == 2:
216
- group_prefix = f'{subgroup_index}-{prefix[1]}-'
218
+ group_prefix += f'{prefix[1]}-'
217
219
  return Testcase(
218
220
  inputPath=_get_group_input(group_fs_path, group_prefix, i),
219
221
  outputPath=_get_group_output(group_fs_path, group_prefix, i),
@@ -228,7 +230,7 @@ def run_testcase_visitor(visitor: TestcaseVisitor):
228
230
  group_entry=_entry(i),
229
231
  subgroup_entry=_sub_entry(i),
230
232
  metadata=GenerationMetadata(
231
- copied_from=_fill_output_for_testcase(tc),
233
+ copied_from=_fill_output_for_defined_testcase(tc),
232
234
  copied_to=_copied_to(i),
233
235
  ),
234
236
  )
@@ -249,7 +251,7 @@ def run_testcase_visitor(visitor: TestcaseVisitor):
249
251
  group_entry=_entry(i),
250
252
  subgroup_entry=_sub_entry(i),
251
253
  metadata=GenerationMetadata(
252
- copied_from=_fill_output_for_testcase(tc),
254
+ copied_from=_fill_output_for_defined_testcase(tc),
253
255
  copied_to=_copied_to(i),
254
256
  ),
255
257
  )
@@ -296,10 +298,10 @@ def run_testcase_visitor(visitor: TestcaseVisitor):
296
298
  if not visitor.should_visit_group(group.name):
297
299
  continue
298
300
 
299
- _explore_subgroup(group, 0, [group.name])
301
+ _explore_subgroup(group, 0 if group.subgroups else None, [group.name])
300
302
 
301
303
  for i, subgroup in enumerate(group.subgroups):
302
- _explore_subgroup(subgroup, i, [group.name, subgroup.name])
304
+ _explore_subgroup(subgroup, i + 1, [group.name, subgroup.name])
303
305
 
304
306
 
305
307
  def _get_necessary_generators_for_groups(
@@ -433,7 +435,7 @@ def generate_standalone(
433
435
  validator_digest,
434
436
  )
435
437
  if not ok:
436
- _print_error_header('Failed validating testcase.')
438
+ _print_error_header('failed validating testcase.')
437
439
  console.console.print(f'[error]Message:[/error] {message}')
438
440
  console.console.print(
439
441
  f'Testcase written at [item]{spec.copied_to.inputPath}[/item]'
@@ -19,7 +19,7 @@ def test_generator_works(pkg_from_testdata: pathlib.Path):
19
19
  print_directory_tree(pkg_from_testdata)
20
20
 
21
21
  assert (
22
- package.get_build_testgroup_path('gen1') / '0-main-000.in'
22
+ package.get_build_testgroup_path('gen1') / '0-000.in'
23
23
  ).read_text() == '777\n'
24
24
  assert (
25
25
  package.get_build_testgroup_path('gen1') / '1-gen-000.in'
@@ -25,6 +25,7 @@ from rbx.box import (
25
25
  builder,
26
26
  cd,
27
27
  setter_config,
28
+ state,
28
29
  creation,
29
30
  download,
30
31
  environment,
@@ -83,6 +84,11 @@ app.add_typer(
83
84
  )
84
85
 
85
86
 
87
+ @app.callback()
88
+ def main():
89
+ state.STATE.run_through_cli = True
90
+
91
+
86
92
  # @app.command('ui', hidden=True)
87
93
  # @package.within_problem
88
94
  # def ui():
@@ -255,6 +261,7 @@ def _time_impl(check: bool, detailed: bool) -> Optional[int]:
255
261
  tracked_solutions=tracked_solutions,
256
262
  check=check,
257
263
  verification=VerificationLevel(verification),
264
+ timelimit_override=600, # 10 minute time limit for estimation
258
265
  )
259
266
 
260
267
  console.console.print()
@@ -352,6 +359,12 @@ def irun(
352
359
  '-t',
353
360
  help='Testcase to run, in the format "[group]/[index]". If not specified, will run interactively.',
354
361
  ),
362
+ output: bool = typer.Option(
363
+ False,
364
+ '--output',
365
+ '-o',
366
+ help='Whether to ask user for custom output.',
367
+ ),
355
368
  print: bool = typer.Option(
356
369
  False, '--print', '-p', help='Whether to print outputs to terminal.'
357
370
  ),
@@ -414,6 +427,7 @@ def irun(
414
427
  if generator is not None
415
428
  else None,
416
429
  testcase_entry=TestcaseEntry.parse(testcase) if testcase else None,
430
+ custom_output=output,
417
431
  print=print,
418
432
  sanitized=sanitized,
419
433
  )
@@ -156,11 +156,11 @@ class CodeItem(BaseModel):
156
156
  )
157
157
 
158
158
  language: Optional[str] = Field(
159
- None, description="""The language of the code file."""
159
+ default=None, description="""The language of the code file."""
160
160
  )
161
161
 
162
162
  compilationFiles: Optional[List[str]] = Field(
163
- [],
163
+ default=[],
164
164
  description="""
165
165
  Extra files that should be placed alongside the code file during its compilation,
166
166
  such as testlib.h, jngen.h, etc.
@@ -189,7 +189,7 @@ class GeneratorCall(BaseModel):
189
189
  name: str = FNameField(description='The name of the generator to call.')
190
190
 
191
191
  args: Optional[str] = Field(
192
- None, description='The arguments to pass to the generator.'
192
+ default=None, description='The arguments to pass to the generator.'
193
193
  )
194
194
 
195
195
 
@@ -199,31 +199,31 @@ class TestcaseSubgroup(BaseModel):
199
199
  name: str = NameField(description='The name of the test group.')
200
200
 
201
201
  testcases: List[Testcase] = Field(
202
- [],
202
+ default=[],
203
203
  description="""
204
204
  The path of testcases to add to this group,
205
205
  in the order they're defined.""",
206
206
  )
207
207
 
208
208
  testcaseGlob: Optional[str] = Field(
209
- None,
209
+ default=None,
210
210
  description="""
211
211
  A Python glob that matches input file paths relative to the
212
212
  package directory. The globbed files should end with the extension
213
213
  ".in", and their corresponding outputs, if defined, should have the same file name,
214
- but ending with ".out".
214
+ but ending with ".ans".
215
215
  """,
216
216
  )
217
217
 
218
218
  generators: List[GeneratorCall] = Field(
219
- [],
219
+ default=[],
220
220
  description="""
221
221
  A list of generators to call to generate testcases for this group.
222
222
  """,
223
223
  )
224
224
 
225
225
  generatorScript: Optional[CodeItem] = Field(
226
- None,
226
+ default=None,
227
227
  description="""
228
228
  A generator script to call to generate testcases for this group.
229
229
  """,
@@ -247,14 +247,14 @@ class TestcaseGroup(TestcaseSubgroup):
247
247
  model_config = ConfigDict(extra='forbid')
248
248
 
249
249
  subgroups: List[TestcaseSubgroup] = Field(
250
- [],
250
+ default=[],
251
251
  description="""
252
252
  A list of test subgroups to define for this group.
253
253
  """,
254
254
  )
255
255
 
256
256
  validator: Optional[CodeItem] = Field(
257
- None,
257
+ default=None,
258
258
  description="""
259
259
  A validator to use to validate the testcases of this group.
260
260
  If not specified, will use the package-level validator.
@@ -263,7 +263,7 @@ Useful in cases where the constraints vary across test groups.
263
263
  )
264
264
 
265
265
  weight: Optional[float] = Field(
266
- 1.0,
266
+ default=1.0,
267
267
  description="""
268
268
  The weight of this group in the final score. Useful for
269
269
  problems that have points.
@@ -301,29 +301,29 @@ class Stress(BaseModel):
301
301
 
302
302
  class Limits(BaseModel):
303
303
  time: Optional[int] = Field(
304
- None, description='Value to override time limit with, in milliseconds.'
304
+ default=None, description='Value to override time limit with, in milliseconds.'
305
305
  )
306
306
  memory: Optional[int] = Field(
307
- None, description='Value to override memory limit with, in MB.'
307
+ default=None, description='Value to override memory limit with, in MB.'
308
308
  )
309
309
  output: Optional[int] = Field(
310
- None, description='Value to override output limit with, in KB.'
310
+ default=None, description='Value to override output limit with, in KB.'
311
311
  )
312
312
 
313
313
  isDoubleTL: bool = Field(
314
- False, description='Whether to use double TL for this language.'
314
+ default=False, description='Whether to use double TL for this language.'
315
315
  )
316
316
 
317
317
 
318
318
  class LimitModifiers(BaseModel):
319
319
  timeMultiplier: Optional[float] = Field(
320
- None, description='Multiplier for time limit.'
320
+ default=None, description='Multiplier for time limit.'
321
321
  )
322
322
  time: Optional[int] = Field(
323
- None, description='Value to override time limit with, in milliseconds.'
323
+ default=None, description='Value to override time limit with, in milliseconds.'
324
324
  )
325
325
  memory: Optional[int] = Field(
326
- None, description='Value to override memory limit with, in MB.'
326
+ default=None, description='Value to override memory limit with, in MB.'
327
327
  )
328
328
 
329
329
 
@@ -338,28 +338,30 @@ class Package(BaseModel):
338
338
  memoryLimit: int = Field(description='Memory limit of the problem, in MB.')
339
339
 
340
340
  outputLimit: int = Field(
341
- 4 * 1024, description='Output limit of the problem, in KB.'
341
+ default=4 * 1024, description='Output limit of the problem, in KB.'
342
342
  )
343
343
 
344
344
  modifiers: Dict[str, LimitModifiers] = Field(
345
- {},
345
+ default={},
346
346
  description="""
347
347
  Limit modifiers that can be specified per language.
348
348
  """,
349
349
  )
350
350
 
351
351
  checker: Optional[CodeItem] = Field(
352
- None, description='The checker for this problem.'
352
+ default=None, description='The checker for this problem.'
353
353
  )
354
354
 
355
355
  validator: Optional[CodeItem] = Field(
356
- None, description='The validator for this problem.'
356
+ default=None, description='The validator for this problem.'
357
357
  )
358
358
 
359
- generators: List[Generator] = Field([], description='Generators for this problem.')
359
+ generators: List[Generator] = Field(
360
+ default=[], description='Generators for this problem.'
361
+ )
360
362
 
361
363
  solutions: List[Solution] = Field(
362
- [],
364
+ default=[],
363
365
  description="""
364
366
  All tested solutions for this problem.
365
367
 
@@ -368,17 +370,23 @@ that is correct and used as reference -- and should have the `accepted` outcome.
368
370
  """,
369
371
  )
370
372
 
371
- testcases: List[TestcaseGroup] = Field([], description='Testcases for the problem.')
373
+ testcases: List[TestcaseGroup] = Field(
374
+ default=[], description='Testcases for the problem.'
375
+ )
372
376
 
373
- stresses: List[Stress] = Field([], description='Stress tests for the problem.')
377
+ stresses: List[Stress] = Field(
378
+ default=[], description='Stress tests for the problem.'
379
+ )
374
380
 
375
- statements: List[Statement] = Field([], description='Statements for the problem.')
381
+ statements: List[Statement] = Field(
382
+ default=[], description='Statements for the problem.'
383
+ )
376
384
 
377
385
  # Vars to be re-used across the package.
378
386
  # - It will be passed as --key=value arguments to the validator.
379
387
  # - It will be available as \VAR{key} variables in the rbx statement.
380
388
  vars: Dict[str, Primitive] = Field(
381
- {}, description='Variables to be re-used across the package.'
389
+ default={}, description='Variables to be re-used across the package.'
382
390
  )
383
391
 
384
392
  @property
@@ -19,36 +19,36 @@ _CONFIG_FILE_NAME_MAC = 'default_setter_config.mac.yml'
19
19
 
20
20
  class SanitizersConfig(BaseModel):
21
21
  enabled: bool = Field(
22
- False,
22
+ default=False,
23
23
  description='Whether to use sanitizers when running solutions.',
24
24
  )
25
25
 
26
26
  command_substitutions: Dict[str, str] = Field(
27
- {},
27
+ default={},
28
28
  description='Substitutions to apply to commands before running them with sanitizers.',
29
29
  )
30
30
 
31
31
 
32
32
  class WarningsConfig(BaseModel):
33
33
  enabled: bool = Field(
34
- False,
34
+ default=False,
35
35
  description='Whether to use warning flags when running solutions.',
36
36
  )
37
37
 
38
38
 
39
39
  class RepeatsConfig(BaseModel):
40
40
  reps: int = Field(
41
- 1,
41
+ default=1,
42
42
  description='Number of times to repeat the solution.',
43
43
  )
44
44
 
45
45
  retries: int = Field(
46
- 0,
46
+ default=0,
47
47
  description='Number of times to retry if the solution TLs.',
48
48
  )
49
49
 
50
50
  retries_for_stress: int = Field(
51
- 0,
51
+ default=0,
52
52
  description='Number of times to retry in stress mode if the solution TLs.',
53
53
  )
54
54
 
@@ -69,7 +69,7 @@ class SetterConfig(BaseModel):
69
69
  )
70
70
 
71
71
  command_substitutions: Dict[str, str] = Field(
72
- {},
72
+ default={},
73
73
  description='Substitutions to apply to commands before running them.',
74
74
  )
75
75