rbx.cp 0.5.37__tar.gz → 0.5.39__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 (176) hide show
  1. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/PKG-INFO +1 -1
  2. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/pyproject.toml +1 -1
  3. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/annotations.py +0 -1
  4. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/code.py +1 -1
  5. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/contest/statements.py +3 -1
  6. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/generators.py +2 -1
  7. rbx_cp-0.5.39/rbx/box/lazy_importing_main.py +7 -0
  8. rbx_cp-0.5.39/rbx/box/lazy_importing_test.py +25 -0
  9. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/main.py +100 -22
  10. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/packaging/contest_main.py +5 -1
  11. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/packaging/main.py +7 -3
  12. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/presets/__init__.py +6 -2
  13. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/setter_config.py +0 -1
  14. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/solutions.py +33 -11
  15. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/state.py +1 -0
  16. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/statements/build_statements.py +3 -1
  17. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/statements/builders.py +7 -6
  18. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/statements/joiners.py +7 -6
  19. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/config.py +8 -2
  20. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/judge/sandboxes/stupid_sandbox.py +0 -1
  21. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testing_utils.py +0 -1
  22. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/utils.py +1 -4
  23. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/LICENSE +0 -0
  24. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/README.md +0 -0
  25. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/__init__.py +0 -0
  26. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/autoenum.py +0 -0
  27. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/__init__.py +0 -0
  28. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/builder.py +0 -0
  29. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/cd.py +0 -0
  30. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/checkers.py +0 -0
  31. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/compile.py +0 -0
  32. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/conftest.py +0 -0
  33. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/contest/__init__.py +0 -0
  34. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/contest/build_contest_statements.py +0 -0
  35. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/contest/contest_package.py +0 -0
  36. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/contest/contest_utils.py +0 -0
  37. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/contest/main.py +0 -0
  38. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/contest/schema.py +0 -0
  39. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/creation.py +0 -0
  40. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/deferred.py +0 -0
  41. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/download.py +0 -0
  42. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/environment.py +0 -0
  43. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/extensions.py +0 -0
  44. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/formatting.py +0 -0
  45. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/generators_test.py +0 -0
  46. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/package.py +0 -0
  47. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/packaging/boca/extension.py +0 -0
  48. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/packaging/boca/packager.py +0 -0
  49. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/packaging/packager.py +0 -0
  50. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/packaging/polygon/packager.py +0 -0
  51. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/packaging/polygon/test.py +0 -0
  52. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/packaging/polygon/xml_schema.py +0 -0
  53. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/presets/fetch.py +0 -0
  54. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/presets/lock_schema.py +0 -0
  55. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/presets/schema.py +0 -0
  56. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/retries.py +0 -0
  57. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/sanitizers/warning_stack.py +0 -0
  58. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/schema.py +0 -0
  59. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/solutions_test.py +0 -0
  60. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/statements/__init__.py +0 -0
  61. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/statements/latex.py +0 -0
  62. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/statements/latex_jinja.py +0 -0
  63. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/statements/schema.py +0 -0
  64. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/stresses.py +0 -0
  65. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/stressing/__init__.py +0 -0
  66. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/stressing/finder_parser.py +0 -0
  67. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/stressing/generator_parser.py +0 -0
  68. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/testcase_extractors.py +0 -0
  69. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/testcase_utils.py +0 -0
  70. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/testcases/__init__.py +0 -0
  71. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/testcases/main.py +0 -0
  72. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/ui/__init__.py +0 -0
  73. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/ui/captured_log.py +0 -0
  74. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/ui/css/app.tcss +0 -0
  75. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/ui/main.py +0 -0
  76. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/ui/run.py +0 -0
  77. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/validators.py +0 -0
  78. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/box/validators_test.py +0 -0
  79. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/checker.py +0 -0
  80. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/clone.py +0 -0
  81. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/conftest.py +0 -0
  82. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/console.py +0 -0
  83. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/create.py +0 -0
  84. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/edit.py +0 -0
  85. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/__init__.py +0 -0
  86. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/caching.py +0 -0
  87. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/conftest.py +0 -0
  88. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/judge/__init__.py +0 -0
  89. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/judge/cacher.py +0 -0
  90. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/judge/digester.py +0 -0
  91. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/judge/sandbox.py +0 -0
  92. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/judge/sandboxes/__init__.py +0 -0
  93. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/judge/sandboxes/isolate.py +0 -0
  94. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/judge/sandboxes/timeit.py +0 -0
  95. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/judge/storage.py +0 -0
  96. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/judge/test.py +0 -0
  97. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/judge/testiso.py +0 -0
  98. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/steps.py +0 -0
  99. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/steps_with_caching.py +0 -0
  100. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading/steps_with_caching_run_test.py +0 -0
  101. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/grading_utils.py +0 -0
  102. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/hydration.py +0 -0
  103. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/main.py +0 -0
  104. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/metadata.py +0 -0
  105. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/providers/__init__.py +0 -0
  106. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/providers/codeforces.py +0 -0
  107. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/providers/provider.py +0 -0
  108. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/checkers/boilerplate.cpp +0 -0
  109. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/default_config.json +0 -0
  110. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/default_setter_config.mac.yml +0 -0
  111. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/default_setter_config.yml +0 -0
  112. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/envs/default.rbx.yml +0 -0
  113. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/envs/isolate.rbx.yml +0 -0
  114. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/checker.sh +0 -0
  115. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/compare +0 -0
  116. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/compile/c +0 -0
  117. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/compile/cc +0 -0
  118. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/compile/cpp +0 -0
  119. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/compile/java +0 -0
  120. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/compile/kt +0 -0
  121. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/compile/pas +0 -0
  122. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/compile/py2 +0 -0
  123. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/compile/py3 +0 -0
  124. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/run/c +0 -0
  125. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/run/cc +0 -0
  126. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/run/cpp +0 -0
  127. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/run/java +0 -0
  128. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/run/kt +0 -0
  129. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/run/py2 +0 -0
  130. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/packagers/boca/run/py3 +0 -0
  131. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/contest/contest.rbx.yml +0 -0
  132. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/contest/statement/contest.rbx.tex +0 -0
  133. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/contest/statement/olymp.sty +0 -0
  134. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/contest/statement/template.rbx.tex +0 -0
  135. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/preset.rbx.yml +0 -0
  136. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/.gitignore +0 -0
  137. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/gen.cpp +0 -0
  138. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/problem.rbx.yml +0 -0
  139. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/random.py +0 -0
  140. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/random.txt +0 -0
  141. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/sols/main.cpp +0 -0
  142. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/sols/slow.cpp +0 -0
  143. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/sols/wa.cpp +0 -0
  144. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/statement/olymp.sty +0 -0
  145. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/statement/projecao.png +0 -0
  146. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/statement/statement.rbx.tex +0 -0
  147. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/statement/template.rbx.tex +0 -0
  148. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/tests/samples/000.in +0 -0
  149. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/tests/samples/001.in +0 -0
  150. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/validator.cpp +0 -0
  151. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/presets/default/problem/wcmp.cpp +0 -0
  152. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/resources/templates/template.cpp +0 -0
  153. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/run.py +0 -0
  154. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/schema.py +0 -0
  155. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/submit.py +0 -0
  156. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/submitors/__init__.py +0 -0
  157. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/submitors/codeforces.py +0 -0
  158. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/submitors/submitor.py +0 -0
  159. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/test.py +0 -0
  160. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testcase.py +0 -0
  161. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testcase_rendering.py +0 -0
  162. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/box1/gen1.cpp +0 -0
  163. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/box1/gen2.cpp +0 -0
  164. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/box1/genScript.py +0 -0
  165. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/box1/hard-tle.sol.cpp +0 -0
  166. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/box1/ole.cpp +0 -0
  167. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/box1/problem.rbx.yml +0 -0
  168. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/box1/re.sol.cpp +0 -0
  169. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/box1/sol.cpp +0 -0
  170. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/box1/tests/1.in +0 -0
  171. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/box1/tle-and-incorrect.sol.cpp +0 -0
  172. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/box1/tle.sol.cpp +0 -0
  173. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/box1/validator.cpp +0 -0
  174. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/box1/wa.sol.cpp +0 -0
  175. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/caching/executable.py +0 -0
  176. {rbx_cp-0.5.37 → rbx_cp-0.5.39}/rbx/testdata/compatible +0 -0
@@ -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,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "rbx.cp"
3
- version = "0.5.37"
3
+ version = "0.5.39"
4
4
  description = ""
5
5
  packages = [
6
6
  {include = "rbx"}
@@ -1,4 +1,3 @@
1
- import importlib
2
1
  import importlib.resources
3
2
  import pathlib
4
3
  import re
@@ -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]...'
@@ -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
@@ -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
  )
@@ -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,
@@ -1,5 +1,4 @@
1
1
  import functools
2
- import importlib
3
2
  import importlib.resources
4
3
  import pathlib
5
4
  import shlex
@@ -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)
@@ -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