rbx.cp 0.7.0__tar.gz → 0.9.0__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 (251) hide show
  1. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/PKG-INFO +4 -1
  2. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/pyproject.toml +6 -1
  3. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/cd.py +2 -2
  4. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/cli.py +87 -33
  5. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/code.py +133 -84
  6. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/contest/build_contest_statements.py +2 -2
  7. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/contest/contest_package.py +1 -1
  8. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/contest/main.py +29 -2
  9. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/environment.py +140 -80
  10. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/formatting.py +2 -1
  11. rbx_cp-0.9.0/rbx/box/global_package.py +74 -0
  12. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/package.py +11 -24
  13. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/packaging/polygon/packager.py +3 -3
  14. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/presets/__init__.py +369 -53
  15. rbx_cp-0.9.0/rbx/box/presets/lock_schema.py +59 -0
  16. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/presets/schema.py +4 -0
  17. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/remote.py +21 -2
  18. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/retries.py +3 -2
  19. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/sanitizers/warning_stack.py +5 -5
  20. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/solutions.py +37 -25
  21. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/statements/build_statements.py +6 -6
  22. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/statements/builders.py +1 -1
  23. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/stats.py +10 -0
  24. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/stresses.py +47 -66
  25. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/stressing/finder_parser.py +11 -16
  26. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/tasks.py +33 -22
  27. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/testcase_utils.py +3 -3
  28. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/tooling/boca/scraper.py +1 -1
  29. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/caching.py +98 -47
  30. rbx_cp-0.9.0/rbx/grading/debug_context.py +31 -0
  31. rbx_cp-0.9.0/rbx/grading/grading_context.py +96 -0
  32. rbx_cp-0.9.0/rbx/grading/judge/__init__.py +0 -0
  33. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/judge/cacher.py +93 -21
  34. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/judge/sandbox.py +8 -4
  35. rbx_cp-0.9.0/rbx/grading/judge/sandboxes/__init__.py +0 -0
  36. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/judge/sandboxes/isolate.py +3 -2
  37. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/judge/sandboxes/stupid_sandbox.py +3 -2
  38. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/judge/sandboxes/timeit.py +1 -1
  39. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/judge/storage.py +170 -35
  40. rbx_cp-0.9.0/rbx/grading/profiling.py +126 -0
  41. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/steps.py +46 -17
  42. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/steps_with_caching.py +52 -26
  43. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/envs/default.rbx.yml +2 -3
  44. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/envs/isolate.rbx.yml +2 -3
  45. {rbx_cp-0.7.0/rbx/resources/presets/default/problem → rbx_cp-0.9.0/rbx/resources/presets/default/contest}/.gitignore +1 -1
  46. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/presets/default/contest/contest.rbx.yml +14 -1
  47. rbx_cp-0.9.0/rbx/resources/presets/default/contest/statement/contest.rbx.tex +35 -0
  48. rbx_cp-0.9.0/rbx/resources/presets/default/contest/statement/instructions.tex +40 -0
  49. rbx_cp-0.9.0/rbx/resources/presets/default/contest/statement/logo.png +0 -0
  50. rbx_cp-0.9.0/rbx/resources/presets/default/env.rbx.yml +67 -0
  51. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/presets/default/preset.rbx.yml +6 -2
  52. rbx_cp-0.9.0/rbx/resources/presets/default/problem/.gitignore +6 -0
  53. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/presets/default/problem/problem.rbx.yml +12 -8
  54. rbx_cp-0.9.0/rbx/resources/presets/default/shared/contest_template.rbx.tex +57 -0
  55. rbx_cp-0.9.0/rbx/resources/presets/default/shared/icpc.sty +322 -0
  56. rbx_cp-0.9.0/rbx/resources/presets/default/shared/problem_template.rbx.tex +57 -0
  57. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/submitors/codeforces.py +3 -2
  58. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/test.py +1 -1
  59. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/utils.py +6 -1
  60. rbx_cp-0.7.0/rbx/box/presets/lock_schema.py +0 -19
  61. rbx_cp-0.7.0/rbx/resources/presets/default/contest/statement/contest.rbx.tex +0 -97
  62. rbx_cp-0.7.0/rbx/resources/presets/default/contest/statement/olymp.sty +0 -250
  63. rbx_cp-0.7.0/rbx/resources/presets/default/contest/statement/template.rbx.tex +0 -42
  64. rbx_cp-0.7.0/rbx/resources/presets/default/problem/statement/olymp.sty +0 -250
  65. rbx_cp-0.7.0/rbx/resources/presets/default/problem/statement/template.rbx.tex +0 -89
  66. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/LICENSE +0 -0
  67. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/README.md +0 -0
  68. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/__init__.py +0 -0
  69. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/annotations.py +0 -0
  70. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/autoenum.py +0 -0
  71. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/__init__.py +0 -0
  72. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/builder.py +0 -0
  73. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/checkers.py +0 -0
  74. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/compile.py +0 -0
  75. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/conftest.py +0 -0
  76. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/contest/__init__.py +0 -0
  77. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/contest/contest_utils.py +0 -0
  78. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/contest/schema.py +0 -0
  79. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/contest/statements.py +0 -0
  80. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/creation.py +0 -0
  81. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/deferred.py +0 -0
  82. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/download.py +0 -0
  83. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/dump_schemas.py +0 -0
  84. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/extensions.py +0 -0
  85. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/fields.py +0 -0
  86. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/generators.py +0 -0
  87. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/generators_test.py +0 -0
  88. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/git_utils.py +0 -0
  89. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/header.py +0 -0
  90. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/lang.py +0 -0
  91. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/lazy_importing_main.py +0 -0
  92. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/lazy_importing_test.py +0 -0
  93. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/linting.py +0 -0
  94. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/main.py +0 -0
  95. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/naming.py +0 -0
  96. {rbx_cp-0.7.0/rbx/box/statements → rbx_cp-0.9.0/rbx/box/packaging}/__init__.py +0 -0
  97. {rbx_cp-0.7.0/rbx/box/stressing → rbx_cp-0.9.0/rbx/box/packaging/boca}/__init__.py +0 -0
  98. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/packaging/boca/extension.py +0 -0
  99. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/packaging/boca/packager.py +0 -0
  100. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/packaging/contest_main.py +0 -0
  101. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/packaging/main.py +0 -0
  102. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/packaging/moj/packager.py +0 -0
  103. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/packaging/packager.py +0 -0
  104. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/packaging/pkg/packager.py +0 -0
  105. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/packaging/polygon/polygon_api.py +0 -0
  106. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/packaging/polygon/test.py +0 -0
  107. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/packaging/polygon/upload.py +0 -0
  108. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/packaging/polygon/xml_schema.py +0 -0
  109. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/presets/fetch.py +0 -0
  110. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/schema.py +0 -0
  111. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/setter_config.py +0 -0
  112. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/solutions_test.py +0 -0
  113. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/state.py +0 -0
  114. {rbx_cp-0.7.0/rbx/box/testcases → rbx_cp-0.9.0/rbx/box/statements}/__init__.py +0 -0
  115. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/statements/expander.py +0 -0
  116. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/statements/joiners.py +0 -0
  117. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/statements/latex.py +0 -0
  118. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/statements/latex_jinja.py +0 -0
  119. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/statements/schema.py +0 -0
  120. {rbx_cp-0.7.0/rbx/box/tooling → rbx_cp-0.9.0/rbx/box/stressing}/__init__.py +0 -0
  121. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/stressing/generator_parser.py +0 -0
  122. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/testcase_extractors.py +0 -0
  123. {rbx_cp-0.7.0/rbx/box/tooling/boca → rbx_cp-0.9.0/rbx/box/testcases}/__init__.py +0 -0
  124. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/testcases/main.py +0 -0
  125. {rbx_cp-0.7.0/rbx/box/ui → rbx_cp-0.9.0/rbx/box/tooling}/__init__.py +0 -0
  126. {rbx_cp-0.7.0/rbx/box/ui/screens → rbx_cp-0.9.0/rbx/box/tooling/boca}/__init__.py +0 -0
  127. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/tooling/boca/main.py +0 -0
  128. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/tooling/boca/scrape.py +0 -0
  129. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/tooling/main.py +0 -0
  130. {rbx_cp-0.7.0/rbx/box/ui/utils → rbx_cp-0.9.0/rbx/box/ui}/__init__.py +0 -0
  131. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/captured_log.py +0 -0
  132. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/css/app.tcss +0 -0
  133. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/main.py +0 -0
  134. {rbx_cp-0.7.0/rbx/box/ui/widgets → rbx_cp-0.9.0/rbx/box/ui/screens}/__init__.py +0 -0
  135. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/screens/build.py +0 -0
  136. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/screens/command.py +0 -0
  137. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/screens/differ.py +0 -0
  138. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/screens/error.py +0 -0
  139. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/screens/rich_log_modal.py +0 -0
  140. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/screens/run.py +0 -0
  141. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/screens/run_explorer.py +0 -0
  142. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/screens/run_test_explorer.py +0 -0
  143. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/screens/selector.py +0 -0
  144. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/screens/test_explorer.py +0 -0
  145. {rbx_cp-0.7.0/rbx/grading → rbx_cp-0.9.0/rbx/box/ui/utils}/__init__.py +0 -0
  146. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/utils/run_ui.py +0 -0
  147. {rbx_cp-0.7.0/rbx/grading/judge → rbx_cp-0.9.0/rbx/box/ui/widgets}/__init__.py +0 -0
  148. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/widgets/diff_box.py +0 -0
  149. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/widgets/file_log.py +0 -0
  150. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/widgets/interaction_box.py +0 -0
  151. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/widgets/rich_log_box.py +0 -0
  152. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/widgets/test_output_box.py +0 -0
  153. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/ui/widgets/two_sided_test_output_box.py +0 -0
  154. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/unit.py +0 -0
  155. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/validators.py +0 -0
  156. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/box/validators_test.py +0 -0
  157. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/checker.py +0 -0
  158. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/clone.py +0 -0
  159. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/config.py +0 -0
  160. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/conftest.py +0 -0
  161. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/console.py +0 -0
  162. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/create.py +0 -0
  163. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/edit.py +0 -0
  164. {rbx_cp-0.7.0/rbx/grading/judge/sandboxes → rbx_cp-0.9.0/rbx/grading}/__init__.py +0 -0
  165. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/conftest.py +0 -0
  166. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/judge/digester.py +0 -0
  167. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/judge/test.py +0 -0
  168. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/judge/testiso.py +0 -0
  169. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/limits.py +0 -0
  170. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/processing_context.py +0 -0
  171. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading/steps_with_caching_run_test.py +0 -0
  172. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/grading_utils.py +0 -0
  173. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/hydration.py +0 -0
  174. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/main.py +0 -0
  175. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/metadata.py +0 -0
  176. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/providers/__init__.py +0 -0
  177. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/providers/codeforces.py +0 -0
  178. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/providers/provider.py +0 -0
  179. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/checkers/boilerplate.cpp +0 -0
  180. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/checkers/noop.cpp +0 -0
  181. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/default_config.json +0 -0
  182. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/default_setter_config.mac.yml +0 -0
  183. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/default_setter_config.yml +0 -0
  184. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/checker.sh +0 -0
  185. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/compare.sh +0 -0
  186. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/compile/c +0 -0
  187. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/compile/cc +0 -0
  188. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/compile/cpp +0 -0
  189. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/compile/java +0 -0
  190. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/compile/kt +0 -0
  191. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/compile/py2 +0 -0
  192. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/compile/py3 +0 -0
  193. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/interactive/c +0 -0
  194. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/interactive/cc +0 -0
  195. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/interactive/cpp +0 -0
  196. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/interactive/java +0 -0
  197. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/interactive/kt +0 -0
  198. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/interactive/py2 +0 -0
  199. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/interactive/py3 +0 -0
  200. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/interactor_compile.sh +0 -0
  201. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/interactor_run.sh +0 -0
  202. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/run/bkp +0 -0
  203. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/run/c +0 -0
  204. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/run/cc +0 -0
  205. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/run/cpp +0 -0
  206. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/run/java +0 -0
  207. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/run/kt +0 -0
  208. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/run/py2 +0 -0
  209. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/run/py3 +0 -0
  210. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/safeexec.c +0 -0
  211. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/boca/safeexec_compile.sh +0 -0
  212. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/c/compile.sh +0 -0
  213. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/c/prep.sh +0 -0
  214. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/c/run.sh +0 -0
  215. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/compare.sh +0 -0
  216. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/cpp/compile.sh +0 -0
  217. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/cpp/prep.sh +0 -0
  218. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/cpp/run.sh +0 -0
  219. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/interactor_prep.sh +0 -0
  220. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/interactor_run.sh +0 -0
  221. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/java/compile.sh +0 -0
  222. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/java/prep.sh +0 -0
  223. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/java/run.sh +0 -0
  224. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/py2/compile.sh +0 -0
  225. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/py2/prep.sh +0 -0
  226. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/py2/run.sh +0 -0
  227. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/py3/compile.sh +0 -0
  228. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/py3/prep.sh +0 -0
  229. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/packagers/moj/scripts/py3/run.sh +0 -0
  230. {rbx_cp-0.7.0/rbx/resources/presets/default/problem → rbx_cp-0.9.0/rbx/resources/presets/default/problem/gens}/gen.cpp +0 -0
  231. {rbx_cp-0.7.0/rbx/resources/presets/default/problem/tests → rbx_cp-0.9.0/rbx/resources/presets/default/problem/manual_tests}/samples/000.in +0 -0
  232. {rbx_cp-0.7.0/rbx/resources/presets/default/problem/tests → rbx_cp-0.9.0/rbx/resources/presets/default/problem/manual_tests}/samples/001.in +0 -0
  233. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/presets/default/problem/rbx.h +0 -0
  234. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/presets/default/problem/sols/main.cpp +0 -0
  235. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/presets/default/problem/sols/slow.cpp +0 -0
  236. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/presets/default/problem/sols/wa.cpp +0 -0
  237. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/presets/default/problem/statement/statement.rbx.tex +0 -0
  238. {rbx_cp-0.7.0/rbx/resources/presets/default/problem → rbx_cp-0.9.0/rbx/resources/presets/default/problem/testplan}/random.py +0 -0
  239. {rbx_cp-0.7.0/rbx/resources/presets/default/problem → rbx_cp-0.9.0/rbx/resources/presets/default/problem/testplan}/random.txt +0 -0
  240. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/presets/default/problem/validator.cpp +0 -0
  241. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/presets/default/problem/wcmp.cpp +0 -0
  242. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/templates/rbx.h +0 -0
  243. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/resources/templates/template.cpp +0 -0
  244. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/run.py +0 -0
  245. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/schema.py +0 -0
  246. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/submit.py +0 -0
  247. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/submitors/__init__.py +0 -0
  248. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/submitors/submitor.py +0 -0
  249. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/testcase.py +0 -0
  250. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/testcase_rendering.py +0 -0
  251. {rbx_cp-0.7.0 → rbx_cp-0.9.0}/rbx/testing_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rbx.cp
3
- Version: 0.7.0
3
+ Version: 0.9.0
4
4
  Summary:
5
5
  Author: Roberto Sales
6
6
  Requires-Python: >=3.9.1,<4.0.0
@@ -18,13 +18,16 @@ Requires-Dist: dateparser (>=1.2.1,<2.0.0)
18
18
  Requires-Dist: deepmerge (>=2.0,<3.0)
19
19
  Requires-Dist: fastapi (>=0.115.8,<0.116.0)
20
20
  Requires-Dist: filelock (>=3.14.0,<4.0.0)
21
+ Requires-Dist: gitignore-parser (>=0.1.12,<0.2.0)
21
22
  Requires-Dist: gitpython (>=3.1.43,<4.0.0)
22
23
  Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
23
24
  Requires-Dist: lark (>=1.2.2,<2.0.0)
24
25
  Requires-Dist: latexbuild (>=0.2.2,<0.3.0)
26
+ Requires-Dist: lz4 (>=4.4.4,<5.0.0)
25
27
  Requires-Dist: mechanize (>=0.4.10,<0.5.0)
26
28
  Requires-Dist: more-itertools (>=10.5.0,<11.0.0)
27
29
  Requires-Dist: nest-asyncio (>=1.6.0,<2.0.0)
30
+ Requires-Dist: ordered-set (>=4.1.0,<5.0.0)
28
31
  Requires-Dist: psutil (>=7.0.0,<8.0.0)
29
32
  Requires-Dist: pydantic (==2.8.2)
30
33
  Requires-Dist: pydantic-xml[lxml] (>=2.11.0,<3.0.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "rbx.cp"
3
- version = "0.7.0"
3
+ version = "0.9.0"
4
4
  description = ""
5
5
  packages = [
6
6
  {include = "rbx"}
@@ -45,6 +45,9 @@ dateparser = "^1.2.1"
45
45
  deepmerge = "^2.0"
46
46
  yamlfix = "^1.17.0"
47
47
  ruamel-yaml = "^0.18.14"
48
+ lz4 = "^4.4.4"
49
+ ordered-set = "^4.1.0"
50
+ gitignore-parser = "^0.1.12"
48
51
 
49
52
  [tool.poetry.scripts]
50
53
  rbc = "rbx.main:app"
@@ -75,6 +78,8 @@ version_scheme = "pep440"
75
78
  version_provider = "poetry"
76
79
  update_changelog_on_bump = true
77
80
  major_version_zero = true
81
+ annotated_tag = true
82
+
78
83
  [build-system]
79
84
  requires = ["poetry-core"]
80
85
  build-backend = "poetry.core.masonry.api"
@@ -5,7 +5,7 @@ from typing import List, Optional
5
5
 
6
6
  import typer
7
7
 
8
- from rbx import console
8
+ from rbx import console, utils
9
9
  from rbx.box.sanitizers import warning_stack
10
10
  from rbx.utils import new_cd
11
11
 
@@ -13,7 +13,7 @@ from rbx.utils import new_cd
13
13
  def find_package(
14
14
  root: pathlib.Path = pathlib.Path(), consider_presets: bool = False
15
15
  ) -> Optional[pathlib.Path]:
16
- root = root.resolve()
16
+ root = utils.abspath(root)
17
17
 
18
18
  def has_file():
19
19
  problem_yaml_path = root / 'problem.rbx.yml'
@@ -1,3 +1,4 @@
1
+ import atexit
1
2
  import pathlib
2
3
  import shlex
3
4
  import shutil
@@ -9,6 +10,7 @@ import rich
9
10
  import rich.prompt
10
11
  import syncer
11
12
  import typer
13
+ from ordered_set import OrderedSet
12
14
 
13
15
  from rbx import annotations, config, console, utils
14
16
  from rbx.box import (
@@ -18,6 +20,7 @@ from rbx.box import (
18
20
  download,
19
21
  environment,
20
22
  generators,
23
+ global_package,
21
24
  package,
22
25
  presets,
23
26
  setter_config,
@@ -43,6 +46,7 @@ from rbx.box.statements import build_statements
43
46
  from rbx.box.testcase_utils import TestcaseEntry
44
47
  from rbx.box.testcases import main as testcases
45
48
  from rbx.box.tooling import main as tooling
49
+ from rbx.grading import grading_context
46
50
 
47
51
  app = typer.Typer(no_args_is_help=True, cls=annotations.AliasGroup)
48
52
  app.add_typer(
@@ -105,6 +109,15 @@ app.add_typer(
105
109
 
106
110
  @app.callback()
107
111
  def main(
112
+ cache: Annotated[
113
+ int,
114
+ typer.Option(
115
+ '-c',
116
+ '--cache',
117
+ help='Which degree of caching to use.',
118
+ default_factory=lambda: grading_context.CacheLevel.CACHE_ALL.value,
119
+ ),
120
+ ],
108
121
  sanitized: bool = typer.Option(
109
122
  False,
110
123
  '--sanitized',
@@ -118,12 +131,23 @@ def main(
118
131
  flag_value=False,
119
132
  help='Whether to save extra logs and outputs from interactive solutions.',
120
133
  ),
134
+ profile: bool = typer.Option(
135
+ False,
136
+ '--profile',
137
+ '-p',
138
+ help='Whether to profile the execution.',
139
+ ),
121
140
  ):
122
141
  if cd.is_problem_package() and not package.is_cache_valid():
123
142
  console.console.print(
124
143
  '[warning]Cache is incompatible with the current version of [item]rbx[/item], so it will be cleared.[/warning]'
125
144
  )
126
145
  clear()
146
+ if not global_package.is_global_cache_valid():
147
+ console.console.print(
148
+ '[warning]Global cache is incompatible with the current version of [item]rbx[/item], so it will be cleared.[/warning]'
149
+ )
150
+ clear(global_cache=True)
127
151
 
128
152
  state.STATE.run_through_cli = True
129
153
  state.STATE.sanitized = sanitized
@@ -134,6 +158,13 @@ def main(
134
158
  )
135
159
  state.STATE.debug_logs = capture
136
160
 
161
+ grading_context.cache_level_var.set(grading_context.CacheLevel(cache))
162
+
163
+ if profile:
164
+ from rbx.grading import profiling
165
+
166
+ atexit.register(profiling.print_summary)
167
+
137
168
 
138
169
  @app.command('ui', hidden=True)
139
170
  @package.within_problem
@@ -252,17 +283,17 @@ async def run(
252
283
  )
253
284
  check = False
254
285
 
255
- tracked_solutions = None
286
+ tracked_solutions: Optional[OrderedSet[str]] = None
256
287
  if outcome is not None:
257
- tracked_solutions = {
288
+ tracked_solutions = OrderedSet(
258
289
  str(solution.path)
259
290
  for solution in get_matching_solutions(ExpectedOutcome(outcome))
260
- }
291
+ )
261
292
  if solutions:
262
- tracked_solutions = set(solutions)
293
+ tracked_solutions = OrderedSet(solutions)
263
294
 
264
295
  if choice:
265
- tracked_solutions = set(
296
+ tracked_solutions = OrderedSet(
266
297
  await pick_solutions(
267
298
  tracked_solutions,
268
299
  extra_solutions=solutions,
@@ -307,10 +338,10 @@ async def run(
307
338
  console.console.print(
308
339
  '[warning]Sanitizers are running, and no solutions were specified to run. Will only run [item]ACCEPTED[/item] solutions.'
309
340
  )
310
- tracked_solutions = {
341
+ tracked_solutions = OrderedSet(
311
342
  str(solution.path)
312
343
  for solution in get_exact_matching_solutions(ExpectedOutcome.ACCEPTED)
313
- }
344
+ )
314
345
 
315
346
  with utils.StatusProgress('Running solutions...') as s:
316
347
  solution_result = run_solutions(
@@ -343,10 +374,10 @@ async def _time_impl(check: bool, detailed: bool, runs: int = 0) -> Optional[int
343
374
  verification = VerificationLevel.ALL_SOLUTIONS.value
344
375
 
345
376
  with utils.StatusProgress('Running ACCEPTED solutions...') as s:
346
- tracked_solutions = {
377
+ tracked_solutions = OrderedSet(
347
378
  str(solution.path)
348
379
  for solution in get_exact_matching_solutions(ExpectedOutcome.ACCEPTED)
349
- }
380
+ )
350
381
  solution_result = run_solutions(
351
382
  progress=s,
352
383
  tracked_solutions=tracked_solutions,
@@ -495,17 +526,17 @@ async def irun(
495
526
  )
496
527
  return
497
528
 
498
- tracked_solutions = None
529
+ tracked_solutions: Optional[OrderedSet[str]] = None
499
530
  if outcome is not None:
500
- tracked_solutions = {
531
+ tracked_solutions = OrderedSet(
501
532
  str(solution.path)
502
533
  for solution in get_matching_solutions(ExpectedOutcome(outcome))
503
- }
534
+ )
504
535
  if solutions:
505
- tracked_solutions = set(solutions)
536
+ tracked_solutions = OrderedSet(solutions)
506
537
 
507
538
  if choice:
508
- tracked_solutions = set(
539
+ tracked_solutions = OrderedSet(
509
540
  await pick_solutions(
510
541
  tracked_solutions,
511
542
  extra_solutions=solutions,
@@ -519,10 +550,10 @@ async def irun(
519
550
  console.console.print(
520
551
  '[warning]Sanitizers are running, and no solutions were specified to run. Will only run [item]ACCEPTED[/item] solutions.'
521
552
  )
522
- tracked_solutions = {
553
+ tracked_solutions = OrderedSet(
523
554
  str(solution.path)
524
555
  for solution in get_exact_matching_solutions(ExpectedOutcome.ACCEPTED)
525
- }
556
+ )
526
557
 
527
558
  with utils.StatusProgress('Running solutions...') as s:
528
559
  await run_and_print_interactive_solutions(
@@ -546,7 +577,13 @@ async def irun(
546
577
  help='Create a new problem package.',
547
578
  )
548
579
  def create(
549
- name: str,
580
+ name: Annotated[
581
+ str,
582
+ typer.Option(
583
+ help='Name of the problem to create, which will be used as the name of the new folder.',
584
+ prompt='What should the name of the problem be?',
585
+ ),
586
+ ],
550
587
  preset: Annotated[
551
588
  Optional[str], typer.Option(help='Preset to use when creating the problem.')
552
589
  ] = None,
@@ -631,16 +668,17 @@ async def stress(
631
668
  from rbx.box import stresses
632
669
 
633
670
  with utils.StatusProgress('Running stress...') as s:
634
- report = await stresses.run_stress(
635
- timeout,
636
- name=name,
637
- generator_call=generator_args,
638
- finder=finder,
639
- findingsLimit=findings,
640
- progress=s,
641
- verbose=verbose,
642
- sanitized=sanitized,
643
- )
671
+ with grading_context.cache_level(grading_context.CacheLevel.CACHE_COMPILATION):
672
+ report = await stresses.run_stress(
673
+ timeout,
674
+ name=name,
675
+ generator_call=generator_args,
676
+ finder=finder,
677
+ findingsLimit=findings,
678
+ progress=s,
679
+ verbose=verbose,
680
+ sanitized=sanitized,
681
+ )
644
682
 
645
683
  stresses.print_stress_report(report)
646
684
 
@@ -882,7 +920,7 @@ def languages():
882
920
 
883
921
  for language in env.languages:
884
922
  console.console.print(
885
- f'[item]{language.name}[/item], aka [item]{language.readable_name or language.name}[/item]:'
923
+ f'[item]{language.name}[/item], aka [item]{language.readableName or language.name}[/item]:'
886
924
  )
887
925
  console.console.print(language)
888
926
  console.console.print()
@@ -922,13 +960,29 @@ def fix(print_diff: bool = typer.Option(False, '--print-diff', '-p')):
922
960
  linting.fix_package(print_diff=print_diff)
923
961
 
924
962
 
963
+ @cd.within_closest_package
964
+ def _clear_package_cache():
965
+ console.console.print('Cleaning cache and build directories...')
966
+ shutil.rmtree('.box', ignore_errors=True)
967
+ shutil.rmtree('build', ignore_errors=True)
968
+
969
+
925
970
  @app.command(
926
971
  'clear, clean',
927
972
  rich_help_panel='Management',
928
973
  help='Clears cache and build directories.',
929
974
  )
930
- @cd.within_closest_package
931
- def clear():
932
- console.console.print('Cleaning cache and build directories...')
933
- shutil.rmtree('.box', ignore_errors=True)
934
- shutil.rmtree('build', ignore_errors=True)
975
+ def clear(global_cache: bool = typer.Option(False, '--global', '-g')):
976
+ cleared = False
977
+ if global_cache:
978
+ console.console.print('Cleaning global cache...')
979
+ global_package.clear_global_cache()
980
+ cleared = True
981
+
982
+ closest_package = cd.find_package()
983
+ if closest_package is not None:
984
+ _clear_package_cache()
985
+ cleared = True
986
+
987
+ if not cleared:
988
+ console.console.print('[error]No cache or build directories to clean.[/error]')
@@ -10,9 +10,10 @@ from typing import List, Optional
10
10
  import rich
11
11
  import rich.text
12
12
  import typer
13
+ from pydantic import BaseModel
13
14
 
14
- from rbx import console
15
- from rbx.box import download, package, setter_config, state
15
+ from rbx import console, utils
16
+ from rbx.box import download, global_package, package, setter_config, state
16
17
  from rbx.box.environment import (
17
18
  CompilationConfig,
18
19
  ExecutionConfig,
@@ -27,10 +28,11 @@ from rbx.box.environment import (
27
28
  merge_execution_configs,
28
29
  )
29
30
  from rbx.box.formatting import get_formatted_memory
31
+ from rbx.box.remote import is_path_remote
30
32
  from rbx.box.sanitizers import warning_stack
31
33
  from rbx.box.schema import CodeItem
32
- from rbx.grading import steps, steps_with_caching
33
- from rbx.grading.judge.sandbox import SandboxBase, SandboxParams
34
+ from rbx.grading import grading_context, profiling, steps, steps_with_caching
35
+ from rbx.grading.judge.sandbox import SandboxParams
34
36
  from rbx.grading.steps import (
35
37
  DigestHolder,
36
38
  DigestOrDest,
@@ -59,6 +61,10 @@ class SanitizationLevel(Enum):
59
61
  return self.value >= SanitizationLevel.FORCE.value
60
62
 
61
63
 
64
+ class CompilationMetadata(BaseModel):
65
+ is_sanitized: bool
66
+
67
+
62
68
  def substitute_commands(commands: List[str], sanitized: bool = False) -> List[str]:
63
69
  cfg = setter_config.get_setter_config()
64
70
  return [cfg.substitute_command(command, sanitized) for command in commands]
@@ -78,8 +84,15 @@ def find_language_name(code: CodeItem) -> str:
78
84
  def is_executable_sanitized(executable: DigestOrSource) -> bool:
79
85
  if executable.digest is None:
80
86
  return False
81
- storage = package.get_cache_storage()
82
- return storage.exists(f'{executable.digest.value}.san')
87
+ if executable.digest.value is None:
88
+ return False
89
+ cacher = package.get_file_cacher()
90
+ desc = cacher.get_metadata(
91
+ executable.digest.value, 'compilation', CompilationMetadata
92
+ )
93
+ if desc is None:
94
+ return False
95
+ return desc.is_sanitized
83
96
 
84
97
 
85
98
  def add_sanitizer_flags_to_command(command: str) -> str:
@@ -283,7 +296,7 @@ def _prepare_for_communication(
283
296
  )
284
297
 
285
298
  if capture.merged_capture is not None:
286
- merged_output_path = package.get_merged_capture_path().resolve()
299
+ merged_output_path = utils.abspath(package.get_merged_capture_path())
287
300
  run.sandbox_params.timeit_dups['Do'].append(merged_output_path)
288
301
 
289
302
  run.artifacts.outputs.append(
@@ -402,7 +415,6 @@ def _should_precompile(commands: List[str]) -> bool:
402
415
  def _precompile_header(
403
416
  compilation_options: CompilationConfig,
404
417
  sanitized: SanitizationLevel,
405
- sandbox: SandboxBase,
406
418
  sandbox_params: SandboxParams,
407
419
  artifacts: GradingArtifacts,
408
420
  input_artifact: GradingFileInput,
@@ -417,7 +429,8 @@ def _precompile_header(
417
429
  """
418
430
  assert compilation_options.commands is not None
419
431
 
420
- dependency_cache = package.get_dependency_cache()
432
+ sandbox = global_package.get_global_sandbox()
433
+ dependency_cache = global_package.get_global_dependency_cache()
421
434
 
422
435
  # TODO: deduplicate code with compile_item.
423
436
  commands = get_mapped_commands(
@@ -455,41 +468,60 @@ def _precompile_header(
455
468
  GradingFileOutput(
456
469
  src=PosixPath('precompilable.h.gch'),
457
470
  digest=precompiled_digest,
458
- executable=True,
459
471
  )
460
472
  )
461
473
 
462
- if not steps_with_caching.compile(
463
- commands,
464
- params=sandbox_params,
465
- artifacts=precompilation_artifacts,
466
- sandbox=sandbox,
467
- dependency_cache=dependency_cache,
468
- ):
469
- console.console.print(
470
- f'[error]Failed to precompile header file: [item]{input_artifact.src}[/item][/error]'
471
- )
472
- raise typer.Exit(1)
474
+ with profiling.PushContext('code.precompile_header'):
475
+ if not steps_with_caching.compile(
476
+ commands,
477
+ params=sandbox_params,
478
+ artifacts=precompilation_artifacts,
479
+ sandbox=sandbox,
480
+ dependency_cache=dependency_cache,
481
+ ):
482
+ console.console.print(
483
+ f'[error]Failed to precompile header file: [item]{input_artifact.src}[/item][/error]'
484
+ )
485
+ raise typer.Exit(1)
473
486
 
474
- if verbose:
475
- console.console.print(
476
- f'[status]Precompiled header file: [item]{input_artifact.src}[/item]'
477
- )
487
+ if verbose:
488
+ console.console.print(
489
+ f'[status]Precompiled header file: [item]{input_artifact.src}[/item]'
490
+ )
478
491
 
479
- if (
480
- precompilation_artifacts.logs is not None
481
- and precompilation_artifacts.logs.preprocess is not None
482
- ):
483
- for log in precompilation_artifacts.logs.preprocess:
484
- console.console.print(f'[status]Command:[/status] {log.get_command()}')
485
- console.console.print(f'[status]Summary:[/status] {log.get_summary()}')
492
+ if (
493
+ precompilation_artifacts.logs is not None
494
+ and precompilation_artifacts.logs.preprocess is not None
495
+ ):
496
+ for log in precompilation_artifacts.logs.preprocess:
497
+ console.console.print(
498
+ f'[status]Command:[/status] {log.get_command()}'
499
+ )
500
+ console.console.print(
501
+ f'[status]Summary:[/status] {log.get_summary()}'
502
+ )
486
503
 
487
504
  assert precompiled_digest.value is not None
488
505
 
506
+ digest_path = dependency_cache.cacher.path_for_symlink(precompiled_digest.value)
507
+ if digest_path is not None and digest_path.is_file():
508
+ # If storage backend supports symlinks, use it as the grading input.
509
+ input = DigestOrSource.create(digest_path)
510
+ else:
511
+ # Otherwise, copy the file to the local cache, transiently.
512
+ local_cacher = package.get_file_cacher()
513
+ with dependency_cache.cacher.get_file(precompiled_digest.value) as f:
514
+ with grading_context.cache_level(
515
+ grading_context.CacheLevel.CACHE_TRANSIENTLY
516
+ ):
517
+ input = DigestOrSource.create(local_cacher.put_file_from_fobj(f))
518
+
489
519
  return GradingFileInput(
490
- digest=precompiled_digest,
520
+ **input.expand(),
491
521
  dest=input_artifact.dest.with_suffix('.h.gch'),
492
- executable=True,
522
+ # Do not track fingerprint of the precompiled header file,
523
+ # trust the compilation step above.
524
+ hash=False,
493
525
  )
494
526
 
495
527
 
@@ -576,37 +608,43 @@ def compile_item(
576
608
 
577
609
  # Precompile C++ interesting header files.
578
610
  if precompile and _should_precompile(commands):
579
- precompilation_inputs = []
580
- for input in artifacts.inputs:
581
- if (
582
- input.src is not None
583
- and input.src.suffix == '.h'
584
- and input.dest.name in ['stdc++.h', 'jngen.h', 'testlib.h']
585
- ):
586
- precompilation_inputs.append(
587
- _precompile_header(
588
- compilation_options,
589
- sanitized,
590
- sandbox,
591
- sandbox_params,
592
- artifacts,
593
- input,
594
- force_warnings,
595
- verbose=False,
611
+ with profiling.Profiler('code.precompile'):
612
+ precompilation_inputs = []
613
+ for input in artifacts.inputs:
614
+ if (
615
+ input.src is not None
616
+ and input.src.suffix == '.h'
617
+ and input.dest.name in ['stdc++.h', 'jngen.h', 'testlib.h']
618
+ ):
619
+ precompilation_inputs.append(
620
+ _precompile_header(
621
+ compilation_options,
622
+ sanitized,
623
+ sandbox_params,
624
+ artifacts,
625
+ input,
626
+ force_warnings,
627
+ verbose=False,
628
+ )
596
629
  )
597
- )
598
- if precompilation_inputs:
599
- artifacts.inputs.extend(precompilation_inputs)
600
-
601
- # Compile the code.
602
- if not steps_with_caching.compile(
603
- commands,
604
- params=sandbox_params,
605
- artifacts=artifacts,
606
- sandbox=sandbox,
607
- dependency_cache=dependency_cache,
608
- ):
609
- raise typer.Exit(1)
630
+ if precompilation_inputs:
631
+ artifacts.inputs.extend(precompilation_inputs)
632
+
633
+ with profiling.Profiler('code.compile'):
634
+ # Compile the code.
635
+ # Do not cache remote solutions.
636
+ with grading_context.cache_level(
637
+ grading_context.CacheLevel.NO_CACHE,
638
+ when=lambda: is_path_remote(code.path),
639
+ ):
640
+ if not steps_with_caching.compile(
641
+ commands,
642
+ params=sandbox_params,
643
+ artifacts=artifacts,
644
+ sandbox=sandbox,
645
+ dependency_cache=dependency_cache,
646
+ ):
647
+ raise typer.Exit(1)
610
648
 
611
649
  assert compiled_digest.value is not None
612
650
 
@@ -629,13 +667,13 @@ def compile_item(
629
667
  warning_stack.get_warning_stack().add_warning(code)
630
668
 
631
669
  # Create sentinel to indicate this executable is sanitized.
632
- storage = package.get_cache_storage()
670
+ cacher = package.get_file_cacher()
633
671
  if sanitized.should_sanitize():
634
- pf = storage.create_file(f'{compiled_digest.value}.san')
635
- if pf is not None:
636
- storage.commit_file(pf)
637
- elif storage.exists(f'{compiled_digest.value}.san'):
638
- storage.delete(f'{compiled_digest.value}.san')
672
+ cacher.set_metadata(
673
+ compiled_digest.value, 'compilation', CompilationMetadata(is_sanitized=True)
674
+ )
675
+ else:
676
+ cacher.set_metadata(compiled_digest.value, 'compilation', None)
639
677
 
640
678
  return compiled_digest.value
641
679
 
@@ -669,14 +707,20 @@ async def run_item(
669
707
  retry_index,
670
708
  )
671
709
 
672
- run_log = await steps_with_caching.run(
673
- prepared.command,
674
- params=prepared.sandbox_params,
675
- sandbox=package.get_singleton_sandbox(),
676
- artifacts=prepared.artifacts,
677
- dependency_cache=dependency_cache,
678
- metadata=prepared.metadata,
679
- )
710
+ with profiling.PushContext('code.run_item'):
711
+ # Do not cache remote solutions.
712
+ with grading_context.cache_level(
713
+ grading_context.CacheLevel.NO_CACHE,
714
+ when=lambda: is_path_remote(code.path),
715
+ ):
716
+ run_log = await steps_with_caching.run(
717
+ prepared.command,
718
+ params=prepared.sandbox_params,
719
+ sandbox=package.get_singleton_sandbox(),
720
+ artifacts=prepared.artifacts,
721
+ dependency_cache=dependency_cache,
722
+ metadata=prepared.metadata,
723
+ )
680
724
 
681
725
  # Find sanitizer logs.
682
726
  if run_log is not None and run_log.warnings:
@@ -686,7 +730,7 @@ async def run_item(
686
730
  )
687
731
  if stderr_output is not None:
688
732
  warning_stack.get_warning_stack().add_sanitizer_warning(
689
- package.get_cache_storage(), code, stderr_output
733
+ package.get_file_cacher(), code, stderr_output
690
734
  )
691
735
  return run_log
692
736
 
@@ -773,8 +817,13 @@ async def run_communication(
773
817
  metadata=solution_prepared.metadata,
774
818
  )
775
819
 
776
- return await steps_with_caching.run_coordinated(
777
- interactor_run_params,
778
- solution_run_params,
779
- dependency_cache=package.get_dependency_cache(),
780
- )
820
+ # Do not cache remote solutions.
821
+ with grading_context.cache_level(
822
+ grading_context.CacheLevel.NO_CACHE,
823
+ when=lambda: is_path_remote(solution.code.path),
824
+ ):
825
+ return await steps_with_caching.run_coordinated(
826
+ interactor_run_params,
827
+ solution_run_params,
828
+ dependency_cache=package.get_dependency_cache(),
829
+ )
@@ -6,7 +6,7 @@ from typing import Any, Dict, List, Optional, Tuple
6
6
 
7
7
  import typer
8
8
 
9
- from rbx import console, testing_utils
9
+ from rbx import console, testing_utils, utils
10
10
  from rbx.box import cd, package
11
11
  from rbx.box.contest.contest_package import get_problems
12
12
  from rbx.box.contest.schema import Contest, ContestProblem, ContestStatement
@@ -156,7 +156,7 @@ def _build_problem_statements(
156
156
  console.console.print('Building problem-level statements...')
157
157
  extracted_problems = get_problems_for_statement(contest, statement)
158
158
  res = []
159
- contest_cwd_absolute = pathlib.Path().resolve()
159
+ contest_cwd_absolute = utils.abspath(pathlib.Path())
160
160
  contest_assets = get_relative_assets(statement.path, statement.assets)
161
161
 
162
162
  extra_vars = dict(statement.override.vars if statement.override is not None else {})
@@ -17,7 +17,7 @@ YAML_NAME = 'contest.rbx.yml'
17
17
 
18
18
  @functools.cache
19
19
  def find_contest_yaml(root: pathlib.Path = pathlib.Path()) -> Optional[pathlib.Path]:
20
- root = root.resolve()
20
+ root = utils.abspath(root)
21
21
  contest_yaml_path = root / YAML_NAME
22
22
  while root != pathlib.PosixPath('/') and not contest_yaml_path.is_file():
23
23
  root = root.parent