rbx.cp 0.18.3__tar.gz → 0.18.4__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.18.3 → rbx_cp-0.18.4}/PKG-INFO +1 -1
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/pyproject.toml +1 -1
- rbx_cp-0.18.4/rbx/__version__.py +1 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/cli.py +7 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/code.py +26 -18
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/contest/build_contest_statements.py +21 -15
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/environment.py +1 -1
- rbx_cp-0.18.4/rbx/box/exception.py +71 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/generators.py +15 -9
- rbx_cp-0.18.4/rbx/box/main.py +17 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/solutions.py +75 -23
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/statements/latex.py +5 -4
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/stresses.py +29 -11
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/console.py +4 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/judge/sandboxes/tee.py +8 -2
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/steps.py +18 -12
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/steps_with_caching.py +14 -10
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/env.rbx.yml +1 -1
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/preset.rbx.yml +1 -1
- rbx_cp-0.18.3/rbx/__version__.py +0 -1
- rbx_cp-0.18.3/rbx/box/main.py +0 -6
- rbx_cp-0.18.3/rbx/resources/envs/default.rbx.yml +0 -67
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/LICENSE +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/README.md +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/annotations.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/autoenum.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/builder.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/cd.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/checkers.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/compile.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/contest/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/contest/contest_package.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/contest/contest_utils.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/contest/main.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/contest/schema.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/contest/statements.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/creation.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/deferred.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/download.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/dump_schemas.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/extensions.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/fields.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/formatting.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/git_utils.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/global_package.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/header.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/lang.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/lazy_importing_main.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/limits_info.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/linting.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/naming.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/package.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/boca/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/boca/boca_language_utils.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/boca/boca_outcome_utils.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/boca/extension.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/boca/packager.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/contest_main.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/importer.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/main.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/moj/packager.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/packager.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/pkg/packager.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/polygon/importer.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/polygon/packager.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/polygon/polygon_api.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/polygon/test.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/polygon/upload.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/packaging/polygon/xml_schema.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/presets/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/presets/fetch.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/presets/lock_schema.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/presets/schema.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/remote.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/retries.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/sanitizers/issue_stack.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/sanitizers/warning_stack.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/schema.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/setter_config.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/state.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/statements/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/statements/build_statements.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/statements/builders.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/statements/expander.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/statements/joiners.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/statements/latex_jinja.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/statements/schema.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/stats.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/stressing/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/stressing/finder_parser.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/stressing/generator_parser.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/tasks.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/testcase_extractors.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/testcase_utils.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/testcases/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/testcases/main.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/testing/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/testing/testing_package.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/testing/testing_preset.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/testing/testing_shared.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/timing.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/tooling/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/tooling/boca/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/tooling/boca/debug_utils.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/tooling/boca/main.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/tooling/boca/manual_scrape.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/tooling/boca/scrape.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/tooling/boca/scraper.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/tooling/converter.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/tooling/main.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/captured_log.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/css/app.tcss +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/main.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/screens/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/screens/build.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/screens/command.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/screens/differ.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/screens/error.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/screens/rich_log_modal.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/screens/run.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/screens/run_explorer.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/screens/run_test_explorer.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/screens/selector.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/screens/test_explorer.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/utils/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/utils/run_ui.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/widgets/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/widgets/diff_box.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/widgets/file_log.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/widgets/interaction_box.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/widgets/rich_log_box.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/widgets/test_output_box.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/ui/widgets/two_sided_test_output_box.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/unit.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/box/validators.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/config.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/caching.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/debug_context.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/grading_context.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/judge/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/judge/cacher.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/judge/digester.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/judge/program.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/judge/sandbox.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/judge/sandboxes/__init__.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/judge/sandboxes/stupid_sandbox.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/judge/storage.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/limits.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/grading/profiling.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/checkers/boilerplate.cpp +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/checkers/noop.cpp +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/default_config.json +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/default_setter_config.mac.yml +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/default_setter_config.yml +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/checker.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/compare.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/compile/c +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/compile/cc +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/compile/cpp +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/compile/java +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/compile/kt +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/compile/py2 +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/compile/py3 +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/interactive/c +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/interactive/cc +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/interactive/cpp +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/interactive/java +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/interactive/kt +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/interactive/py2 +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/interactive/py3 +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/interactor_compile.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/interactor_run.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/run/bkp +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/run/c +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/run/cc +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/run/cpp +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/run/java +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/run/kt +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/run/py2 +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/run/py3 +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/safeexec.c +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/boca/safeexec_compile.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/c/compile.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/c/prep.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/c/run.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/compare.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/cpp/compile.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/cpp/prep.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/cpp/run.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/interactor_prep.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/interactor_run.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/java/compile.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/java/prep.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/java/run.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/py2/compile.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/py2/prep.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/py2/run.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/py3/compile.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/py3/prep.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/packagers/moj/scripts/py3/run.sh +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/contest/.gitignore +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/contest/contest.rbx.yml +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/contest/statement/contest.rbx.tex +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/contest/statement/info.rbx.tex +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/contest/statement/instructions.tex +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/contest/statement/logo.png +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/problem/.gitignore +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/problem/gens/gen.cpp +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/problem/manual_tests/samples/000.in +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/problem/manual_tests/samples/001.in +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/problem/problem.rbx.yml +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/problem/rbx.h +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/problem/sols/main.cpp +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/problem/sols/wa-overflow.cpp +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/problem/statement/statement.rbx.tex +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/problem/testlib.h +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/problem/testplan/random.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/problem/testplan/random.txt +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/problem/validator.cpp +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/problem/wcmp.cpp +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/shared/contest_template.rbx.tex +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/shared/icpc.sty +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/presets/default/shared/problem_template.rbx.tex +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/templates/rbx.h +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/resources/templates/template.cpp +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/testing_utils.py +0 -0
- {rbx_cp-0.18.3 → rbx_cp-0.18.4}/rbx/utils.py +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = '0.18.4'
|
@@ -680,6 +680,12 @@ async def stress(
|
|
680
680
|
help='Whether to print descriptors of the stress test.',
|
681
681
|
hidden=True,
|
682
682
|
),
|
683
|
+
skip_invalid_testcases: bool = typer.Option(
|
684
|
+
False,
|
685
|
+
'--skip-invalid',
|
686
|
+
'--skip',
|
687
|
+
help='Whether to skip invalid testcases.',
|
688
|
+
),
|
683
689
|
):
|
684
690
|
if finder and not generator_args or generator_args and not finder:
|
685
691
|
console.console.print(
|
@@ -701,6 +707,7 @@ async def stress(
|
|
701
707
|
verbose=verbose,
|
702
708
|
sanitized=sanitized,
|
703
709
|
print_descriptors=print_descriptors,
|
710
|
+
skip_invalid_testcases=skip_invalid_testcases,
|
704
711
|
)
|
705
712
|
|
706
713
|
stresses.print_stress_report(report)
|
@@ -443,17 +443,19 @@ def _precompile_header(
|
|
443
443
|
)
|
444
444
|
|
445
445
|
with profiling.PushContext('code.precompile_header'):
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
446
|
+
try:
|
447
|
+
steps_with_caching.compile(
|
448
|
+
commands,
|
449
|
+
params=sandbox_params,
|
450
|
+
artifacts=precompilation_artifacts,
|
451
|
+
sandbox=sandbox,
|
452
|
+
dependency_cache=dependency_cache,
|
453
|
+
)
|
454
|
+
except steps.CompilationError as e:
|
455
|
+
e.print(
|
454
456
|
f'[error]Failed to precompile header file: [item]{input_artifact.src}[/item][/error]'
|
455
457
|
)
|
456
|
-
raise
|
458
|
+
raise
|
457
459
|
|
458
460
|
if verbose:
|
459
461
|
console.console.print(
|
@@ -487,13 +489,14 @@ def _precompile_header(
|
|
487
489
|
):
|
488
490
|
input = DigestOrSource.create(local_cacher.put_file_from_fobj(f))
|
489
491
|
|
490
|
-
|
492
|
+
res = GradingFileInput(
|
491
493
|
**input.expand(),
|
492
494
|
dest=input_artifact.dest.with_suffix('.h.gch'),
|
493
495
|
# Do not track fingerprint of the precompiled header file,
|
494
496
|
# trust the compilation step above.
|
495
497
|
hash=False,
|
496
498
|
)
|
499
|
+
return res
|
497
500
|
|
498
501
|
|
499
502
|
# Compile code item and return its digest in the storage.
|
@@ -609,14 +612,19 @@ def compile_item(
|
|
609
612
|
grading_context.CacheLevel.NO_CACHE,
|
610
613
|
when=lambda: is_path_remote(code.path),
|
611
614
|
):
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
615
|
+
try:
|
616
|
+
steps_with_caching.compile(
|
617
|
+
commands,
|
618
|
+
params=sandbox_params,
|
619
|
+
artifacts=artifacts,
|
620
|
+
sandbox=sandbox,
|
621
|
+
dependency_cache=dependency_cache,
|
622
|
+
)
|
623
|
+
except steps.CompilationError as e:
|
624
|
+
e.print(
|
625
|
+
f'[error]Failed to compile item: [item]{code.path}[/item][/error]'
|
626
|
+
)
|
627
|
+
raise
|
620
628
|
|
621
629
|
assert compiled_digest.value is not None
|
622
630
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import dataclasses
|
2
2
|
import pathlib
|
3
|
+
import shutil
|
3
4
|
import tempfile
|
4
5
|
import typing
|
5
6
|
from typing import Any, Dict, List, Optional, Tuple
|
@@ -228,10 +229,10 @@ def _build_problem_statements(
|
|
228
229
|
)
|
229
230
|
issue_stack.add_issue(StatementBuildIssue(extracted_problem.problem))
|
230
231
|
continue
|
231
|
-
dest_dir =
|
232
|
+
dest_dir = pathlib.Path('.problems') / extracted_problem.problem.short_name
|
232
233
|
dest_path = dest_dir / f'statement{output_type.get_file_suffix()}'
|
233
|
-
dest_dir.mkdir(parents=True, exist_ok=True)
|
234
|
-
dest_path.write_bytes(content)
|
234
|
+
(root / dest_dir).mkdir(parents=True, exist_ok=True)
|
235
|
+
(root / dest_path).write_bytes(content)
|
235
236
|
|
236
237
|
problem_assets = (
|
237
238
|
get_relative_assets(
|
@@ -240,7 +241,7 @@ def _build_problem_statements(
|
|
240
241
|
)
|
241
242
|
+ contest_assets
|
242
243
|
)
|
243
|
-
prepare_assets(problem_assets, dest_dir)
|
244
|
+
prepare_assets(problem_assets, root / dest_dir)
|
244
245
|
|
245
246
|
res.append(dataclasses.replace(extracted_problem, built_statement=dest_path))
|
246
247
|
return res
|
@@ -393,6 +394,10 @@ def build_statement_rooted(
|
|
393
394
|
return last_content, last_output
|
394
395
|
|
395
396
|
|
397
|
+
def get_statement_build_dir(statement: ContestStatement) -> pathlib.Path:
|
398
|
+
return pathlib.Path('build') / 'statement_build' / statement.name
|
399
|
+
|
400
|
+
|
396
401
|
def build_statement(
|
397
402
|
statement: ContestStatement,
|
398
403
|
contest: Contest,
|
@@ -401,17 +406,18 @@ def build_statement(
|
|
401
406
|
custom_vars: Optional[Dict[str, Any]] = None,
|
402
407
|
install_tex: bool = False,
|
403
408
|
) -> pathlib.Path:
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
409
|
+
root = get_statement_build_dir(statement)
|
410
|
+
shutil.rmtree(root, ignore_errors=True)
|
411
|
+
root.mkdir(parents=True, exist_ok=True)
|
412
|
+
last_content, last_output = build_statement_rooted(
|
413
|
+
statement,
|
414
|
+
contest,
|
415
|
+
root,
|
416
|
+
output_type=output_type,
|
417
|
+
use_samples=use_samples,
|
418
|
+
custom_vars=custom_vars,
|
419
|
+
install_tex=install_tex,
|
420
|
+
)
|
415
421
|
|
416
422
|
statement_path = (pathlib.Path('build') / statement.name).with_suffix(
|
417
423
|
last_output.get_file_suffix()
|
@@ -252,7 +252,7 @@ execution config can be individually overridden in the language configuration.""
|
|
252
252
|
|
253
253
|
|
254
254
|
def get_app_environment_path(env: str) -> pathlib.Path:
|
255
|
-
return config.get_resources_file(pathlib.PosixPath('
|
255
|
+
return config.get_resources_file(pathlib.PosixPath('presets') / env / 'env.rbx.yml')
|
256
256
|
|
257
257
|
|
258
258
|
def get_active_environment_path() -> pathlib.Path:
|
@@ -0,0 +1,71 @@
|
|
1
|
+
from typing import List, Optional
|
2
|
+
|
3
|
+
from rich.console import Capture, Console
|
4
|
+
|
5
|
+
from rbx import console
|
6
|
+
|
7
|
+
|
8
|
+
class PossiblyCapture:
|
9
|
+
def __init__(
|
10
|
+
self, console: Console, msg: List[str], capture: Optional[Capture] = None
|
11
|
+
):
|
12
|
+
self.console = console
|
13
|
+
self.msg = msg
|
14
|
+
self.capture = capture
|
15
|
+
self.actual_capture = None
|
16
|
+
|
17
|
+
def __enter__(self):
|
18
|
+
if self.capture is not None:
|
19
|
+
return
|
20
|
+
self.actual_capture = self.console.capture()
|
21
|
+
self.actual_capture.__enter__()
|
22
|
+
return self
|
23
|
+
|
24
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
25
|
+
if self.actual_capture is not None:
|
26
|
+
self.actual_capture.__exit__(exc_type, exc_value, traceback)
|
27
|
+
self.msg.append(self.actual_capture.get())
|
28
|
+
self.actual_capture = None
|
29
|
+
|
30
|
+
|
31
|
+
class RbxException(RuntimeError):
|
32
|
+
def __init__(self):
|
33
|
+
super().__init__()
|
34
|
+
self.msg = []
|
35
|
+
self.capture = None
|
36
|
+
self.console = console.new_console()
|
37
|
+
|
38
|
+
def possibly_capture(self):
|
39
|
+
return PossiblyCapture(self.console, self.msg, self.capture)
|
40
|
+
|
41
|
+
def rule(self, *args, **kwargs):
|
42
|
+
with self.possibly_capture():
|
43
|
+
self.console.rule(*args, **kwargs)
|
44
|
+
|
45
|
+
def print(self, *args, **kwargs):
|
46
|
+
with self.possibly_capture():
|
47
|
+
self.console.print(*args, **kwargs)
|
48
|
+
|
49
|
+
def log(self, *args, **kwargs):
|
50
|
+
with self.possibly_capture():
|
51
|
+
self.console.log(*args, **kwargs)
|
52
|
+
|
53
|
+
def __enter__(self):
|
54
|
+
capture = self.console.capture()
|
55
|
+
capture.__enter__()
|
56
|
+
self.capture = capture
|
57
|
+
return self
|
58
|
+
|
59
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
60
|
+
if self.capture is not None:
|
61
|
+
self.capture.__exit__(exc_type, exc_value, traceback)
|
62
|
+
self.msg.append(self.capture.get())
|
63
|
+
self.capture = None
|
64
|
+
if exc_type is not None:
|
65
|
+
return
|
66
|
+
raise self
|
67
|
+
|
68
|
+
def __str__(self) -> str:
|
69
|
+
if not self.msg:
|
70
|
+
return ''
|
71
|
+
return ''.join(self.msg)
|
@@ -4,10 +4,12 @@ import shutil
|
|
4
4
|
from typing import Dict, List, Optional, Set
|
5
5
|
|
6
6
|
import typer
|
7
|
+
from rich.console import Console
|
7
8
|
|
8
9
|
from rbx import console
|
9
10
|
from rbx.box import checkers, package, testcase_utils, validators
|
10
11
|
from rbx.box.code import SanitizationLevel, compile_item, run_item
|
12
|
+
from rbx.box.exception import RbxException
|
11
13
|
from rbx.box.schema import (
|
12
14
|
CodeItem,
|
13
15
|
GeneratorCall,
|
@@ -37,6 +39,10 @@ from rbx.grading.steps import (
|
|
37
39
|
from rbx.utils import StatusProgress
|
38
40
|
|
39
41
|
|
42
|
+
class ValidationError(RbxException):
|
43
|
+
pass
|
44
|
+
|
45
|
+
|
40
46
|
def _compile_generator(generator: CodeItem) -> str:
|
41
47
|
return compile_item(generator, sanitized=SanitizationLevel.PREFER)
|
42
48
|
|
@@ -261,7 +267,7 @@ async def generate_standalone(
|
|
261
267
|
validator_digest: Optional[str] = None,
|
262
268
|
progress: Optional[StatusProgress] = None,
|
263
269
|
):
|
264
|
-
def _print_error_header(text: Optional[str] = None):
|
270
|
+
def _print_error_header(console: Console, text: Optional[str] = None):
|
265
271
|
prefix = 'Failed generating test'
|
266
272
|
if group_entry is not None:
|
267
273
|
prefix += (
|
@@ -271,11 +277,11 @@ async def generate_standalone(
|
|
271
277
|
if text:
|
272
278
|
suffix = f': {text}'
|
273
279
|
if spec.generator_call is not None:
|
274
|
-
console.
|
280
|
+
console.print(
|
275
281
|
f'[error]{prefix} using generator call [info]{spec.generator_call.name} {spec.generator_call.args}[/info]{suffix}[/error]'
|
276
282
|
)
|
277
283
|
else:
|
278
|
-
console.
|
284
|
+
console.print(f'[error]{prefix}{suffix}[/error]')
|
279
285
|
|
280
286
|
if spec.generator_call is not None:
|
281
287
|
call = spec.generator_call
|
@@ -333,12 +339,12 @@ async def generate_standalone(
|
|
333
339
|
validator_digest,
|
334
340
|
)
|
335
341
|
if not validation_info.ok:
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
+
with ValidationError() as err:
|
343
|
+
_print_error_header(err.console, 'failed validating testcase.')
|
344
|
+
err.print(f'[error]Message:[/error] {validation_info.message}')
|
345
|
+
err.print(
|
346
|
+
f'Testcase written at [item]{spec.copied_to.inputPath}[/item]'
|
347
|
+
)
|
342
348
|
|
343
349
|
|
344
350
|
async def generate_testcases(
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# flake8: noqa
|
2
|
+
import nest_asyncio
|
3
|
+
import sys
|
4
|
+
|
5
|
+
from rbx.box.exception import RbxException
|
6
|
+
|
7
|
+
nest_asyncio.apply()
|
8
|
+
|
9
|
+
from rbx.box.cli import app as app_cli
|
10
|
+
|
11
|
+
|
12
|
+
def app():
|
13
|
+
try:
|
14
|
+
app_cli()
|
15
|
+
except RbxException as e:
|
16
|
+
print(str(e))
|
17
|
+
sys.exit(1)
|
@@ -55,7 +55,7 @@ from rbx.box.testcase_utils import (
|
|
55
55
|
parse_interaction,
|
56
56
|
print_interaction,
|
57
57
|
)
|
58
|
-
from rbx.grading import grading_context
|
58
|
+
from rbx.grading import grading_context, steps
|
59
59
|
from rbx.grading.limits import Limits
|
60
60
|
from rbx.grading.steps import (
|
61
61
|
Evaluation,
|
@@ -90,6 +90,7 @@ class SolutionReportSkeleton(BaseModel):
|
|
90
90
|
entries: List[TestcaseEntry]
|
91
91
|
groups: List[GroupSkeleton]
|
92
92
|
limits: Dict[str, Limits]
|
93
|
+
compiled_solutions: Dict[str, str]
|
93
94
|
verification: VerificationLevel
|
94
95
|
capture_pipes: bool = False
|
95
96
|
|
@@ -125,6 +126,9 @@ class SolutionReportSkeleton(BaseModel):
|
|
125
126
|
return i
|
126
127
|
return None
|
127
128
|
|
129
|
+
def get_solution_compiled_digest(self, solution: Solution) -> str:
|
130
|
+
return self.compiled_solutions[str(solution.path)]
|
131
|
+
|
128
132
|
def get_solution_path_set(self) -> Set[str]:
|
129
133
|
return set(str(sol.path) for sol in self.solutions)
|
130
134
|
|
@@ -179,10 +183,22 @@ def get_exact_matching_solutions(expected_outcome: ExpectedOutcome) -> List[Solu
|
|
179
183
|
return res
|
180
184
|
|
181
185
|
|
186
|
+
class FailedToCompileSolutionIssue(issue_stack.Issue):
|
187
|
+
def __init__(self, solution: Solution):
|
188
|
+
self.solution = solution
|
189
|
+
|
190
|
+
def get_detailed_section(self) -> Tuple[str, ...]:
|
191
|
+
return ('solutions',)
|
192
|
+
|
193
|
+
def get_detailed_message(self) -> str:
|
194
|
+
return f'[item]{href(self.solution.path)}[/item] could not be compiled and was skipped.'
|
195
|
+
|
196
|
+
|
182
197
|
def compile_solutions(
|
183
198
|
progress: Optional[StatusProgress] = None,
|
184
199
|
tracked_solutions: Optional[Set[str]] = None,
|
185
200
|
sanitized: bool = False,
|
201
|
+
fail_if_one: bool = True,
|
186
202
|
) -> Dict[pathlib.Path, str]:
|
187
203
|
compiled_solutions = {}
|
188
204
|
|
@@ -199,6 +215,10 @@ def compile_solutions(
|
|
199
215
|
if sanitized
|
200
216
|
else SanitizationLevel.NONE,
|
201
217
|
)
|
218
|
+
except steps.CompilationError:
|
219
|
+
if fail_if_one and len(tracked_solutions) <= 1:
|
220
|
+
raise
|
221
|
+
issue_stack.add_issue(FailedToCompileSolutionIssue(solution))
|
202
222
|
except:
|
203
223
|
console.console.print(
|
204
224
|
f'[error]Failed compiling solution {href(solution.path)}.[/error]'
|
@@ -283,13 +303,48 @@ def _get_solutions_for_skeleton(
|
|
283
303
|
return solutions
|
284
304
|
|
285
305
|
|
306
|
+
def _get_compiled_solutions_for_skeleton(
|
307
|
+
tracked_solutions: Optional[Iterable[str]] = None,
|
308
|
+
progress: Optional[StatusProgress] = None,
|
309
|
+
sanitized: bool = False,
|
310
|
+
verification: VerificationLevel = VerificationLevel.NONE,
|
311
|
+
) -> Tuple[List[Solution], Dict[str, str]]:
|
312
|
+
solutions_to_compile = _get_solutions_for_skeleton(tracked_solutions, verification)
|
313
|
+
|
314
|
+
compiled_solutions = compile_solutions(
|
315
|
+
progress=progress,
|
316
|
+
tracked_solutions=set(str(solution.path) for solution in solutions_to_compile),
|
317
|
+
sanitized=sanitized,
|
318
|
+
)
|
319
|
+
|
320
|
+
# TODO: Handle solutions that failed to compile.
|
321
|
+
solutions = [
|
322
|
+
solution
|
323
|
+
for solution in solutions_to_compile
|
324
|
+
if solution.path in compiled_solutions
|
325
|
+
]
|
326
|
+
|
327
|
+
return solutions, {
|
328
|
+
str(solution_path): digest
|
329
|
+
for solution_path, digest in compiled_solutions.items()
|
330
|
+
}
|
331
|
+
|
332
|
+
|
286
333
|
def _get_report_skeleton(
|
287
334
|
tracked_solutions: Optional[Iterable[str]] = None,
|
288
335
|
verification: VerificationLevel = VerificationLevel.NONE,
|
289
336
|
timelimit_override: Optional[int] = None,
|
337
|
+
progress: Optional[StatusProgress] = None,
|
338
|
+
sanitized: bool = False,
|
290
339
|
) -> SolutionReportSkeleton:
|
291
340
|
pkg = package.find_problem_package_or_die()
|
292
|
-
|
341
|
+
|
342
|
+
solutions, compiled_solutions = _get_compiled_solutions_for_skeleton(
|
343
|
+
tracked_solutions=tracked_solutions,
|
344
|
+
verification=verification,
|
345
|
+
progress=progress,
|
346
|
+
sanitized=sanitized,
|
347
|
+
)
|
293
348
|
|
294
349
|
langs = set(find_language_name(solution) for solution in solutions)
|
295
350
|
limits = {
|
@@ -324,6 +379,7 @@ def _get_report_skeleton(
|
|
324
379
|
groups=groups,
|
325
380
|
limits=limits,
|
326
381
|
entries=entries,
|
382
|
+
compiled_solutions=compiled_solutions,
|
327
383
|
verification=verification,
|
328
384
|
capture_pipes=state.STATE.debug_logs,
|
329
385
|
)
|
@@ -340,7 +396,6 @@ def _produce_solution_items(
|
|
340
396
|
verification: VerificationLevel = VerificationLevel.NONE,
|
341
397
|
check: bool = True,
|
342
398
|
timelimit_override: Optional[int] = None,
|
343
|
-
sanitized: bool = False,
|
344
399
|
nruns: int = 0,
|
345
400
|
) -> List[EvaluationItem]:
|
346
401
|
pkg = package.find_problem_package_or_die()
|
@@ -354,12 +409,6 @@ def _produce_solution_items(
|
|
354
409
|
checker_digest = checkers.compile_checker() if check else None
|
355
410
|
interactor_digest = None
|
356
411
|
|
357
|
-
compiled_solutions = compile_solutions(
|
358
|
-
progress=progress,
|
359
|
-
tracked_solutions=skeleton.get_solution_path_set(),
|
360
|
-
sanitized=sanitized,
|
361
|
-
)
|
362
|
-
|
363
412
|
def yield_items(
|
364
413
|
solution: SolutionSkeleton, group_name: str
|
365
414
|
) -> List[EvaluationItem]:
|
@@ -367,7 +416,7 @@ def _produce_solution_items(
|
|
367
416
|
for i, eval in enumerate(
|
368
417
|
_run_solution(
|
369
418
|
solution,
|
370
|
-
|
419
|
+
skeleton.get_solution_compiled_digest(solution),
|
371
420
|
checker_digest,
|
372
421
|
solution.runs_dir,
|
373
422
|
group_name,
|
@@ -425,9 +474,11 @@ def run_solutions(
|
|
425
474
|
nruns: int = 0,
|
426
475
|
) -> RunSolutionResult:
|
427
476
|
skeleton = _get_report_skeleton(
|
428
|
-
|
477
|
+
progress=progress,
|
478
|
+
tracked_solutions=tracked_solutions,
|
429
479
|
verification=verification,
|
430
480
|
timelimit_override=timelimit_override,
|
481
|
+
sanitized=sanitized,
|
431
482
|
)
|
432
483
|
result = RunSolutionResult(
|
433
484
|
skeleton=skeleton,
|
@@ -437,7 +488,6 @@ def run_solutions(
|
|
437
488
|
verification=verification,
|
438
489
|
check=check,
|
439
490
|
timelimit_override=timelimit_override,
|
440
|
-
sanitized=sanitized,
|
441
491
|
nruns=nruns,
|
442
492
|
),
|
443
493
|
)
|
@@ -588,7 +638,6 @@ def _run_interactive_solutions(
|
|
588
638
|
progress: Optional[StatusProgress] = None,
|
589
639
|
verification: VerificationLevel = VerificationLevel.NONE,
|
590
640
|
check: bool = True,
|
591
|
-
sanitized: bool = False,
|
592
641
|
) -> Iterator[EvaluationItem]:
|
593
642
|
pkg = package.find_problem_package_or_die()
|
594
643
|
|
@@ -599,12 +648,6 @@ def _run_interactive_solutions(
|
|
599
648
|
checker_digest = checkers.compile_checker() if check else None
|
600
649
|
interactor_digest = None
|
601
650
|
|
602
|
-
compiled_solutions = compile_solutions(
|
603
|
-
progress=progress,
|
604
|
-
tracked_solutions=skeleton.get_solution_path_set(),
|
605
|
-
sanitized=sanitized,
|
606
|
-
)
|
607
|
-
|
608
651
|
if progress:
|
609
652
|
progress.update('Running solutions...')
|
610
653
|
|
@@ -614,7 +657,7 @@ def _run_interactive_solutions(
|
|
614
657
|
async def run_fn(solution=solution, output_dir=output_dir):
|
615
658
|
return await run_solution_on_testcase(
|
616
659
|
solution,
|
617
|
-
|
660
|
+
skeleton.get_solution_compiled_digest(solution),
|
618
661
|
checker_digest,
|
619
662
|
testcase,
|
620
663
|
output_dir=output_dir,
|
@@ -632,9 +675,16 @@ def _run_interactive_solutions(
|
|
632
675
|
|
633
676
|
def _get_interactive_skeleton(
|
634
677
|
tracked_solutions: Optional[Iterable[str]] = None,
|
678
|
+
progress: Optional[StatusProgress] = None,
|
679
|
+
sanitized: bool = False,
|
635
680
|
verification: VerificationLevel = VerificationLevel.NONE,
|
636
681
|
) -> SolutionReportSkeleton:
|
637
|
-
solutions =
|
682
|
+
solutions, compiled_solutions = _get_compiled_solutions_for_skeleton(
|
683
|
+
tracked_solutions,
|
684
|
+
verification=verification,
|
685
|
+
progress=progress,
|
686
|
+
sanitized=sanitized,
|
687
|
+
)
|
638
688
|
|
639
689
|
langs = set(find_language_name(solution) for solution in solutions)
|
640
690
|
limits = {
|
@@ -660,6 +710,7 @@ def _get_interactive_skeleton(
|
|
660
710
|
limits=limits,
|
661
711
|
entries=[],
|
662
712
|
verification=verification,
|
713
|
+
compiled_solutions=compiled_solutions,
|
663
714
|
capture_pipes=True,
|
664
715
|
)
|
665
716
|
|
@@ -682,8 +733,10 @@ async def run_and_print_interactive_solutions(
|
|
682
733
|
):
|
683
734
|
pkg = package.find_problem_package_or_die()
|
684
735
|
skeleton = _get_interactive_skeleton(
|
685
|
-
tracked_solutions,
|
736
|
+
tracked_solutions=tracked_solutions,
|
686
737
|
verification=verification,
|
738
|
+
sanitized=sanitized,
|
739
|
+
progress=progress,
|
687
740
|
)
|
688
741
|
|
689
742
|
should_cache = testcase_entry is not None
|
@@ -705,7 +758,6 @@ async def run_and_print_interactive_solutions(
|
|
705
758
|
progress=progress,
|
706
759
|
verification=verification,
|
707
760
|
check=check,
|
708
|
-
sanitized=sanitized,
|
709
761
|
)
|
710
762
|
|
711
763
|
for item in items:
|
@@ -37,16 +37,17 @@ class Latex:
|
|
37
37
|
self.latex = latex
|
38
38
|
|
39
39
|
def build_pdf(self, temp_dir: pathlib.Path) -> LatexResult:
|
40
|
-
temp_path =
|
40
|
+
temp_path = pathlib.Path('statement.tex')
|
41
41
|
output_path = temp_path.with_suffix('.pdf')
|
42
42
|
args = ['pdflatex', '-interaction', 'nonstopmode', str(temp_path)]
|
43
|
-
|
43
|
+
|
44
|
+
(temp_dir / temp_path).write_text(self.latex)
|
44
45
|
|
45
46
|
completed = subprocess.run(args, timeout=15, capture_output=True, cwd=temp_dir)
|
46
|
-
if completed.returncode != 0 or not output_path.exists():
|
47
|
+
if completed.returncode != 0 or not (temp_dir / output_path).exists():
|
47
48
|
return LatexResult(result=completed, pdf=None)
|
48
49
|
|
49
|
-
return LatexResult(result=completed, pdf=output_path.read_bytes())
|
50
|
+
return LatexResult(result=completed, pdf=(temp_dir / output_path).read_bytes())
|
50
51
|
|
51
52
|
|
52
53
|
def install_tex_packages(path: pathlib.Path, cwd: pathlib.Path):
|