rbx.cp 0.6.0__tar.gz → 0.7.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 (244) hide show
  1. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/PKG-INFO +23 -6
  2. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/README.md +19 -3
  3. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/pyproject.toml +13 -2
  4. rbx_cp-0.7.0/rbx/box/cd.py +98 -0
  5. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/checkers.py +9 -1
  6. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/cli.py +49 -45
  7. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/code.py +9 -7
  8. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/contest/contest_package.py +4 -7
  9. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/contest/main.py +32 -58
  10. rbx_cp-0.7.0/rbx/box/creation.py +48 -0
  11. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/environment.py +21 -9
  12. rbx_cp-0.7.0/rbx/box/linting.py +95 -0
  13. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/package.py +3 -34
  14. rbx_cp-0.7.0/rbx/box/presets/__init__.py +718 -0
  15. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/presets/lock_schema.py +1 -2
  16. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/presets/schema.py +13 -5
  17. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/retries.py +8 -0
  18. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/schema.py +15 -2
  19. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/solutions.py +71 -14
  20. rbx_cp-0.7.0/rbx/box/stats.py +92 -0
  21. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/tasks.py +6 -3
  22. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/utils/run_ui.py +1 -1
  23. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/sandbox.py +22 -10
  24. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/steps.py +1 -0
  25. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/contest/contest.rbx.yml +4 -3
  26. rbx_cp-0.7.0/rbx/resources/presets/default/preset.rbx.yml +14 -0
  27. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/problem.rbx.yml +20 -10
  28. rbx_cp-0.7.0/rbx/resources/presets/default/problem/random.txt +4 -0
  29. rbx_cp-0.7.0/rbx/resources/presets/default/problem/rbx.h +92 -0
  30. rbx_cp-0.7.0/rbx/resources/presets/default/problem/statement/statement.rbx.tex +15 -0
  31. rbx_cp-0.7.0/rbx/resources/presets/default/problem/validator.cpp +16 -0
  32. rbx_cp-0.6.0/rbx/box/cd.py +0 -60
  33. rbx_cp-0.6.0/rbx/box/creation.py +0 -78
  34. rbx_cp-0.6.0/rbx/box/presets/__init__.py +0 -637
  35. rbx_cp-0.6.0/rbx/resources/presets/default/preset.rbx.yml +0 -12
  36. rbx_cp-0.6.0/rbx/resources/presets/default/problem/random.txt +0 -2
  37. rbx_cp-0.6.0/rbx/resources/presets/default/problem/statement/projecao.png +0 -0
  38. rbx_cp-0.6.0/rbx/resources/presets/default/problem/statement/statement.rbx.tex +0 -18
  39. rbx_cp-0.6.0/rbx/resources/presets/default/problem/validator.cpp +0 -16
  40. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/LICENSE +0 -0
  41. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/__init__.py +0 -0
  42. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/annotations.py +0 -0
  43. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/autoenum.py +0 -0
  44. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/__init__.py +0 -0
  45. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/builder.py +0 -0
  46. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/compile.py +0 -0
  47. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/conftest.py +0 -0
  48. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/contest/__init__.py +0 -0
  49. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/contest/build_contest_statements.py +0 -0
  50. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/contest/contest_utils.py +0 -0
  51. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/contest/schema.py +0 -0
  52. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/contest/statements.py +0 -0
  53. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/deferred.py +0 -0
  54. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/download.py +0 -0
  55. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/dump_schemas.py +0 -0
  56. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/extensions.py +0 -0
  57. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/fields.py +0 -0
  58. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/formatting.py +0 -0
  59. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/generators.py +0 -0
  60. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/generators_test.py +0 -0
  61. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/git_utils.py +0 -0
  62. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/header.py +0 -0
  63. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/lang.py +0 -0
  64. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/lazy_importing_main.py +0 -0
  65. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/lazy_importing_test.py +0 -0
  66. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/main.py +0 -0
  67. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/naming.py +0 -0
  68. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/boca/extension.py +0 -0
  69. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/boca/packager.py +0 -0
  70. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/contest_main.py +0 -0
  71. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/main.py +0 -0
  72. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/moj/packager.py +0 -0
  73. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/packager.py +0 -0
  74. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/pkg/packager.py +0 -0
  75. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/polygon/packager.py +0 -0
  76. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/polygon/polygon_api.py +0 -0
  77. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/polygon/test.py +0 -0
  78. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/polygon/upload.py +0 -0
  79. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/polygon/xml_schema.py +0 -0
  80. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/presets/fetch.py +0 -0
  81. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/remote.py +0 -0
  82. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/sanitizers/warning_stack.py +0 -0
  83. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/setter_config.py +0 -0
  84. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/solutions_test.py +0 -0
  85. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/state.py +0 -0
  86. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/__init__.py +0 -0
  87. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/build_statements.py +0 -0
  88. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/builders.py +0 -0
  89. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/expander.py +0 -0
  90. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/joiners.py +0 -0
  91. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/latex.py +0 -0
  92. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/latex_jinja.py +0 -0
  93. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/schema.py +0 -0
  94. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/stresses.py +0 -0
  95. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/stressing/__init__.py +0 -0
  96. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/stressing/finder_parser.py +0 -0
  97. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/stressing/generator_parser.py +0 -0
  98. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/testcase_extractors.py +0 -0
  99. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/testcase_utils.py +0 -0
  100. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/testcases/__init__.py +0 -0
  101. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/testcases/main.py +0 -0
  102. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/tooling/__init__.py +0 -0
  103. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/tooling/boca/__init__.py +0 -0
  104. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/tooling/boca/main.py +0 -0
  105. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/tooling/boca/scrape.py +0 -0
  106. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/tooling/boca/scraper.py +0 -0
  107. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/tooling/main.py +0 -0
  108. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/__init__.py +0 -0
  109. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/captured_log.py +0 -0
  110. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/css/app.tcss +0 -0
  111. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/main.py +0 -0
  112. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/__init__.py +0 -0
  113. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/build.py +0 -0
  114. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/command.py +0 -0
  115. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/differ.py +0 -0
  116. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/error.py +0 -0
  117. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/rich_log_modal.py +0 -0
  118. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/run.py +0 -0
  119. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/run_explorer.py +0 -0
  120. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/run_test_explorer.py +0 -0
  121. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/selector.py +0 -0
  122. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/test_explorer.py +0 -0
  123. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/utils/__init__.py +0 -0
  124. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/widgets/__init__.py +0 -0
  125. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/widgets/diff_box.py +0 -0
  126. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/widgets/file_log.py +0 -0
  127. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/widgets/interaction_box.py +0 -0
  128. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/widgets/rich_log_box.py +0 -0
  129. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/widgets/test_output_box.py +0 -0
  130. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/widgets/two_sided_test_output_box.py +0 -0
  131. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/unit.py +0 -0
  132. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/validators.py +0 -0
  133. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/validators_test.py +0 -0
  134. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/checker.py +0 -0
  135. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/clone.py +0 -0
  136. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/config.py +0 -0
  137. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/conftest.py +0 -0
  138. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/console.py +0 -0
  139. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/create.py +0 -0
  140. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/edit.py +0 -0
  141. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/__init__.py +0 -0
  142. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/caching.py +0 -0
  143. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/conftest.py +0 -0
  144. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/__init__.py +0 -0
  145. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/cacher.py +0 -0
  146. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/digester.py +0 -0
  147. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/sandboxes/__init__.py +0 -0
  148. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/sandboxes/isolate.py +0 -0
  149. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/sandboxes/stupid_sandbox.py +0 -0
  150. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/sandboxes/timeit.py +0 -0
  151. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/storage.py +0 -0
  152. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/test.py +0 -0
  153. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/testiso.py +0 -0
  154. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/limits.py +0 -0
  155. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/processing_context.py +0 -0
  156. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/steps_with_caching.py +0 -0
  157. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/steps_with_caching_run_test.py +0 -0
  158. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading_utils.py +0 -0
  159. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/hydration.py +0 -0
  160. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/main.py +0 -0
  161. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/metadata.py +0 -0
  162. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/providers/__init__.py +0 -0
  163. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/providers/codeforces.py +0 -0
  164. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/providers/provider.py +0 -0
  165. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/checkers/boilerplate.cpp +0 -0
  166. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/checkers/noop.cpp +0 -0
  167. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/default_config.json +0 -0
  168. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/default_setter_config.mac.yml +0 -0
  169. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/default_setter_config.yml +0 -0
  170. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/envs/default.rbx.yml +0 -0
  171. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/envs/isolate.rbx.yml +0 -0
  172. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/checker.sh +0 -0
  173. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compare.sh +0 -0
  174. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compile/c +0 -0
  175. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compile/cc +0 -0
  176. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compile/cpp +0 -0
  177. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compile/java +0 -0
  178. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compile/kt +0 -0
  179. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compile/py2 +0 -0
  180. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compile/py3 +0 -0
  181. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactive/c +0 -0
  182. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactive/cc +0 -0
  183. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactive/cpp +0 -0
  184. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactive/java +0 -0
  185. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactive/kt +0 -0
  186. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactive/py2 +0 -0
  187. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactive/py3 +0 -0
  188. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactor_compile.sh +0 -0
  189. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactor_run.sh +0 -0
  190. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/bkp +0 -0
  191. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/c +0 -0
  192. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/cc +0 -0
  193. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/cpp +0 -0
  194. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/java +0 -0
  195. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/kt +0 -0
  196. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/py2 +0 -0
  197. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/py3 +0 -0
  198. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/safeexec.c +0 -0
  199. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/safeexec_compile.sh +0 -0
  200. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/c/compile.sh +0 -0
  201. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/c/prep.sh +0 -0
  202. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/c/run.sh +0 -0
  203. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/compare.sh +0 -0
  204. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/cpp/compile.sh +0 -0
  205. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/cpp/prep.sh +0 -0
  206. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/cpp/run.sh +0 -0
  207. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/interactor_prep.sh +0 -0
  208. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/interactor_run.sh +0 -0
  209. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/java/compile.sh +0 -0
  210. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/java/prep.sh +0 -0
  211. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/java/run.sh +0 -0
  212. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/py2/compile.sh +0 -0
  213. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/py2/prep.sh +0 -0
  214. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/py2/run.sh +0 -0
  215. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/py3/compile.sh +0 -0
  216. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/py3/prep.sh +0 -0
  217. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/py3/run.sh +0 -0
  218. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/contest/statement/contest.rbx.tex +0 -0
  219. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/contest/statement/olymp.sty +0 -0
  220. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/contest/statement/template.rbx.tex +0 -0
  221. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/.gitignore +0 -0
  222. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/gen.cpp +0 -0
  223. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/random.py +0 -0
  224. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/sols/main.cpp +0 -0
  225. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/sols/slow.cpp +0 -0
  226. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/sols/wa.cpp +0 -0
  227. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/statement/olymp.sty +0 -0
  228. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/statement/template.rbx.tex +0 -0
  229. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/tests/samples/000.in +0 -0
  230. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/tests/samples/001.in +0 -0
  231. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/wcmp.cpp +0 -0
  232. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/templates/rbx.h +0 -0
  233. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/templates/template.cpp +0 -0
  234. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/run.py +0 -0
  235. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/schema.py +0 -0
  236. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/submit.py +0 -0
  237. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/submitors/__init__.py +0 -0
  238. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/submitors/codeforces.py +0 -0
  239. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/submitors/submitor.py +0 -0
  240. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/test.py +0 -0
  241. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/testcase.py +0 -0
  242. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/testcase_rendering.py +0 -0
  243. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/testing_utils.py +0 -0
  244. {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/utils.py +0 -0
@@ -1,11 +1,10 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rbx.cp
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary:
5
5
  Author: Roberto Sales
6
- Requires-Python: >=3.9,<4.0
6
+ Requires-Python: >=3.9.1,<4.0.0
7
7
  Classifier: Programming Language :: Python :: 3
8
- Classifier: Programming Language :: Python :: 3.9
9
8
  Classifier: Programming Language :: Python :: 3.10
10
9
  Classifier: Programming Language :: Python :: 3.11
11
10
  Classifier: Programming Language :: Python :: 3.12
@@ -35,15 +34,21 @@ Requires-Dist: pyyaml (>=6.0.1,<7.0.0)
35
34
  Requires-Dist: questionary (>=2.1.0,<3.0.0)
36
35
  Requires-Dist: requests (>=2.32.3,<3.0.0)
37
36
  Requires-Dist: rich (>=13.9.4,<14.0.0)
37
+ Requires-Dist: ruamel-yaml (>=0.18.14,<0.19.0)
38
38
  Requires-Dist: ruyaml (>=0.91.0,<0.92.0)
39
39
  Requires-Dist: syncer (>=2.0.3,<3.0.0)
40
40
  Requires-Dist: textual (>=3.1.1,<4.0.0)
41
41
  Requires-Dist: textual-serve (>=1.1.2,<2.0.0)
42
42
  Requires-Dist: typer (>=0.15.1,<0.16.0)
43
+ Requires-Dist: yamlfix (>=1.17.0,<2.0.0)
43
44
  Description-Content-Type: text/markdown
44
45
 
45
46
  <p align="center">
46
- <em>The go-to CLI tool for competitive programmers and setters.</em>
47
+ <img src="docs/rbx_white.png" alt="rbx" width="200">
48
+ </p>
49
+
50
+ <p align="center">
51
+ <em>The go-to CLI tool for programming competitions setters.</em>
47
52
  </p>
48
53
  <p align="center">
49
54
  <!-- loscal repository, no metadata badges. -->
@@ -60,6 +65,7 @@ Description-Content-Type: text/markdown
60
65
  <summary>Table of Contents</summary><br>
61
66
 
62
67
  - [Overview](#overview)
68
+ - [Features](#features)
63
69
  - [Documentation](#documentation)
64
70
  - [License](#license)
65
71
  </details>
@@ -73,9 +79,20 @@ Description-Content-Type: text/markdown
73
79
  [![PyPI pyversions](https://img.shields.io/pypi/pyversions/rbx.svg)](https://pypi.python.org/pypi/rbx/)
74
80
  [![PyPI version shields.io](https://img.shields.io/pypi/v/rbx.svg)](https://pypi.python.org/pypi/rbx/)
75
81
 
76
- rbx is a CLI tool and library that aims to help contestants and setters from the competitive programming community to have an easier time.
82
+ **rbx** is a CLI tool that empowers setters from the competitive programming community.
83
+
84
+ A flexible setting tool, as powerful as [Polygon](https://polygon.codeforces.com/), right on your terminal.
85
+
86
+ ---
87
+
88
+ ## Features
77
89
 
78
- Although trying to solve the issues of these two audiences seems to be too much for a single tool to handle, we exploit the fact that the journeys of contestants and setters have a lot in common.
90
+ - 🧱 Structure: describe your problem or contest structure with the use of YAML configuration files.
91
+ - 🤖 Generation: provides a simple way to describe your whole testset, including both manually added and generated testcases.
92
+ - 🔨 Testing: provides commands for automatically running correct and incorrect solutions against the testcases of your problem, automatically judging whether the verdict was as expected or not.
93
+ - ✅ Verify: checks if your testcases and solutions are strictly conformant with the use of validators and unit tests.
94
+ - 📝 Statements: provides tooling for writing and building statements, also ensuring they're easily synchronized with your testset.
95
+ - 📤 Package: provides a single command for packaging your problems for use in your preferred judge system.
79
96
 
80
97
  ---
81
98
 
@@ -1,5 +1,9 @@
1
1
  <p align="center">
2
- <em>The go-to CLI tool for competitive programmers and setters.</em>
2
+ <img src="docs/rbx_white.png" alt="rbx" width="200">
3
+ </p>
4
+
5
+ <p align="center">
6
+ <em>The go-to CLI tool for programming competitions setters.</em>
3
7
  </p>
4
8
  <p align="center">
5
9
  <!-- loscal repository, no metadata badges. -->
@@ -16,6 +20,7 @@
16
20
  <summary>Table of Contents</summary><br>
17
21
 
18
22
  - [Overview](#overview)
23
+ - [Features](#features)
19
24
  - [Documentation](#documentation)
20
25
  - [License](#license)
21
26
  </details>
@@ -29,9 +34,20 @@
29
34
  [![PyPI pyversions](https://img.shields.io/pypi/pyversions/rbx.svg)](https://pypi.python.org/pypi/rbx/)
30
35
  [![PyPI version shields.io](https://img.shields.io/pypi/v/rbx.svg)](https://pypi.python.org/pypi/rbx/)
31
36
 
32
- rbx is a CLI tool and library that aims to help contestants and setters from the competitive programming community to have an easier time.
37
+ **rbx** is a CLI tool that empowers setters from the competitive programming community.
38
+
39
+ A flexible setting tool, as powerful as [Polygon](https://polygon.codeforces.com/), right on your terminal.
40
+
41
+ ---
42
+
43
+ ## Features
33
44
 
34
- Although trying to solve the issues of these two audiences seems to be too much for a single tool to handle, we exploit the fact that the journeys of contestants and setters have a lot in common.
45
+ - 🧱 Structure: describe your problem or contest structure with the use of YAML configuration files.
46
+ - 🤖 Generation: provides a simple way to describe your whole testset, including both manually added and generated testcases.
47
+ - 🔨 Testing: provides commands for automatically running correct and incorrect solutions against the testcases of your problem, automatically judging whether the verdict was as expected or not.
48
+ - ✅ Verify: checks if your testcases and solutions are strictly conformant with the use of validators and unit tests.
49
+ - 📝 Statements: provides tooling for writing and building statements, also ensuring they're easily synchronized with your testset.
50
+ - 📤 Package: provides a single command for packaging your problems for use in your preferred judge system.
35
51
 
36
52
  ---
37
53
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "rbx.cp"
3
- version = "0.6.0"
3
+ version = "0.7.0"
4
4
  description = ""
5
5
  packages = [
6
6
  {include = "rbx"}
@@ -12,7 +12,7 @@ exclude = [
12
12
  ]
13
13
 
14
14
  [tool.poetry.dependencies]
15
- python = "^3.9"
15
+ python = "^3.9.1"
16
16
  typer = "^0.15.1"
17
17
  fastapi = "^0.115.8"
18
18
  filelock = "^3.14.0"
@@ -43,6 +43,8 @@ colour = "^0.1.5"
43
43
  beautifulsoup4 = "^4.13.4"
44
44
  dateparser = "^1.2.1"
45
45
  deepmerge = "^2.0"
46
+ yamlfix = "^1.17.0"
47
+ ruamel-yaml = "^0.18.14"
46
48
 
47
49
  [tool.poetry.scripts]
48
50
  rbc = "rbx.main:app"
@@ -63,7 +65,16 @@ pytest-cov = "^5.0.0"
63
65
  textual-dev = "^1.6.1"
64
66
  pytest-asyncio = "^0.26.0"
65
67
  mkdocs-gen-files = "^0.5.0"
68
+ markdown-grid-tables = "^0.5.0"
66
69
 
70
+
71
+ [tool.commitizen]
72
+ name = "cz_conventional_commits"
73
+ tag_format = "$version"
74
+ version_scheme = "pep440"
75
+ version_provider = "poetry"
76
+ update_changelog_on_bump = true
77
+ major_version_zero = true
67
78
  [build-system]
68
79
  requires = ["poetry-core"]
69
80
  build-backend = "poetry.core.masonry.api"
@@ -0,0 +1,98 @@
1
+ import contextlib
2
+ import functools
3
+ import pathlib
4
+ from typing import List, Optional
5
+
6
+ import typer
7
+
8
+ from rbx import console
9
+ from rbx.box.sanitizers import warning_stack
10
+ from rbx.utils import new_cd
11
+
12
+
13
+ def find_package(
14
+ root: pathlib.Path = pathlib.Path(), consider_presets: bool = False
15
+ ) -> Optional[pathlib.Path]:
16
+ root = root.resolve()
17
+
18
+ def has_file():
19
+ problem_yaml_path = root / 'problem.rbx.yml'
20
+ contest_yaml_path = root / 'contest.rbx.yml'
21
+ preset_yaml_path = root / 'preset.rbx.yml'
22
+ return (
23
+ problem_yaml_path.is_file()
24
+ or contest_yaml_path.is_file()
25
+ or (consider_presets and preset_yaml_path.is_file())
26
+ )
27
+
28
+ while root != pathlib.PosixPath('/') and not has_file():
29
+ root = root.parent
30
+ if not has_file():
31
+ return None
32
+ return root
33
+
34
+
35
+ def find_all_ancestor_packages(
36
+ root: pathlib.Path = pathlib.Path(),
37
+ ) -> List[pathlib.Path]:
38
+ packages = []
39
+ while (pkg := find_package(root)) is not None:
40
+ packages.append(pkg)
41
+ root = pkg.parent
42
+ return packages
43
+
44
+
45
+ def is_problem_package(root: pathlib.Path = pathlib.Path()) -> bool:
46
+ dir = find_package(root)
47
+ if dir is None:
48
+ return False
49
+ return (dir / 'problem.rbx.yml').is_file()
50
+
51
+
52
+ def is_contest_package(root: pathlib.Path = pathlib.Path()) -> bool:
53
+ dir = find_package(root)
54
+ if dir is None:
55
+ return False
56
+ return (dir / 'contest.rbx.yml').is_file()
57
+
58
+
59
+ def is_preset_package(root: pathlib.Path = pathlib.Path()) -> bool:
60
+ dir = find_package(root, consider_presets=True)
61
+ if dir is None:
62
+ return False
63
+ return (dir / 'preset.rbx.yml').is_file()
64
+
65
+
66
+ def within_closest_package(func, consider_presets: bool = False):
67
+ @functools.wraps(func)
68
+ def wrapper(*args, **kwargs):
69
+ package = find_package(consider_presets=consider_presets)
70
+ if package is None:
71
+ console.console.print('[error]No rbx package found.[/error]')
72
+ raise typer.Exit(1)
73
+ # Get deepest package.
74
+ with new_package_cd(package):
75
+ return func(*args, **kwargs)
76
+
77
+ return wrapper
78
+
79
+
80
+ def within_closest_wrapper(func):
81
+ @functools.wraps(func)
82
+ def wrapper(*args, **kwargs):
83
+ package = find_package(consider_presets=True)
84
+ if package is None:
85
+ console.console.print('[error]No rbx package found.[/error]')
86
+ raise typer.Exit(1)
87
+ # Get deepest package.
88
+ with new_package_cd(package):
89
+ return func(*args, **kwargs)
90
+
91
+ return wrapper
92
+
93
+
94
+ @contextlib.contextmanager
95
+ def new_package_cd(x: pathlib.Path):
96
+ with new_cd(x):
97
+ yield
98
+ warning_stack.print_warning_stack_report()
@@ -141,9 +141,16 @@ def _is_checker_exitcode(exitcode: int) -> bool:
141
141
  return exitcode in [0, 1, 2, 3]
142
142
 
143
143
 
144
+ def _get_last_line(message: str) -> str:
145
+ if not message:
146
+ return ''
147
+ return message.strip().split('\n')[-1]
148
+
149
+
144
150
  def process_checker_run_log(
145
151
  checker_run_log: Optional[RunLog], message: str
146
152
  ) -> CheckerResult:
153
+ message = _get_last_line(message)
147
154
  if (
148
155
  checker_run_log is not None
149
156
  and checker_run_log.exitstatus == SandboxBase.EXIT_SANDBOX_ERROR
@@ -352,7 +359,8 @@ async def check_communication(
352
359
  return _extra_check_and_sanitize(result)
353
360
 
354
361
  # Just a defensive pattern to ensure result is not None, should never happen.
355
- result = check_with_no_output(interactor_run_log)
362
+ if result is None:
363
+ result = check_with_no_output(interactor_run_log)
356
364
  if result.outcome != Outcome.ACCEPTED:
357
365
  if result.outcome == Outcome.RUNTIME_ERROR:
358
366
  result.outcome = Outcome.JUDGE_FAILED
@@ -26,7 +26,7 @@ from rbx.box import (
26
26
  )
27
27
  from rbx.box.contest import main as contest
28
28
  from rbx.box.contest.contest_package import find_contest_yaml
29
- from rbx.box.environment import VerificationLevel, get_environment_path
29
+ from rbx.box.environment import VerificationLevel, get_app_environment_path
30
30
  from rbx.box.header import generate_header
31
31
  from rbx.box.packaging import main as packaging
32
32
  from rbx.box.schema import CodeItem, ExpectedOutcome, TestcaseGroup
@@ -333,7 +333,7 @@ async def run(
333
333
  )
334
334
 
335
335
 
336
- async def _time_impl(check: bool, detailed: bool) -> Optional[int]:
336
+ async def _time_impl(check: bool, detailed: bool, runs: int = 0) -> Optional[int]:
337
337
  if package.get_main_solution() is None:
338
338
  console.console.print(
339
339
  '[warning]No main solution found, so cannot estimate a time limit.[/warning]'
@@ -353,6 +353,7 @@ async def _time_impl(check: bool, detailed: bool) -> Optional[int]:
353
353
  check=check,
354
354
  verification=VerificationLevel(verification),
355
355
  timelimit_override=-1, # Unlimited for time limit estimation
356
+ nruns=runs,
356
357
  )
357
358
 
358
359
  console.console.print()
@@ -397,6 +398,12 @@ async def time(
397
398
  '-d',
398
399
  help='Whether to print a detailed view of the tests using tables.',
399
400
  ),
401
+ runs: int = typer.Option(
402
+ 0,
403
+ '--runs',
404
+ '-r',
405
+ help='Number of runs to perform for each solution. Zero means the config default.',
406
+ ),
400
407
  ):
401
408
  main_solution = package.get_main_solution()
402
409
  if check and main_solution is None:
@@ -411,7 +418,7 @@ async def time(
411
418
  if not await builder.build(verification=verification, output=check):
412
419
  return None
413
420
 
414
- await _time_impl(check, detailed)
421
+ await _time_impl(check, detailed, runs)
415
422
 
416
423
 
417
424
  @app.command(
@@ -814,6 +821,7 @@ def header():
814
821
  generate_header()
815
822
 
816
823
 
824
+ # TODO: warn when using a preset (or show it)
817
825
  @app.command(
818
826
  'environment, env',
819
827
  rich_help_panel='Configuration',
@@ -831,15 +839,14 @@ def environment_command(
831
839
  ] = None,
832
840
  ):
833
841
  if env is None:
834
- cfg = config.get_config()
835
- console.console.print(f'Current environment: [item]{cfg.boxEnvironment}[/item]')
836
842
  console.console.print(
837
- f'Location: {environment.get_environment_path(cfg.boxEnvironment)}'
843
+ f'Current environment: [item]{environment.get_active_environment_description()}[/item]'
838
844
  )
845
+ console.console.print(f'Location: {environment.get_active_environment_path()}')
839
846
  return
840
847
  if install_from is not None:
841
848
  environment.install_environment(env, pathlib.Path(install_from))
842
- if not get_environment_path(env).is_file():
849
+ if not get_app_environment_path(env).is_file():
843
850
  console.console.print(
844
851
  f'[error]Environment [item]{env}[/item] does not exist.[/error]'
845
852
  )
@@ -852,7 +859,7 @@ def environment_command(
852
859
  )
853
860
  return
854
861
  console.console.print(
855
- f'Changing box environment from [item]{cfg.boxEnvironment}[/item] to [item]{env}[/item]...'
862
+ f'Changing global environment from [item]{cfg.boxEnvironment}[/item] to [item]{env}[/item]...'
856
863
  )
857
864
  cfg.boxEnvironment = env
858
865
  config.save_config(cfg)
@@ -861,43 +868,6 @@ def environment_command(
861
868
  clear()
862
869
 
863
870
 
864
- @app.command(
865
- 'activate',
866
- rich_help_panel='Configuration',
867
- help='Activate the environment of the current preset used by the package.',
868
- )
869
- @cd.within_closest_package
870
- def activate():
871
- preset_lock = presets.get_preset_lock()
872
- if preset_lock is None:
873
- console.console.print(
874
- '[warning]No configured preset to be activated for this package.[/warning]'
875
- )
876
- raise typer.Exit(1)
877
-
878
- preset = presets.get_installed_preset_or_null(preset_lock.preset_name)
879
- if preset is None:
880
- if preset_lock.uri is None:
881
- console.console.print(
882
- '[error]Preset is not installed. Install it manually, or specify a URI in [item].preset-lock.yml[/item].[/error]'
883
- )
884
- raise typer.Exit(1)
885
- presets.install(preset_lock.uri)
886
-
887
- preset = presets.get_installed_preset(preset_lock.preset_name)
888
-
889
- # Install the environment from the preset if it's not already installed.
890
- presets.optionally_install_environment_from_preset(
891
- preset, root=presets.get_preset_installation_path(preset_lock.name)
892
- )
893
-
894
- # Activate the environment.
895
- if preset.env is not None:
896
- environment_command(preset.name)
897
-
898
- console.console.print(f'[success]Preset [item]{preset.name}[/item] is activated.')
899
-
900
-
901
871
  @app.command(
902
872
  'languages',
903
873
  rich_help_panel='Configuration',
@@ -918,6 +888,40 @@ def languages():
918
888
  console.console.print()
919
889
 
920
890
 
891
+ @app.command(
892
+ 'stats',
893
+ rich_help_panel='Management',
894
+ help='Show stats about current and related packages.',
895
+ )
896
+ @cd.within_closest_package
897
+ def stats(
898
+ transitive: bool = typer.Option(
899
+ False,
900
+ '--transitive',
901
+ '-t',
902
+ help='Show stats about all reachable packages.',
903
+ ),
904
+ ):
905
+ from rbx.box import stats
906
+
907
+ if transitive:
908
+ stats.print_reachable_package_stats()
909
+ else:
910
+ stats.print_package_stats()
911
+
912
+
913
+ @app.command(
914
+ 'fix',
915
+ rich_help_panel='Management',
916
+ help='Format files of the current package.',
917
+ )
918
+ @cd.within_closest_wrapper
919
+ def fix(print_diff: bool = typer.Option(False, '--print-diff', '-p')):
920
+ from rbx.box import linting
921
+
922
+ linting.fix_package(print_diff=print_diff)
923
+
924
+
921
925
  @app.command(
922
926
  'clear, clean',
923
927
  rich_help_panel='Management',
@@ -408,6 +408,7 @@ def _precompile_header(
408
408
  input_artifact: GradingFileInput,
409
409
  force_warnings: bool = False,
410
410
  verbose: bool = False,
411
+ include_other_headers: bool = False,
411
412
  ) -> GradingFileInput:
412
413
  """
413
414
  Precompile a header file (.h).
@@ -435,11 +436,12 @@ def _precompile_header(
435
436
  precompilation_artifacts = GradingArtifacts()
436
437
 
437
438
  # Keep only header files.
438
- precompilation_artifacts.inputs = [
439
- input
440
- for input in artifacts.inputs
441
- if input.src is not None and input.src.suffix == '.h'
442
- ]
439
+ if include_other_headers:
440
+ precompilation_artifacts.inputs = [
441
+ input
442
+ for input in artifacts.inputs
443
+ if input.src is not None and input.src.suffix == '.h'
444
+ ]
443
445
  precompilation_artifacts.inputs.append(
444
446
  GradingFileInput(
445
447
  src=input_artifact.src,
@@ -572,14 +574,14 @@ def compile_item(
572
574
  if is_cxx_command(get_exe_from_command(command))
573
575
  ]
574
576
 
575
- # Precompile C++ header files.
577
+ # Precompile C++ interesting header files.
576
578
  if precompile and _should_precompile(commands):
577
579
  precompilation_inputs = []
578
580
  for input in artifacts.inputs:
579
581
  if (
580
582
  input.src is not None
581
583
  and input.src.suffix == '.h'
582
- and input.dest.suffix == '.h'
584
+ and input.dest.name in ['stdc++.h', 'jngen.h', 'testlib.h']
583
585
  ):
584
586
  precompilation_inputs.append(
585
587
  _precompile_header(
@@ -9,7 +9,7 @@ from pydantic import ValidationError
9
9
  from rbx import console, utils
10
10
  from rbx.box import cd
11
11
  from rbx.box.contest.schema import Contest
12
- from rbx.box.package import find_problem_package_or_die, warn_preset_deactivated
12
+ from rbx.box.package import find_problem_package_or_die
13
13
  from rbx.box.schema import Package
14
14
 
15
15
  YAML_NAME = 'contest.rbx.yml'
@@ -24,7 +24,6 @@ def find_contest_yaml(root: pathlib.Path = pathlib.Path()) -> Optional[pathlib.P
24
24
  contest_yaml_path = root / YAML_NAME
25
25
  if not contest_yaml_path.is_file():
26
26
  return None
27
- warn_preset_deactivated(root)
28
27
  return contest_yaml_path
29
28
 
30
29
 
@@ -84,12 +83,10 @@ def get_problems(contest: Contest) -> List[Package]:
84
83
  return problems
85
84
 
86
85
 
87
- def get_ruyaml() -> Tuple[ruyaml.YAML, ruyaml.Any]:
88
- contest_yaml_path = find_contest_yaml()
86
+ def get_ruyaml(root: pathlib.Path = pathlib.Path()) -> Tuple[ruyaml.YAML, ruyaml.Any]:
87
+ contest_yaml_path = find_contest_yaml(root)
89
88
  if contest_yaml_path is None:
90
- console.console.print(
91
- f'Contest not found in {pathlib.Path().absolute()}', style='error'
92
- )
89
+ console.console.print(f'[error]Contest not found in {root.absolute()}[/error]')
93
90
  raise typer.Exit(1)
94
91
  res = ruyaml.YAML()
95
92
  return res, res.load(contest_yaml_path.read_text())
@@ -16,8 +16,8 @@ from rbx.box.contest.contest_package import (
16
16
  within_contest,
17
17
  )
18
18
  from rbx.box.contest.schema import ContestProblem
19
+ from rbx.box.linting import fix_package
19
20
  from rbx.box.packaging import contest_main as packaging
20
- from rbx.box.presets.fetch import get_preset_fetch_info
21
21
  from rbx.box.schema import Package
22
22
  from rbx.config import open_editor
23
23
 
@@ -40,53 +40,18 @@ app.add_typer(
40
40
  def create(
41
41
  path: str,
42
42
  preset: Annotated[
43
- str,
43
+ Optional[str],
44
44
  typer.Option(
45
45
  '--preset',
46
46
  '-p',
47
- help='Which preset to use to create this package. Can be a named of an already installed preset, or an URI, in which case the preset will be downloaded.',
47
+ help='Which preset to use to create this package. Can be a named of an already installed preset, or an URI, in which case the preset will be downloaded.\n'
48
+ 'If not provided, the default preset will be used, or the active preset if any.',
48
49
  ),
49
- ] = 'default',
50
- local: bool = typer.Option(
51
- False,
52
- '--local',
53
- '-l',
54
- help='Whether to inline the installed preset within the contest folder.',
55
- ),
50
+ ] = None,
56
51
  ):
57
52
  console.console.print(f'Creating new contest at [item]{path}[/item]...')
58
53
 
59
- fetch_info = get_preset_fetch_info(preset)
60
- if fetch_info is None:
61
- console.console.print(
62
- f'[error]Invalid preset name/URI [item]{preset}[/item][/error]'
63
- )
64
- raise typer.Exit(1)
65
-
66
- if fetch_info.is_remote():
67
- preset = presets.install_from_remote(fetch_info)
68
- elif fetch_info.is_local_dir():
69
- preset = presets.install_from_local_dir(fetch_info)
70
-
71
- preset_cfg = presets.get_installed_preset(preset)
72
- preset_path = (
73
- presets.get_preset_installation_path(preset)
74
- if preset_cfg.contest is not None
75
- else presets.get_preset_installation_path('default')
76
- )
77
-
78
- contest_path = (
79
- presets.get_preset_installation_path(preset) / preset_cfg.contest
80
- if preset_cfg.contest is not None
81
- else presets.get_preset_installation_path('default') / 'contest'
82
- )
83
-
84
- if not contest_path.is_dir():
85
- console.console.print(
86
- f'[error]Contest template [item]{contest_path}[/item] does not exist.[/error]'
87
- )
88
- raise typer.Exit(1)
89
-
54
+ fetch_info = presets.get_preset_fetch_info_with_fallback(preset)
90
55
  dest_path = pathlib.Path(path)
91
56
 
92
57
  if dest_path.exists():
@@ -100,23 +65,35 @@ def create(
100
65
  )
101
66
  raise typer.Exit(1)
102
67
 
103
- dest_path.mkdir(parents=True, exist_ok=True)
104
- shutil.copytree(str(contest_path), str(dest_path), dirs_exist_ok=True)
105
- shutil.rmtree(str(dest_path / 'build'), ignore_errors=True)
106
- shutil.rmtree(str(dest_path / '.box'), ignore_errors=True)
107
- shutil.rmtree(str(dest_path / '.local.rbx'), ignore_errors=True)
108
- # TODO: consider clearing build and .box recursively for nested problem directories
109
- for lock in dest_path.rglob('.preset-lock.yml'):
110
- lock.unlink(missing_ok=True)
111
-
112
- if local:
113
- presets.copy_local_preset(
114
- preset_path, dest_path, remote_uri=fetch_info.uri or preset_cfg.uri
115
- )
68
+ presets.install_contest(dest_path, fetch_info)
116
69
 
117
70
  with cd.new_package_cd(dest_path):
118
71
  contest_utils.clear_all_caches()
119
- presets.generate_lock(preset if not local else presets.LOCAL)
72
+ fix_package()
73
+ presets.generate_lock()
74
+
75
+
76
+ @app.command('init, i', help='Initialize a new contest in the current directory.')
77
+ def init(
78
+ preset: Annotated[
79
+ Optional[str],
80
+ typer.Option(
81
+ '--preset',
82
+ '-p',
83
+ help='Which preset to use to create this package. Can be a named of an already installed preset, or an URI, in which case the preset will be downloaded.\n'
84
+ 'If not provided, the default preset will be used, or the active preset if any.',
85
+ ),
86
+ ] = None,
87
+ ):
88
+ console.console.print('Initializing new contest in the current directory...')
89
+
90
+ fetch_info = presets.get_preset_fetch_info_with_fallback(preset)
91
+
92
+ presets.install_contest(pathlib.Path.cwd(), fetch_info)
93
+
94
+ contest_utils.clear_all_caches()
95
+ fix_package()
96
+ presets.generate_lock()
120
97
 
121
98
 
122
99
  @app.command('edit, e', help='Open contest.rbx.yml in your default editor.')
@@ -143,9 +120,6 @@ def add(path: str, short_name: str, preset: Optional[str] = None):
143
120
  )
144
121
  raise typer.Exit(1)
145
122
 
146
- preset_lock = presets.get_preset_lock()
147
- if preset is None and preset_lock is not None:
148
- preset = preset_lock.preset_name
149
123
  creation.create(name, preset=preset, path=pathlib.Path(path))
150
124
 
151
125
  contest = find_contest_package_or_die()