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.
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/PKG-INFO +23 -6
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/README.md +19 -3
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/pyproject.toml +13 -2
- rbx_cp-0.7.0/rbx/box/cd.py +98 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/checkers.py +9 -1
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/cli.py +49 -45
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/code.py +9 -7
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/contest/contest_package.py +4 -7
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/contest/main.py +32 -58
- rbx_cp-0.7.0/rbx/box/creation.py +48 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/environment.py +21 -9
- rbx_cp-0.7.0/rbx/box/linting.py +95 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/package.py +3 -34
- rbx_cp-0.7.0/rbx/box/presets/__init__.py +718 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/presets/lock_schema.py +1 -2
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/presets/schema.py +13 -5
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/retries.py +8 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/schema.py +15 -2
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/solutions.py +71 -14
- rbx_cp-0.7.0/rbx/box/stats.py +92 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/tasks.py +6 -3
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/utils/run_ui.py +1 -1
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/sandbox.py +22 -10
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/steps.py +1 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/contest/contest.rbx.yml +4 -3
- rbx_cp-0.7.0/rbx/resources/presets/default/preset.rbx.yml +14 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/problem.rbx.yml +20 -10
- rbx_cp-0.7.0/rbx/resources/presets/default/problem/random.txt +4 -0
- rbx_cp-0.7.0/rbx/resources/presets/default/problem/rbx.h +92 -0
- rbx_cp-0.7.0/rbx/resources/presets/default/problem/statement/statement.rbx.tex +15 -0
- rbx_cp-0.7.0/rbx/resources/presets/default/problem/validator.cpp +16 -0
- rbx_cp-0.6.0/rbx/box/cd.py +0 -60
- rbx_cp-0.6.0/rbx/box/creation.py +0 -78
- rbx_cp-0.6.0/rbx/box/presets/__init__.py +0 -637
- rbx_cp-0.6.0/rbx/resources/presets/default/preset.rbx.yml +0 -12
- rbx_cp-0.6.0/rbx/resources/presets/default/problem/random.txt +0 -2
- rbx_cp-0.6.0/rbx/resources/presets/default/problem/statement/projecao.png +0 -0
- rbx_cp-0.6.0/rbx/resources/presets/default/problem/statement/statement.rbx.tex +0 -18
- rbx_cp-0.6.0/rbx/resources/presets/default/problem/validator.cpp +0 -16
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/LICENSE +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/annotations.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/autoenum.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/builder.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/compile.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/conftest.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/contest/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/contest/build_contest_statements.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/contest/contest_utils.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/contest/schema.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/contest/statements.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/deferred.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/download.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/dump_schemas.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/extensions.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/fields.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/formatting.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/generators.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/generators_test.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/git_utils.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/header.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/lang.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/lazy_importing_main.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/lazy_importing_test.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/main.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/naming.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/boca/extension.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/boca/packager.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/contest_main.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/main.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/moj/packager.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/packager.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/pkg/packager.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/polygon/packager.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/polygon/polygon_api.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/polygon/test.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/polygon/upload.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/packaging/polygon/xml_schema.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/presets/fetch.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/remote.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/sanitizers/warning_stack.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/setter_config.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/solutions_test.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/state.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/build_statements.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/builders.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/expander.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/joiners.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/latex.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/latex_jinja.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/statements/schema.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/stresses.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/stressing/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/stressing/finder_parser.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/stressing/generator_parser.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/testcase_extractors.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/testcase_utils.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/testcases/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/testcases/main.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/tooling/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/tooling/boca/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/tooling/boca/main.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/tooling/boca/scrape.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/tooling/boca/scraper.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/tooling/main.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/captured_log.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/css/app.tcss +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/main.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/build.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/command.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/differ.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/error.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/rich_log_modal.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/run.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/run_explorer.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/run_test_explorer.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/selector.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/screens/test_explorer.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/utils/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/widgets/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/widgets/diff_box.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/widgets/file_log.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/widgets/interaction_box.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/widgets/rich_log_box.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/widgets/test_output_box.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/ui/widgets/two_sided_test_output_box.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/unit.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/validators.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/box/validators_test.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/checker.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/clone.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/config.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/conftest.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/console.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/create.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/edit.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/caching.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/conftest.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/cacher.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/digester.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/sandboxes/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/sandboxes/isolate.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/sandboxes/stupid_sandbox.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/sandboxes/timeit.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/storage.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/test.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/judge/testiso.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/limits.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/processing_context.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/steps_with_caching.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading/steps_with_caching_run_test.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/grading_utils.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/hydration.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/main.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/metadata.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/providers/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/providers/codeforces.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/providers/provider.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/checkers/boilerplate.cpp +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/checkers/noop.cpp +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/default_config.json +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/default_setter_config.mac.yml +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/default_setter_config.yml +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/envs/default.rbx.yml +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/envs/isolate.rbx.yml +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/checker.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compare.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compile/c +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compile/cc +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compile/cpp +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compile/java +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compile/kt +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compile/py2 +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/compile/py3 +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactive/c +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactive/cc +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactive/cpp +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactive/java +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactive/kt +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactive/py2 +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactive/py3 +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactor_compile.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/interactor_run.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/bkp +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/c +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/cc +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/cpp +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/java +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/kt +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/py2 +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/run/py3 +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/safeexec.c +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/boca/safeexec_compile.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/c/compile.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/c/prep.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/c/run.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/compare.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/cpp/compile.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/cpp/prep.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/cpp/run.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/interactor_prep.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/interactor_run.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/java/compile.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/java/prep.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/java/run.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/py2/compile.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/py2/prep.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/py2/run.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/py3/compile.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/py3/prep.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/packagers/moj/scripts/py3/run.sh +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/contest/statement/contest.rbx.tex +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/contest/statement/olymp.sty +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/contest/statement/template.rbx.tex +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/.gitignore +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/gen.cpp +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/random.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/sols/main.cpp +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/sols/slow.cpp +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/sols/wa.cpp +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/statement/olymp.sty +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/statement/template.rbx.tex +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/tests/samples/000.in +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/tests/samples/001.in +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/presets/default/problem/wcmp.cpp +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/templates/rbx.h +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/resources/templates/template.cpp +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/run.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/schema.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/submit.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/submitors/__init__.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/submitors/codeforces.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/submitors/submitor.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/test.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/testcase.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/testcase_rendering.py +0 -0
- {rbx_cp-0.6.0 → rbx_cp-0.7.0}/rbx/testing_utils.py +0 -0
- {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.
|
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
|
-
|
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
|
[](https://pypi.python.org/pypi/rbx/)
|
74
80
|
[](https://pypi.python.org/pypi/rbx/)
|
75
81
|
|
76
|
-
rbx is a CLI tool
|
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
|
-
|
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
|
-
|
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.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
|
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
|
@@ -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'
|
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
|
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
|
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
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
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.
|
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
|
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
|
-
] =
|
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 =
|
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
|
-
|
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
|
-
|
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()
|