rbx.cp 0.5.73__tar.gz → 0.6.1__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.
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/PKG-INFO +23 -6
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/README.md +19 -3
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/pyproject.toml +13 -2
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/annotations.py +21 -1
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/cd.py +11 -1
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/checkers.py +9 -1
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/cli.py +59 -46
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/code.py +142 -3
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/contest/build_contest_statements.py +44 -34
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/contest/contest_package.py +4 -7
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/contest/main.py +7 -58
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/contest/schema.py +52 -8
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/contest/statements.py +53 -25
- rbx_cp-0.6.1/rbx/box/creation.py +45 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/environment.py +21 -9
- rbx_cp-0.6.1/rbx/box/fields.py +35 -0
- rbx_cp-0.6.1/rbx/box/lang.py +27 -0
- rbx_cp-0.6.1/rbx/box/linting.py +26 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/package.py +4 -35
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/packaging/boca/packager.py +48 -5
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/packaging/contest_main.py +13 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/packaging/main.py +13 -2
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/packaging/packager.py +4 -4
- rbx_cp-0.6.1/rbx/box/packaging/pkg/packager.py +142 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/packaging/polygon/packager.py +2 -24
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/packaging/polygon/upload.py +35 -17
- rbx_cp-0.6.1/rbx/box/presets/__init__.py +718 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/presets/lock_schema.py +1 -2
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/presets/schema.py +13 -5
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/remote.py +2 -2
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/retries.py +8 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/schema.py +82 -19
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/solutions.py +77 -15
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/statements/build_statements.py +44 -27
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/statements/builders.py +18 -10
- rbx_cp-0.6.1/rbx/box/statements/expander.py +49 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/statements/latex_jinja.py +61 -4
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/statements/schema.py +33 -9
- rbx_cp-0.6.1/rbx/box/stats.py +92 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/tasks.py +6 -3
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/testcase_utils.py +19 -47
- rbx_cp-0.6.1/rbx/box/tooling/boca/main.py +13 -0
- rbx_cp-0.6.1/rbx/box/tooling/boca/scrape.py +34 -0
- rbx_cp-0.5.73/rbx/box/packaging/boca/upload.py → rbx_cp-0.6.1/rbx/box/tooling/boca/scraper.py +77 -8
- rbx_cp-0.6.1/rbx/box/tooling/main.py +8 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/utils/run_ui.py +1 -1
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/widgets/interaction_box.py +19 -1
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/caching.py +18 -2
- rbx_cp-0.6.1/rbx/grading/judge/__init__.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/judge/sandbox.py +60 -5
- rbx_cp-0.6.1/rbx/grading/judge/sandboxes/__init__.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/judge/sandboxes/isolate.py +1 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/judge/sandboxes/stupid_sandbox.py +11 -5
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/judge/sandboxes/timeit.py +36 -15
- rbx_cp-0.6.1/rbx/grading/processing_context.py +71 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/steps.py +92 -40
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/checker.sh +4 -1
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/compile/c +2 -6
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/compile/cc +2 -6
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/compile/cpp +2 -6
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/compile/java +1 -6
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/compile/kt +24 -28
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/compile/py2 +2 -6
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/compile/py3 +2 -6
- rbx_cp-0.6.1/rbx/resources/packagers/boca/interactive/c +173 -0
- rbx_cp-0.6.1/rbx/resources/packagers/boca/interactive/cc +173 -0
- rbx_cp-0.6.1/rbx/resources/packagers/boca/interactive/cpp +173 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/interactive/java +15 -88
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/interactive/kt +15 -88
- rbx_cp-0.6.1/rbx/resources/packagers/boca/interactive/py2 +170 -0
- rbx_cp-0.6.1/rbx/resources/packagers/boca/interactive/py3 +170 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/interactor_compile.sh +5 -2
- rbx_cp-0.6.1/rbx/resources/packagers/boca/interactor_run.sh +174 -0
- rbx_cp-0.6.1/rbx/resources/packagers/boca/safeexec.c +530 -0
- rbx_cp-0.6.1/rbx/resources/packagers/boca/safeexec_compile.sh +49 -0
- rbx_cp-0.6.1/rbx/resources/presets/default/contest/contest.rbx.yml +15 -0
- rbx_cp-0.6.1/rbx/resources/presets/default/problem/problem.rbx.yml +56 -0
- rbx_cp-0.6.1/rbx/resources/presets/default/problem/random.txt +4 -0
- rbx_cp-0.6.1/rbx/resources/presets/default/problem/rbx.h +92 -0
- rbx_cp-0.6.1/rbx/resources/presets/default/problem/statement/statement.rbx.tex +15 -0
- rbx_cp-0.6.1/rbx/resources/presets/default/problem/validator.cpp +16 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/templates/rbx.h +2 -3
- rbx_cp-0.5.73/rbx/box/creation.py +0 -78
- rbx_cp-0.5.73/rbx/box/presets/__init__.py +0 -637
- rbx_cp-0.5.73/rbx/grading/processing_context.py +0 -87
- rbx_cp-0.5.73/rbx/resources/packagers/boca/compile/pas +0 -172
- rbx_cp-0.5.73/rbx/resources/packagers/boca/interactive/c +0 -241
- rbx_cp-0.5.73/rbx/resources/packagers/boca/interactive/cc +0 -241
- rbx_cp-0.5.73/rbx/resources/packagers/boca/interactive/cpp +0 -241
- rbx_cp-0.5.73/rbx/resources/packagers/boca/interactive/py2 +0 -243
- rbx_cp-0.5.73/rbx/resources/packagers/boca/interactive/py3 +0 -243
- rbx_cp-0.5.73/rbx/resources/presets/default/contest/contest.rbx.yml +0 -14
- rbx_cp-0.5.73/rbx/resources/presets/default/problem/problem.rbx.yml +0 -44
- rbx_cp-0.5.73/rbx/resources/presets/default/problem/random.txt +0 -2
- rbx_cp-0.5.73/rbx/resources/presets/default/problem/statement/projecao.png +0 -0
- rbx_cp-0.5.73/rbx/resources/presets/default/problem/statement/statement.rbx.tex +0 -18
- rbx_cp-0.5.73/rbx/resources/presets/default/problem/validator.cpp +0 -16
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/LICENSE +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/__init__.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/autoenum.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/__init__.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/builder.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/compile.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/conftest.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/contest/__init__.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/contest/contest_utils.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/deferred.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/download.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/dump_schemas.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/extensions.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/formatting.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/generators.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/generators_test.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/git_utils.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/header.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/lazy_importing_main.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/lazy_importing_test.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/main.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/naming.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/packaging/boca/extension.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/packaging/moj/packager.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/packaging/polygon/polygon_api.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/packaging/polygon/test.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/packaging/polygon/xml_schema.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/presets/fetch.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/sanitizers/warning_stack.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/setter_config.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/solutions_test.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/state.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/statements/__init__.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/statements/joiners.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/statements/latex.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/stresses.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/stressing/__init__.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/stressing/finder_parser.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/stressing/generator_parser.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/testcase_extractors.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/testcases/__init__.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/testcases/main.py +0 -0
- {rbx_cp-0.5.73/rbx/box/ui → rbx_cp-0.6.1/rbx/box/tooling}/__init__.py +0 -0
- {rbx_cp-0.5.73/rbx/box/ui/screens → rbx_cp-0.6.1/rbx/box/tooling/boca}/__init__.py +0 -0
- {rbx_cp-0.5.73/rbx/box/ui/utils → rbx_cp-0.6.1/rbx/box/ui}/__init__.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/captured_log.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/css/app.tcss +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/main.py +0 -0
- {rbx_cp-0.5.73/rbx/box/ui/widgets → rbx_cp-0.6.1/rbx/box/ui/screens}/__init__.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/screens/build.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/screens/command.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/screens/differ.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/screens/error.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/screens/rich_log_modal.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/screens/run.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/screens/run_explorer.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/screens/run_test_explorer.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/screens/selector.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/screens/test_explorer.py +0 -0
- {rbx_cp-0.5.73/rbx/grading → rbx_cp-0.6.1/rbx/box/ui/utils}/__init__.py +0 -0
- {rbx_cp-0.5.73/rbx/grading/judge → rbx_cp-0.6.1/rbx/box/ui/widgets}/__init__.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/widgets/diff_box.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/widgets/file_log.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/widgets/rich_log_box.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/widgets/test_output_box.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/ui/widgets/two_sided_test_output_box.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/unit.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/validators.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/box/validators_test.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/checker.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/clone.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/config.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/conftest.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/console.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/create.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/edit.py +0 -0
- {rbx_cp-0.5.73/rbx/grading/judge/sandboxes → rbx_cp-0.6.1/rbx/grading}/__init__.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/conftest.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/judge/cacher.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/judge/digester.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/judge/storage.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/judge/test.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/judge/testiso.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/limits.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/steps_with_caching.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading/steps_with_caching_run_test.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/grading_utils.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/hydration.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/main.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/metadata.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/providers/__init__.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/providers/codeforces.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/providers/provider.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/checkers/boilerplate.cpp +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/checkers/noop.cpp +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/default_config.json +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/default_setter_config.mac.yml +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/default_setter_config.yml +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/envs/default.rbx.yml +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/envs/isolate.rbx.yml +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/compare.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/run/bkp +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/run/c +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/run/cc +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/run/cpp +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/run/java +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/run/kt +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/run/py2 +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/boca/run/py3 +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/c/compile.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/c/prep.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/c/run.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/compare.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/cpp/compile.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/cpp/prep.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/cpp/run.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/interactor_prep.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/interactor_run.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/java/compile.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/java/prep.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/java/run.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/py2/compile.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/py2/prep.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/py2/run.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/py3/compile.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/py3/prep.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/packagers/moj/scripts/py3/run.sh +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/contest/statement/contest.rbx.tex +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/contest/statement/olymp.sty +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/contest/statement/template.rbx.tex +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/preset.rbx.yml +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/problem/.gitignore +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/problem/gen.cpp +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/problem/random.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/problem/sols/main.cpp +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/problem/sols/slow.cpp +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/problem/sols/wa.cpp +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/problem/statement/olymp.sty +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/problem/statement/template.rbx.tex +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/problem/tests/samples/000.in +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/problem/tests/samples/001.in +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/presets/default/problem/wcmp.cpp +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/resources/templates/template.cpp +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/run.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/schema.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/submit.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/submitors/__init__.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/submitors/codeforces.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/submitors/submitor.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/test.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/testcase.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/testcase_rendering.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/testing_utils.py +0 -0
- {rbx_cp-0.5.73 → rbx_cp-0.6.1}/rbx/utils.py +0 -0
@@ -1,11 +1,10 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: rbx.cp
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.6.1
|
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
|
@@ -16,6 +15,7 @@ Requires-Dist: beautifulsoup4 (>=4.13.4,<5.0.0)
|
|
16
15
|
Requires-Dist: chardet (>=5.2.0,<6.0.0)
|
17
16
|
Requires-Dist: colour (>=0.1.5,<0.2.0)
|
18
17
|
Requires-Dist: dateparser (>=1.2.1,<2.0.0)
|
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
21
|
Requires-Dist: gitpython (>=3.1.43,<4.0.0)
|
@@ -39,10 +39,15 @@ Requires-Dist: syncer (>=2.0.3,<3.0.0)
|
|
39
39
|
Requires-Dist: textual (>=3.1.1,<4.0.0)
|
40
40
|
Requires-Dist: textual-serve (>=1.1.2,<2.0.0)
|
41
41
|
Requires-Dist: typer (>=0.15.1,<0.16.0)
|
42
|
+
Requires-Dist: yamlfix (>=1.17.0,<2.0.0)
|
42
43
|
Description-Content-Type: text/markdown
|
43
44
|
|
44
45
|
<p align="center">
|
45
|
-
|
46
|
+
<img src="docs/rbx_white.png" alt="rbx" width="200">
|
47
|
+
</p>
|
48
|
+
|
49
|
+
<p align="center">
|
50
|
+
<em>The go-to CLI tool for programming competitions setters.</em>
|
46
51
|
</p>
|
47
52
|
<p align="center">
|
48
53
|
<!-- loscal repository, no metadata badges. -->
|
@@ -59,6 +64,7 @@ Description-Content-Type: text/markdown
|
|
59
64
|
<summary>Table of Contents</summary><br>
|
60
65
|
|
61
66
|
- [Overview](#overview)
|
67
|
+
- [Features](#features)
|
62
68
|
- [Documentation](#documentation)
|
63
69
|
- [License](#license)
|
64
70
|
</details>
|
@@ -72,9 +78,20 @@ Description-Content-Type: text/markdown
|
|
72
78
|
[](https://pypi.python.org/pypi/rbx/)
|
73
79
|
[](https://pypi.python.org/pypi/rbx/)
|
74
80
|
|
75
|
-
rbx is a CLI tool
|
81
|
+
**rbx** is a CLI tool that empowers setters from the competitive programming community.
|
82
|
+
|
83
|
+
A flexible setting tool, as powerful as [Polygon](https://polygon.codeforces.com/), right on your terminal.
|
84
|
+
|
85
|
+
---
|
86
|
+
|
87
|
+
## Features
|
76
88
|
|
77
|
-
|
89
|
+
- 🧱 Structure: describe your problem or contest structure with the use of YAML configuration files.
|
90
|
+
- 🤖 Generation: provides a simple way to describe your whole testset, including both manually added and generated testcases.
|
91
|
+
- 🔨 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.
|
92
|
+
- ✅ Verify: checks if your testcases and solutions are strictly conformant with the use of validators and unit tests.
|
93
|
+
- 📝 Statements: provides tooling for writing and building statements, also ensuring they're easily synchronized with your testset.
|
94
|
+
- 📤 Package: provides a single command for packaging your problems for use in your preferred judge system.
|
78
95
|
|
79
96
|
---
|
80
97
|
|
@@ -1,5 +1,9 @@
|
|
1
1
|
<p align="center">
|
2
|
-
|
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
|
[](https://pypi.python.org/pypi/rbx/)
|
30
35
|
[](https://pypi.python.org/pypi/rbx/)
|
31
36
|
|
32
|
-
rbx is a CLI tool
|
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
|
-
|
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.
|
3
|
+
version = "0.6.1"
|
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"
|
@@ -42,6 +42,8 @@ aiofiles = "^24.1.0"
|
|
42
42
|
colour = "^0.1.5"
|
43
43
|
beautifulsoup4 = "^4.13.4"
|
44
44
|
dateparser = "^1.2.1"
|
45
|
+
deepmerge = "^2.0"
|
46
|
+
yamlfix = "^1.17.0"
|
45
47
|
|
46
48
|
[tool.poetry.scripts]
|
47
49
|
rbc = "rbx.main:app"
|
@@ -62,7 +64,16 @@ pytest-cov = "^5.0.0"
|
|
62
64
|
textual-dev = "^1.6.1"
|
63
65
|
pytest-asyncio = "^0.26.0"
|
64
66
|
mkdocs-gen-files = "^0.5.0"
|
67
|
+
markdown-grid-tables = "^0.5.0"
|
65
68
|
|
69
|
+
|
70
|
+
[tool.commitizen]
|
71
|
+
name = "cz_conventional_commits"
|
72
|
+
tag_format = "$version"
|
73
|
+
version_scheme = "pep440"
|
74
|
+
version_provider = "poetry"
|
75
|
+
update_changelog_on_bump = true
|
76
|
+
major_version_zero = true
|
66
77
|
[build-system]
|
67
78
|
requires = ["poetry-core"]
|
68
79
|
build-backend = "poetry.core.masonry.api"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import importlib.resources
|
2
2
|
import pathlib
|
3
3
|
import re
|
4
|
-
from typing import List, Optional
|
4
|
+
from typing import Any, Dict, List, Optional
|
5
5
|
|
6
6
|
import typer
|
7
7
|
import typer.core
|
@@ -112,6 +112,26 @@ Checker = Annotated[
|
|
112
112
|
]
|
113
113
|
|
114
114
|
|
115
|
+
def parse_dictionary(value: Optional[str]) -> Dict[str, Any]:
|
116
|
+
if value is None:
|
117
|
+
return {}
|
118
|
+
res = {}
|
119
|
+
for item in value.split(','):
|
120
|
+
key, value = item.split('=', 1)
|
121
|
+
res[key] = value
|
122
|
+
return res
|
123
|
+
|
124
|
+
|
125
|
+
def parse_dictionary_items(items: Optional[List[str]]) -> Dict[str, Any]:
|
126
|
+
if items is None:
|
127
|
+
return {}
|
128
|
+
res = {}
|
129
|
+
for item in items:
|
130
|
+
key, value = item.split('=', 1)
|
131
|
+
res[key] = value
|
132
|
+
return res
|
133
|
+
|
134
|
+
|
115
135
|
class AliasGroup(typer.core.TyperGroup):
|
116
136
|
_CMD_SPLIT_P = re.compile(r', ?')
|
117
137
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import contextlib
|
2
2
|
import functools
|
3
3
|
import pathlib
|
4
|
-
from typing import Optional
|
4
|
+
from typing import List, Optional
|
5
5
|
|
6
6
|
import typer
|
7
7
|
|
@@ -25,6 +25,16 @@ def find_package(root: pathlib.Path = pathlib.Path()) -> Optional[pathlib.Path]:
|
|
25
25
|
return root
|
26
26
|
|
27
27
|
|
28
|
+
def find_all_ancestor_packages(
|
29
|
+
root: pathlib.Path = pathlib.Path(),
|
30
|
+
) -> List[pathlib.Path]:
|
31
|
+
packages = []
|
32
|
+
while (pkg := find_package(root)) is not None:
|
33
|
+
packages.append(pkg)
|
34
|
+
root = pkg.parent
|
35
|
+
return packages
|
36
|
+
|
37
|
+
|
28
38
|
def is_problem_package(root: pathlib.Path = pathlib.Path()) -> bool:
|
29
39
|
dir = find_package(root)
|
30
40
|
if dir is None:
|
@@ -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
|
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,
|
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
|
@@ -42,6 +42,7 @@ from rbx.box.solutions import (
|
|
42
42
|
from rbx.box.statements import build_statements
|
43
43
|
from rbx.box.testcase_utils import TestcaseEntry
|
44
44
|
from rbx.box.testcases import main as testcases
|
45
|
+
from rbx.box.tooling import main as tooling
|
45
46
|
|
46
47
|
app = typer.Typer(no_args_is_help=True, cls=annotations.AliasGroup)
|
47
48
|
app.add_typer(
|
@@ -93,6 +94,13 @@ app.add_typer(
|
|
93
94
|
help='Manage testcases (sub-command).',
|
94
95
|
rich_help_panel='Management',
|
95
96
|
)
|
97
|
+
app.add_typer(
|
98
|
+
tooling.app,
|
99
|
+
name='tool, tooling',
|
100
|
+
cls=annotations.AliasGroup,
|
101
|
+
help='Manage tooling (sub-command).',
|
102
|
+
rich_help_panel='Misc',
|
103
|
+
)
|
96
104
|
|
97
105
|
|
98
106
|
@app.callback()
|
@@ -106,7 +114,8 @@ def main(
|
|
106
114
|
),
|
107
115
|
capture: bool = typer.Option(
|
108
116
|
True,
|
109
|
-
'--
|
117
|
+
'--nocapture',
|
118
|
+
flag_value=False,
|
110
119
|
help='Whether to save extra logs and outputs from interactive solutions.',
|
111
120
|
),
|
112
121
|
):
|
@@ -324,7 +333,7 @@ async def run(
|
|
324
333
|
)
|
325
334
|
|
326
335
|
|
327
|
-
async def _time_impl(check: bool, detailed: bool) -> Optional[int]:
|
336
|
+
async def _time_impl(check: bool, detailed: bool, runs: int = 0) -> Optional[int]:
|
328
337
|
if package.get_main_solution() is None:
|
329
338
|
console.console.print(
|
330
339
|
'[warning]No main solution found, so cannot estimate a time limit.[/warning]'
|
@@ -344,6 +353,7 @@ async def _time_impl(check: bool, detailed: bool) -> Optional[int]:
|
|
344
353
|
check=check,
|
345
354
|
verification=VerificationLevel(verification),
|
346
355
|
timelimit_override=-1, # Unlimited for time limit estimation
|
356
|
+
nruns=runs,
|
347
357
|
)
|
348
358
|
|
349
359
|
console.console.print()
|
@@ -388,6 +398,12 @@ async def time(
|
|
388
398
|
'-d',
|
389
399
|
help='Whether to print a detailed view of the tests using tables.',
|
390
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
|
+
),
|
391
407
|
):
|
392
408
|
main_solution = package.get_main_solution()
|
393
409
|
if check and main_solution is None:
|
@@ -402,7 +418,7 @@ async def time(
|
|
402
418
|
if not await builder.build(verification=verification, output=check):
|
403
419
|
return None
|
404
420
|
|
405
|
-
await _time_impl(check, detailed)
|
421
|
+
await _time_impl(check, detailed, runs)
|
406
422
|
|
407
423
|
|
408
424
|
@app.command(
|
@@ -805,6 +821,7 @@ def header():
|
|
805
821
|
generate_header()
|
806
822
|
|
807
823
|
|
824
|
+
# TODO: warn when using a preset (or show it)
|
808
825
|
@app.command(
|
809
826
|
'environment, env',
|
810
827
|
rich_help_panel='Configuration',
|
@@ -822,15 +839,14 @@ def environment_command(
|
|
822
839
|
] = None,
|
823
840
|
):
|
824
841
|
if env is None:
|
825
|
-
cfg = config.get_config()
|
826
|
-
console.console.print(f'Current environment: [item]{cfg.boxEnvironment}[/item]')
|
827
842
|
console.console.print(
|
828
|
-
f'
|
843
|
+
f'Current environment: [item]{environment.get_active_environment_description()}[/item]'
|
829
844
|
)
|
845
|
+
console.console.print(f'Location: {environment.get_active_environment_path()}')
|
830
846
|
return
|
831
847
|
if install_from is not None:
|
832
848
|
environment.install_environment(env, pathlib.Path(install_from))
|
833
|
-
if not
|
849
|
+
if not get_app_environment_path(env).is_file():
|
834
850
|
console.console.print(
|
835
851
|
f'[error]Environment [item]{env}[/item] does not exist.[/error]'
|
836
852
|
)
|
@@ -843,7 +859,7 @@ def environment_command(
|
|
843
859
|
)
|
844
860
|
return
|
845
861
|
console.console.print(
|
846
|
-
f'Changing
|
862
|
+
f'Changing global environment from [item]{cfg.boxEnvironment}[/item] to [item]{env}[/item]...'
|
847
863
|
)
|
848
864
|
cfg.boxEnvironment = env
|
849
865
|
config.save_config(cfg)
|
@@ -852,43 +868,6 @@ def environment_command(
|
|
852
868
|
clear()
|
853
869
|
|
854
870
|
|
855
|
-
@app.command(
|
856
|
-
'activate',
|
857
|
-
rich_help_panel='Configuration',
|
858
|
-
help='Activate the environment of the current preset used by the package.',
|
859
|
-
)
|
860
|
-
@cd.within_closest_package
|
861
|
-
def activate():
|
862
|
-
preset_lock = presets.get_preset_lock()
|
863
|
-
if preset_lock is None:
|
864
|
-
console.console.print(
|
865
|
-
'[warning]No configured preset to be activated for this package.[/warning]'
|
866
|
-
)
|
867
|
-
raise typer.Exit(1)
|
868
|
-
|
869
|
-
preset = presets.get_installed_preset_or_null(preset_lock.preset_name)
|
870
|
-
if preset is None:
|
871
|
-
if preset_lock.uri is None:
|
872
|
-
console.console.print(
|
873
|
-
'[error]Preset is not installed. Install it manually, or specify a URI in [item].preset-lock.yml[/item].[/error]'
|
874
|
-
)
|
875
|
-
raise typer.Exit(1)
|
876
|
-
presets.install(preset_lock.uri)
|
877
|
-
|
878
|
-
preset = presets.get_installed_preset(preset_lock.preset_name)
|
879
|
-
|
880
|
-
# Install the environment from the preset if it's not already installed.
|
881
|
-
presets.optionally_install_environment_from_preset(
|
882
|
-
preset, root=presets.get_preset_installation_path(preset_lock.name)
|
883
|
-
)
|
884
|
-
|
885
|
-
# Activate the environment.
|
886
|
-
if preset.env is not None:
|
887
|
-
environment_command(preset.name)
|
888
|
-
|
889
|
-
console.console.print(f'[success]Preset [item]{preset.name}[/item] is activated.')
|
890
|
-
|
891
|
-
|
892
871
|
@app.command(
|
893
872
|
'languages',
|
894
873
|
rich_help_panel='Configuration',
|
@@ -909,6 +888,40 @@ def languages():
|
|
909
888
|
console.console.print()
|
910
889
|
|
911
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_package
|
919
|
+
def fix():
|
920
|
+
from rbx.box import linting
|
921
|
+
|
922
|
+
linting.fix_package()
|
923
|
+
|
924
|
+
|
912
925
|
@app.command(
|
913
926
|
'clear, clean',
|
914
927
|
rich_help_panel='Management',
|
@@ -14,6 +14,7 @@ import typer
|
|
14
14
|
from rbx import console
|
15
15
|
from rbx.box import download, package, setter_config, state
|
16
16
|
from rbx.box.environment import (
|
17
|
+
CompilationConfig,
|
17
18
|
ExecutionConfig,
|
18
19
|
FileMapping,
|
19
20
|
get_compilation_config,
|
@@ -29,7 +30,7 @@ from rbx.box.formatting import get_formatted_memory
|
|
29
30
|
from rbx.box.sanitizers import warning_stack
|
30
31
|
from rbx.box.schema import CodeItem
|
31
32
|
from rbx.grading import steps, steps_with_caching
|
32
|
-
from rbx.grading.judge.sandbox import SandboxParams
|
33
|
+
from rbx.grading.judge.sandbox import SandboxBase, SandboxParams
|
33
34
|
from rbx.grading.steps import (
|
34
35
|
DigestHolder,
|
35
36
|
DigestOrDest,
|
@@ -39,7 +40,10 @@ from rbx.grading.steps import (
|
|
39
40
|
GradingFileOutput,
|
40
41
|
RunLog,
|
41
42
|
RunLogMetadata,
|
43
|
+
get_exe_from_command,
|
44
|
+
is_cpp_command,
|
42
45
|
is_cxx_command,
|
46
|
+
maybe_get_bits_stdcpp_for_commands,
|
43
47
|
)
|
44
48
|
|
45
49
|
|
@@ -391,12 +395,111 @@ def _prepare_run(
|
|
391
395
|
)
|
392
396
|
|
393
397
|
|
398
|
+
def _should_precompile(commands: List[str]) -> bool:
|
399
|
+
return any(is_cpp_command(command) for command in commands)
|
400
|
+
|
401
|
+
|
402
|
+
def _precompile_header(
|
403
|
+
compilation_options: CompilationConfig,
|
404
|
+
sanitized: SanitizationLevel,
|
405
|
+
sandbox: SandboxBase,
|
406
|
+
sandbox_params: SandboxParams,
|
407
|
+
artifacts: GradingArtifacts,
|
408
|
+
input_artifact: GradingFileInput,
|
409
|
+
force_warnings: bool = False,
|
410
|
+
verbose: bool = False,
|
411
|
+
include_other_headers: bool = False,
|
412
|
+
) -> GradingFileInput:
|
413
|
+
"""
|
414
|
+
Precompile a header file (.h).
|
415
|
+
|
416
|
+
Assumes input artifact is a header file (.h) and compilation commands are C++.
|
417
|
+
"""
|
418
|
+
assert compilation_options.commands is not None
|
419
|
+
|
420
|
+
dependency_cache = package.get_dependency_cache()
|
421
|
+
|
422
|
+
# TODO: deduplicate code with compile_item.
|
423
|
+
commands = get_mapped_commands(
|
424
|
+
compilation_options.commands,
|
425
|
+
FileMapping(
|
426
|
+
compilable='precompilable.h',
|
427
|
+
executable='precompilable.h.gch',
|
428
|
+
),
|
429
|
+
)
|
430
|
+
commands = add_warning_flags(commands, force_warnings)
|
431
|
+
commands = substitute_commands(commands, sanitized=sanitized.should_sanitize())
|
432
|
+
|
433
|
+
if sanitized.should_sanitize():
|
434
|
+
commands = add_sanitizer_flags(commands)
|
435
|
+
|
436
|
+
precompilation_artifacts = GradingArtifacts()
|
437
|
+
|
438
|
+
# Keep only header files.
|
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
|
+
]
|
445
|
+
precompilation_artifacts.inputs.append(
|
446
|
+
GradingFileInput(
|
447
|
+
src=input_artifact.src,
|
448
|
+
dest=PosixPath('precompilable.h'),
|
449
|
+
)
|
450
|
+
)
|
451
|
+
|
452
|
+
# Pull only the precompiled header file.
|
453
|
+
precompiled_digest = DigestHolder()
|
454
|
+
precompilation_artifacts.outputs.append(
|
455
|
+
GradingFileOutput(
|
456
|
+
src=PosixPath('precompilable.h.gch'),
|
457
|
+
digest=precompiled_digest,
|
458
|
+
executable=True,
|
459
|
+
)
|
460
|
+
)
|
461
|
+
|
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)
|
473
|
+
|
474
|
+
if verbose:
|
475
|
+
console.console.print(
|
476
|
+
f'[status]Precompiled header file: [item]{input_artifact.src}[/item]'
|
477
|
+
)
|
478
|
+
|
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()}')
|
486
|
+
|
487
|
+
assert precompiled_digest.value is not None
|
488
|
+
|
489
|
+
return GradingFileInput(
|
490
|
+
digest=precompiled_digest,
|
491
|
+
dest=input_artifact.dest.with_suffix('.h.gch'),
|
492
|
+
executable=True,
|
493
|
+
)
|
494
|
+
|
495
|
+
|
394
496
|
# Compile code item and return its digest in the storage.
|
395
497
|
def compile_item(
|
396
498
|
code: CodeItem,
|
397
499
|
sanitized: SanitizationLevel = SanitizationLevel.PREFER,
|
398
500
|
force_warnings: bool = False,
|
399
501
|
verbose: bool = False,
|
502
|
+
precompile: bool = True,
|
400
503
|
) -> str:
|
401
504
|
_check_stack_limit()
|
402
505
|
|
@@ -461,6 +564,41 @@ def compile_item(
|
|
461
564
|
for input in artifacts.inputs:
|
462
565
|
_ignore_warning_in_cxx_input(input)
|
463
566
|
|
567
|
+
# Add system bits/stdc++.h to the compilation.
|
568
|
+
bits_artifact = maybe_get_bits_stdcpp_for_commands(commands)
|
569
|
+
if bits_artifact is not None:
|
570
|
+
artifacts.inputs.append(bits_artifact)
|
571
|
+
commands = [
|
572
|
+
command + ' -I.'
|
573
|
+
for command in commands
|
574
|
+
if is_cxx_command(get_exe_from_command(command))
|
575
|
+
]
|
576
|
+
|
577
|
+
# Precompile C++ interesting header files.
|
578
|
+
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,
|
596
|
+
)
|
597
|
+
)
|
598
|
+
if precompilation_inputs:
|
599
|
+
artifacts.inputs.extend(precompilation_inputs)
|
600
|
+
|
601
|
+
# Compile the code.
|
464
602
|
if not steps_with_caching.compile(
|
465
603
|
commands,
|
466
604
|
params=sandbox_params,
|
@@ -473,6 +611,7 @@ def compile_item(
|
|
473
611
|
assert compiled_digest.value is not None
|
474
612
|
|
475
613
|
if verbose and artifacts.logs is not None and artifacts.logs.preprocess is not None:
|
614
|
+
console.console.print(f'[status]Compiled item: [item]{code.path}[/item]')
|
476
615
|
for log in artifacts.logs.preprocess:
|
477
616
|
console.console.print(f'[status]Command:[/status] {log.get_command()}')
|
478
617
|
console.console.print(f'[status]Summary:[/status] {log.get_summary()}')
|
@@ -589,8 +728,8 @@ async def run_communication(
|
|
589
728
|
interactor_prepared.metadata.retryIndex = retry_index
|
590
729
|
solution_prepared.metadata.retryIndex = retry_index
|
591
730
|
|
592
|
-
interactor_prefix = '
|
593
|
-
solution_prefix = '
|
731
|
+
interactor_prefix = '<'
|
732
|
+
solution_prefix = '>'
|
594
733
|
|
595
734
|
if merged_capture is not None:
|
596
735
|
package.get_merged_capture_path().write_text(
|