rbx.cp 0.5.32__tar.gz → 0.5.34__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.32 → rbx_cp-0.5.34}/PKG-INFO +3 -2
  2. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/pyproject.toml +1 -1
  3. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/code.py +6 -7
  4. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/contest/build_contest_statements.py +3 -2
  5. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/main.py +0 -5
  6. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/package.py +7 -0
  7. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/solutions.py +60 -13
  8. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/statements/build_statements.py +4 -1
  9. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/statements/builders.py +24 -5
  10. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/validators.py +5 -0
  11. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/utils.py +8 -0
  12. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/LICENSE +0 -0
  13. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/README.md +0 -0
  14. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/__init__.py +0 -0
  15. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/annotations.py +0 -0
  16. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/autoenum.py +0 -0
  17. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/__init__.py +0 -0
  18. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/builder.py +0 -0
  19. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/cd.py +0 -0
  20. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/checkers.py +0 -0
  21. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/compile.py +0 -0
  22. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/conftest.py +0 -0
  23. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/contest/__init__.py +0 -0
  24. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/contest/contest_package.py +0 -0
  25. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/contest/contest_utils.py +0 -0
  26. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/contest/main.py +0 -0
  27. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/contest/schema.py +0 -0
  28. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/contest/statements.py +0 -0
  29. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/creation.py +0 -0
  30. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/deferred.py +0 -0
  31. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/download.py +0 -0
  32. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/environment.py +0 -0
  33. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/extensions.py +0 -0
  34. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/formatting.py +0 -0
  35. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/generators.py +0 -0
  36. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/generators_test.py +0 -0
  37. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/packaging/boca/extension.py +0 -0
  38. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/packaging/boca/packager.py +0 -0
  39. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/packaging/contest_main.py +0 -0
  40. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/packaging/main.py +0 -0
  41. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/packaging/packager.py +0 -0
  42. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/packaging/polygon/packager.py +0 -0
  43. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/packaging/polygon/test.py +0 -0
  44. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/packaging/polygon/xml_schema.py +0 -0
  45. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/presets/__init__.py +0 -0
  46. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/presets/fetch.py +0 -0
  47. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/presets/lock_schema.py +0 -0
  48. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/presets/schema.py +0 -0
  49. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/retries.py +0 -0
  50. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/sanitizers/warning_stack.py +0 -0
  51. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/schema.py +0 -0
  52. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/setter_config.py +0 -0
  53. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/solutions_test.py +0 -0
  54. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/state.py +0 -0
  55. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/statements/__init__.py +0 -0
  56. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/statements/joiners.py +0 -0
  57. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/statements/latex.py +0 -0
  58. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/statements/latex_jinja.py +0 -0
  59. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/statements/schema.py +0 -0
  60. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/stresses.py +0 -0
  61. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/stressing/__init__.py +0 -0
  62. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/stressing/finder_parser.py +0 -0
  63. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/stressing/generator_parser.py +0 -0
  64. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/testcases.py +0 -0
  65. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/ui/__init__.py +0 -0
  66. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/ui/captured_log.py +0 -0
  67. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/ui/css/app.tcss +0 -0
  68. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/ui/main.py +0 -0
  69. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/ui/run.py +0 -0
  70. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/box/validators_test.py +0 -0
  71. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/checker.py +0 -0
  72. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/clone.py +0 -0
  73. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/config.py +0 -0
  74. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/conftest.py +0 -0
  75. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/console.py +0 -0
  76. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/create.py +0 -0
  77. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/edit.py +0 -0
  78. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/__init__.py +0 -0
  79. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/caching.py +0 -0
  80. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/conftest.py +0 -0
  81. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/judge/__init__.py +0 -0
  82. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/judge/cacher.py +0 -0
  83. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/judge/digester.py +0 -0
  84. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/judge/sandbox.py +0 -0
  85. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/judge/sandboxes/__init__.py +0 -0
  86. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/judge/sandboxes/isolate.py +0 -0
  87. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/judge/sandboxes/stupid_sandbox.py +0 -0
  88. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/judge/sandboxes/timeit.py +0 -0
  89. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/judge/storage.py +0 -0
  90. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/judge/test.py +0 -0
  91. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/judge/testiso.py +0 -0
  92. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/steps.py +0 -0
  93. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/steps_with_caching.py +0 -0
  94. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading/steps_with_caching_run_test.py +0 -0
  95. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/grading_utils.py +0 -0
  96. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/hydration.py +0 -0
  97. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/main.py +0 -0
  98. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/metadata.py +0 -0
  99. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/providers/__init__.py +0 -0
  100. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/providers/codeforces.py +0 -0
  101. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/providers/provider.py +0 -0
  102. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/checkers/boilerplate.cpp +0 -0
  103. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/default_config.json +0 -0
  104. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/default_setter_config.mac.yml +0 -0
  105. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/default_setter_config.yml +0 -0
  106. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/envs/default.rbx.yml +0 -0
  107. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/envs/isolate.rbx.yml +0 -0
  108. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/checker.sh +0 -0
  109. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/compare +0 -0
  110. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/compile/c +0 -0
  111. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/compile/cc +0 -0
  112. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/compile/cpp +0 -0
  113. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/compile/java +0 -0
  114. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/compile/kt +0 -0
  115. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/compile/pas +0 -0
  116. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/compile/py2 +0 -0
  117. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/compile/py3 +0 -0
  118. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/run/c +0 -0
  119. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/run/cc +0 -0
  120. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/run/cpp +0 -0
  121. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/run/java +0 -0
  122. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/run/kt +0 -0
  123. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/run/py2 +0 -0
  124. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/packagers/boca/run/py3 +0 -0
  125. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/contest/contest.rbx.yml +0 -0
  126. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/contest/statement/contest.rbx.tex +0 -0
  127. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/contest/statement/olymp.sty +0 -0
  128. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/contest/statement/template.rbx.tex +0 -0
  129. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/preset.rbx.yml +0 -0
  130. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/.gitignore +0 -0
  131. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/gen.cpp +0 -0
  132. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/problem.rbx.yml +0 -0
  133. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/random.py +0 -0
  134. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/random.txt +0 -0
  135. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/sols/main.cpp +0 -0
  136. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/sols/slow.cpp +0 -0
  137. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/sols/wa.cpp +0 -0
  138. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/statement/olymp.sty +0 -0
  139. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/statement/projecao.png +0 -0
  140. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/statement/statement.rbx.tex +0 -0
  141. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/statement/template.rbx.tex +0 -0
  142. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/tests/samples/000.in +0 -0
  143. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/tests/samples/001.in +0 -0
  144. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/validator.cpp +0 -0
  145. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/presets/default/problem/wcmp.cpp +0 -0
  146. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/resources/templates/template.cpp +0 -0
  147. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/run.py +0 -0
  148. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/schema.py +0 -0
  149. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/submit.py +0 -0
  150. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/submitors/__init__.py +0 -0
  151. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/submitors/codeforces.py +0 -0
  152. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/submitors/submitor.py +0 -0
  153. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/test.py +0 -0
  154. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testcase.py +0 -0
  155. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testcase_rendering.py +0 -0
  156. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/box1/gen1.cpp +0 -0
  157. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/box1/gen2.cpp +0 -0
  158. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/box1/genScript.py +0 -0
  159. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/box1/hard-tle.sol.cpp +0 -0
  160. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/box1/ole.cpp +0 -0
  161. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/box1/problem.rbx.yml +0 -0
  162. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/box1/re.sol.cpp +0 -0
  163. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/box1/sol.cpp +0 -0
  164. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/box1/tests/1.in +0 -0
  165. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/box1/tle-and-incorrect.sol.cpp +0 -0
  166. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/box1/tle.sol.cpp +0 -0
  167. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/box1/validator.cpp +0 -0
  168. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/box1/wa.sol.cpp +0 -0
  169. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/caching/executable.py +0 -0
  170. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testdata/compatible +0 -0
  171. {rbx_cp-0.5.32 → rbx_cp-0.5.34}/rbx/testing_utils.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: rbx.cp
3
- Version: 0.5.32
3
+ Version: 0.5.34
4
4
  Summary:
5
5
  Author: Roberto Sales
6
6
  Requires-Python: >=3.9,<4.0
@@ -9,6 +9,7 @@ Classifier: Programming Language :: Python :: 3.9
9
9
  Classifier: Programming Language :: Python :: 3.10
10
10
  Classifier: Programming Language :: Python :: 3.11
11
11
  Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
12
13
  Requires-Dist: chardet (>=5.2.0,<6.0.0)
13
14
  Requires-Dist: fastapi (>=0.115.8,<0.116.0)
14
15
  Requires-Dist: filelock (>=3.14.0,<4.0.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "rbx.cp"
3
- version = "0.5.32"
3
+ version = "0.5.34"
4
4
  description = ""
5
5
  packages = [
6
6
  {include = "rbx"}
@@ -186,15 +186,14 @@ def _check_stack_limit():
186
186
  if hard != resource.RLIM_INFINITY:
187
187
  target_text = min(hard, TARGET)
188
188
  console.console.print(
189
- """
189
+ f"""
190
190
  ```
191
- export RBX_BIN_PATH=`which rbx`
192
- function rbx() {
193
- ulimit -s %s && $RBX_BIN_PATH $@
194
- }
191
+ function rbx() {{
192
+ local rbx_bin=`bash -c "type -P rbx"`
193
+ ulimit -s {target_text // 1024} && $rbx_bin $@
194
+ }}
195
195
  ```
196
- """
197
- % target_text
196
+ """
198
197
  )
199
198
  console.console.print()
200
199
  console.console.print(
@@ -22,6 +22,7 @@ from rbx.box.statements.builders import (
22
22
  StatementBuilderContest,
23
23
  StatementBuilderContext,
24
24
  StatementBuilderProblem,
25
+ StatementSample,
25
26
  prepare_assets,
26
27
  )
27
28
  from rbx.box.statements.joiners import (
@@ -51,7 +52,7 @@ class ExtractedProblem:
51
52
  return StatementBuilderProblem(
52
53
  package=self.package,
53
54
  statement=self.statement,
54
- samples=self.samples,
55
+ samples=StatementSample.from_testcases(self.samples),
55
56
  io_path=self.built_statement,
56
57
  short_name=self.problem.short_name,
57
58
  )
@@ -124,7 +125,7 @@ def get_builder_problems(
124
125
  StatementBuilderProblem(
125
126
  package=ex.package,
126
127
  statement=ex.statement,
127
- samples=ex.samples,
128
+ samples=StatementSample.from_testcases(ex.samples),
128
129
  )
129
130
  for ex in extracted_problems
130
131
  ]
@@ -760,8 +760,3 @@ def clear():
760
760
  console.console.print('Cleaning cache and build directories...')
761
761
  shutil.rmtree('.box', ignore_errors=True)
762
762
  shutil.rmtree('build', ignore_errors=True)
763
-
764
-
765
- @app.callback()
766
- def callback():
767
- pass
@@ -364,6 +364,13 @@ def get_compilation_files(code: CodeItem) -> List[Tuple[pathlib.Path, pathlib.Pa
364
364
  return res
365
365
 
366
366
 
367
+ @functools.cache
368
+ def get_empty_sentinel_path(root: pathlib.Path = pathlib.Path()) -> pathlib.Path:
369
+ path = get_problem_cache_dir(root) / '.empty'
370
+ path.write_text('')
371
+ return path
372
+
373
+
367
374
  def clear_package_cache():
368
375
  pkgs = [sys.modules[__name__]]
369
376
 
@@ -911,38 +911,81 @@ class TimingSummary:
911
911
  if self.fastest_slow is None or time < self.fastest_slow:
912
912
  self.fastest_slow = time
913
913
 
914
+ def print(self, console: rich.console.Console, tl: Optional[int] = None):
915
+ if self.slowest_good is not None:
916
+ console.print(
917
+ f'Slowest [success]OK[/success] solution: {self.slowest_good} ms'
918
+ )
919
+ if self.fastest_slow is not None:
920
+ fastest_slow = self.fastest_slow
921
+ if tl is not None and self.fastest_slow > tl:
922
+ fastest_slow = f'>{tl}'
923
+ console.print(f'Fastest [error]slow[/error] solution: {fastest_slow} ms')
924
+
914
925
 
915
926
  async def _print_timing(
916
927
  console: rich.console.Console,
917
928
  skeleton: SolutionReportSkeleton,
918
929
  evaluations: StructuredEvaluation,
930
+ verification: VerificationLevel,
919
931
  ):
932
+ pkg = package.find_problem_package_or_die()
920
933
  summary = TimingSummary()
921
- sumamry_per_language = collections.defaultdict(TimingSummary)
934
+ summary_per_language = collections.defaultdict(TimingSummary)
935
+ tls_per_language = {}
936
+ all_tls = set()
922
937
  for solution in skeleton.solutions:
923
- all_evals = []
938
+ all_evals: List[Evaluation] = []
924
939
  for evals in evaluations[str(solution.path)].values():
925
940
  all_evals.extend([await eval() for eval in evals if eval is not None])
941
+ if not all_evals:
942
+ continue
943
+
944
+ # Get solution TL.
926
945
  solution_time = _get_evals_time_in_ms(all_evals)
946
+ solution_tls = [
947
+ eval.log.metadata.timeLimit
948
+ for eval in all_evals
949
+ if eval.log.metadata is not None and eval.log.metadata.timeLimit is not None
950
+ ]
951
+ solution_tl = 0
952
+ if solution_tls:
953
+ solution_tl = min(solution_tls)
954
+ else:
955
+ solution_tl = pkg.timelimit_for_language(solution.language)
956
+ if verification.value >= VerificationLevel.FULL.value:
957
+ solution_tl = solution_tl * 2
958
+ all_tls.add(solution_tl)
959
+ for eval in all_evals:
960
+ if eval.log.get_run_language() is not None:
961
+ tls_per_language[eval.log.get_run_language()] = solution_tl
962
+
963
+ # Get solution timings.
927
964
  if solution.outcome.match(Outcome.ACCEPTED):
928
965
  summary.add_good(solution_time)
929
- sumamry_per_language[solution.language].add_good(solution_time)
966
+ summary_per_language[solution.language].add_good(solution_time)
930
967
  if solution.outcome.is_slow():
931
968
  summary.add_slow(solution_time)
932
- sumamry_per_language[solution.language].add_slow(solution_time)
969
+ summary_per_language[solution.language].add_slow(solution_time)
933
970
 
934
971
  if summary.slowest_good is None and summary.fastest_slow is None:
935
972
  return
936
973
 
974
+ all_languages = set(summary_per_language)
975
+ all_tl = min(all_tls) if all_tls else None
937
976
  console.print('[status]Timing summary:[/status]')
938
- if summary.slowest_good is not None:
939
- console.print(
940
- f'Slowest [success]OK[/success] solution: {summary.slowest_good} ms'
941
- )
942
- if summary.fastest_slow is not None:
943
- console.print(
944
- f'Fastest [error]slow[/error] solution: {summary.fastest_slow} ms'
977
+
978
+ if len(all_languages) <= 1 or len(all_tls) <= 1:
979
+ summary.print(console, tl=all_tl)
980
+ return
981
+
982
+ # Otherwise, print per language.
983
+ for lang in sorted(all_languages):
984
+ console.print(f'[status]{lang}[/status]')
985
+ summary_per_language[lang].print(
986
+ console, tl=tls_per_language.get(lang) or all_tl
945
987
  )
988
+ console.print()
946
989
 
947
990
 
948
991
  def _length_markup(markup: str) -> int:
@@ -1109,7 +1152,9 @@ async def _print_detailed_run_report(
1109
1152
  console.print()
1110
1153
 
1111
1154
  if timing:
1112
- await _print_timing(console, result.skeleton, structured_evaluations)
1155
+ await _print_timing(
1156
+ console, result.skeleton, structured_evaluations, verification=verification
1157
+ )
1113
1158
  return ok
1114
1159
 
1115
1160
 
@@ -1193,7 +1238,9 @@ async def print_run_report(
1193
1238
  ok = ok and cur_ok
1194
1239
  console.print()
1195
1240
 
1196
- await _print_timing(console, result.skeleton, structured_evaluations)
1241
+ await _print_timing(
1242
+ console, result.skeleton, structured_evaluations, verification=verification
1243
+ )
1197
1244
 
1198
1245
  return ok
1199
1246
 
@@ -15,6 +15,7 @@ from rbx.box.statements.builders import (
15
15
  StatementBuilderContext,
16
16
  StatementBuilderProblem,
17
17
  StatementCodeLanguage,
18
+ StatementSample,
18
19
  prepare_assets,
19
20
  )
20
21
  from rbx.box.statements.schema import (
@@ -263,7 +264,9 @@ def build_statement_bytes(
263
264
  item=StatementBuilderProblem(
264
265
  package=pkg,
265
266
  statement=statement,
266
- samples=get_samples() if use_samples else [],
267
+ samples=StatementSample.from_testcases(
268
+ get_samples() if use_samples else []
269
+ ),
267
270
  short_name=short_name,
268
271
  ),
269
272
  verbose=False,
@@ -7,8 +7,9 @@ from abc import ABC, abstractmethod
7
7
  from typing import Any, Dict, List, Optional, Tuple
8
8
 
9
9
  import typer
10
+ from pydantic import BaseModel
10
11
 
11
- from rbx import console
12
+ from rbx import console, utils
12
13
  from rbx.box.schema import Package, Primitive, Testcase
13
14
  from rbx.box.statements.latex import (
14
15
  MAX_PDFLATEX_RUNS,
@@ -64,7 +65,25 @@ class StatementBuilderItem(ABC):
64
65
  pass
65
66
 
66
67
 
67
- class StatementSample(Testcase):
68
+ class StatementSample(BaseModel):
69
+ inputPath: pathlib.Path
70
+ outputPath: pathlib.Path
71
+ hasOutput: bool = True
72
+
73
+ @staticmethod
74
+ def from_testcase(testcase: Testcase) -> 'StatementSample':
75
+ return StatementSample(
76
+ inputPath=testcase.inputPath,
77
+ outputPath=testcase.outputPath or utils.get_empty_sentinel_path(),
78
+ hasOutput=testcase.outputPath is not None,
79
+ )
80
+
81
+ @staticmethod
82
+ def from_testcases(testcases: List[Testcase]) -> List['StatementSample']:
83
+ return [StatementSample.from_testcase(testcase) for testcase in testcases]
84
+
85
+
86
+ class ExplainedStatementSample(StatementSample):
68
87
  explanation: Optional[str] = None
69
88
 
70
89
 
@@ -72,7 +91,7 @@ class StatementSample(Testcase):
72
91
  class StatementBuilderProblem(StatementBuilderItem):
73
92
  package: Package
74
93
  statement: Statement
75
- samples: List[Testcase] = dataclasses.field(default_factory=list)
94
+ samples: List[StatementSample] = dataclasses.field(default_factory=list)
76
95
  short_name: Optional[str] = None
77
96
 
78
97
  # Will only be filled by contests.
@@ -301,8 +320,8 @@ class rbxTeXBuilder(StatementBuilder):
301
320
  problem_kwargs['problem']['blocks'] = blocks
302
321
  if statement_blocks.explanations is not None:
303
322
  problem_kwargs['problem']['samples'] = [
304
- StatementSample(
305
- **typing.cast(Testcase, sample).model_dump(),
323
+ ExplainedStatementSample(
324
+ **typing.cast(StatementSample, sample).model_dump(),
306
325
  explanation=statement_blocks.explanations.get(i),
307
326
  )
308
327
  for i, sample in enumerate(problem_kwargs['problem']['samples'])
@@ -273,6 +273,11 @@ def print_validation_report(infos: List[TestcaseValidationInfo]):
273
273
  if _is_hit_bound_good(v) and k != 'samples'
274
274
  }
275
275
 
276
+ all_groups = set(info.group for info in infos)
277
+ if len(all_groups) == 1 and 'samples' in all_groups:
278
+ # If there's only the samples group, do not check for hit bounds.
279
+ hit_bounds_per_group = {}
280
+
276
281
  if not hit_bounds_per_group:
277
282
  console.console.print('[info]No validation issues found.[/info]')
278
283
  return
@@ -1,5 +1,6 @@
1
1
  import contextlib
2
2
  import fcntl
3
+ import functools
3
4
  import json
4
5
  import os
5
6
  import pathlib
@@ -98,6 +99,13 @@ def save_ruyaml(path: pathlib.Path, yml: ruyaml.YAML, data: ruyaml.Any):
98
99
  yml.dump(data, f)
99
100
 
100
101
 
102
+ @functools.cache
103
+ def get_empty_sentinel_path() -> pathlib.Path:
104
+ path = get_app_path() / '.empty'
105
+ path.write_text('')
106
+ return path
107
+
108
+
101
109
  @contextlib.contextmanager
102
110
  def no_progress(status: Optional[rich.status.Status]):
103
111
  if status:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes