rbx.cp 0.5.62__tar.gz → 0.5.64__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.62 → rbx_cp-0.5.64}/PKG-INFO +1 -1
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/pyproject.toml +1 -1
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/contest/build_contest_statements.py +2 -1
- rbx_cp-0.5.64/rbx/box/formatting.py +35 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/packaging/boca/upload.py +18 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/packaging/main.py +4 -3
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/setter_config.py +4 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/solutions.py +14 -11
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/statements/build_statements.py +2 -1
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/screens/run_test_explorer.py +12 -1
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/screens/test_explorer.py +14 -1
- rbx_cp-0.5.64/rbx/box/ui/widgets/interaction_box.py +59 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/widgets/test_output_box.py +11 -2
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/widgets/two_sided_test_output_box.py +4 -0
- rbx_cp-0.5.62/rbx/box/formatting.py +0 -10
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/LICENSE +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/README.md +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/annotations.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/autoenum.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/builder.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/cd.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/checkers.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/cli.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/code.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/compile.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/conftest.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/contest/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/contest/contest_package.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/contest/contest_utils.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/contest/main.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/contest/schema.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/contest/statements.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/creation.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/deferred.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/download.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/dump_schemas.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/environment.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/extensions.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/generators.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/generators_test.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/git_utils.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/header.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/lazy_importing_main.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/lazy_importing_test.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/main.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/naming.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/package.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/packaging/boca/extension.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/packaging/boca/packager.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/packaging/contest_main.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/packaging/moj/packager.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/packaging/packager.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/packaging/polygon/packager.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/packaging/polygon/polygon_api.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/packaging/polygon/test.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/packaging/polygon/upload.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/packaging/polygon/xml_schema.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/presets/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/presets/fetch.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/presets/lock_schema.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/presets/schema.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/retries.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/sanitizers/warning_stack.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/schema.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/solutions_test.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/state.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/statements/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/statements/builders.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/statements/joiners.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/statements/latex.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/statements/latex_jinja.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/statements/schema.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/stresses.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/stressing/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/stressing/finder_parser.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/stressing/generator_parser.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/tasks.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/testcase_extractors.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/testcase_utils.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/testcases/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/testcases/main.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/captured_log.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/css/app.tcss +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/main.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/screens/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/screens/build.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/screens/command.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/screens/error.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/screens/run.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/screens/run_explorer.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/screens/selector.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/utils/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/utils/run_ui.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/widgets/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/widgets/file_log.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/ui/widgets/rich_log_box.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/unit.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/validators.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/box/validators_test.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/checker.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/clone.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/config.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/conftest.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/console.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/create.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/edit.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/caching.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/conftest.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/judge/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/judge/cacher.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/judge/digester.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/judge/sandbox.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/judge/sandboxes/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/judge/sandboxes/isolate.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/judge/sandboxes/stupid_sandbox.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/judge/sandboxes/timeit.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/judge/storage.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/judge/test.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/judge/testiso.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/limits.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/processing_context.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/steps.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/steps_with_caching.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading/steps_with_caching_run_test.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/grading_utils.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/hydration.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/main.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/metadata.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/providers/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/providers/codeforces.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/providers/provider.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/checkers/boilerplate.cpp +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/default_config.json +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/default_setter_config.mac.yml +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/default_setter_config.yml +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/envs/default.rbx.yml +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/envs/isolate.rbx.yml +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/checker.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/compare.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/compile/c +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/compile/cc +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/compile/cpp +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/compile/java +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/compile/kt +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/compile/pas +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/compile/py2 +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/compile/py3 +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/interactive/c +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/interactive/cc +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/interactive/cpp +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/interactive/java +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/interactive/kt +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/interactive/py2 +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/interactive/py3 +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/interactor_compile.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/run/bkp +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/run/c +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/run/cc +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/run/cpp +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/run/java +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/run/kt +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/run/py2 +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/boca/run/py3 +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/c/compile.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/c/prep.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/c/run.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/compare.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/cpp/compile.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/cpp/prep.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/cpp/run.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/interactor_prep.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/interactor_run.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/java/compile.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/java/prep.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/java/run.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/py2/compile.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/py2/prep.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/py2/run.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/py3/compile.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/py3/prep.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/packagers/moj/scripts/py3/run.sh +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/contest/contest.rbx.yml +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/contest/statement/contest.rbx.tex +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/contest/statement/olymp.sty +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/contest/statement/template.rbx.tex +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/preset.rbx.yml +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/.gitignore +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/gen.cpp +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/problem.rbx.yml +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/random.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/random.txt +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/sols/main.cpp +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/sols/slow.cpp +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/sols/wa.cpp +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/statement/olymp.sty +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/statement/projecao.png +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/statement/statement.rbx.tex +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/statement/template.rbx.tex +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/tests/samples/000.in +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/tests/samples/001.in +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/validator.cpp +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/presets/default/problem/wcmp.cpp +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/templates/rbx.h +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/resources/templates/template.cpp +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/run.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/schema.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/submit.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/submitors/__init__.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/submitors/codeforces.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/submitors/submitor.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/test.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/testcase.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/testcase_rendering.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/testing_utils.py +0 -0
- {rbx_cp-0.5.62 → rbx_cp-0.5.64}/rbx/utils.py +0 -0
@@ -10,6 +10,7 @@ from rbx import console, testing_utils
|
|
10
10
|
from rbx.box import cd, package
|
11
11
|
from rbx.box.contest.contest_package import get_problems
|
12
12
|
from rbx.box.contest.schema import Contest, ContestProblem, ContestStatement
|
13
|
+
from rbx.box.formatting import href
|
13
14
|
from rbx.box.schema import Package, Testcase
|
14
15
|
from rbx.box.statements import build_statements
|
15
16
|
from rbx.box.statements.build_statements import (
|
@@ -344,6 +345,6 @@ def build_statement(
|
|
344
345
|
console.console.print(
|
345
346
|
f'Statement built successfully for language '
|
346
347
|
f'[item]{statement.language}[/item] at '
|
347
|
-
f'
|
348
|
+
f'{href(statement_path)}'
|
348
349
|
)
|
349
350
|
return statement_path
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import os
|
2
|
+
import pathlib
|
3
|
+
from typing import Optional
|
4
|
+
|
5
|
+
from rbx.box import setter_config
|
6
|
+
|
7
|
+
|
8
|
+
def href(url: os.PathLike[str], text: Optional[str] = None, style: str = 'item') -> str:
|
9
|
+
custom_text = False
|
10
|
+
if text is None:
|
11
|
+
text = str(url)
|
12
|
+
else:
|
13
|
+
custom_text = True
|
14
|
+
|
15
|
+
if not custom_text:
|
16
|
+
if not setter_config.get_setter_config().hyperlinks:
|
17
|
+
return f'[{style}]{text}[/{style}]'
|
18
|
+
if os.environ.get('TERM') in ['vscode']:
|
19
|
+
return f'[{style}]{text}[/{style}]'
|
20
|
+
|
21
|
+
if isinstance(url, pathlib.Path):
|
22
|
+
url = url.resolve()
|
23
|
+
return f'[{style}][link={url}]{text}[/link][/{style}]'
|
24
|
+
|
25
|
+
|
26
|
+
def get_formatted_memory(memory_in_bytes: int, mib_decimal_places: int = 0) -> str:
|
27
|
+
if memory_in_bytes < 1024 * 1024:
|
28
|
+
if memory_in_bytes < 1024:
|
29
|
+
return f'{memory_in_bytes} B'
|
30
|
+
return f'{memory_in_bytes / 1024:.0f} KiB'
|
31
|
+
return f'{memory_in_bytes / (1024 * 1024):.{mib_decimal_places}f} MiB'
|
32
|
+
|
33
|
+
|
34
|
+
def get_formatted_time(time_in_ms: int) -> str:
|
35
|
+
return f'{time_in_ms} ms'
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import datetime
|
2
|
+
import functools
|
2
3
|
import hashlib
|
3
4
|
import os
|
4
5
|
import pathlib
|
@@ -41,6 +42,8 @@ class BocaUploader:
|
|
41
42
|
self.username = _parse_env_var('BOCA_USERNAME', username)
|
42
43
|
self.password = _parse_env_var('BOCA_PASSWORD', password)
|
43
44
|
|
45
|
+
self.loggedIn = False
|
46
|
+
|
44
47
|
self.br = mechanize.Browser()
|
45
48
|
self.br.set_handle_robots(False)
|
46
49
|
self.br.addheaders = [ # type: ignore
|
@@ -140,6 +143,9 @@ class BocaUploader:
|
|
140
143
|
return self.log_response_alert(response, error_msg)
|
141
144
|
|
142
145
|
def login(self):
|
146
|
+
if self.loggedIn:
|
147
|
+
return
|
148
|
+
|
143
149
|
_, html = self.open(
|
144
150
|
f'{self.base_url}', error_msg='Error while opening BOCA login page'
|
145
151
|
)
|
@@ -157,6 +163,8 @@ class BocaUploader:
|
|
157
163
|
login_url = f'{self.base_url}?name={self.username}&password={pwd_hash}'
|
158
164
|
self.open(login_url, error_msg='Error while logging in to BOCA')
|
159
165
|
|
166
|
+
self.loggedIn = True
|
167
|
+
|
160
168
|
def upload(self, file: pathlib.Path) -> bool:
|
161
169
|
self.open(
|
162
170
|
f'{self.base_url}/admin/problem.php',
|
@@ -226,6 +234,7 @@ class BocaUploader:
|
|
226
234
|
console.console.print(
|
227
235
|
f'[warning]Potentially transient error while uploading problem to BOCA. Retrying ({tries}/{RETRIES})...[/warning]'
|
228
236
|
)
|
237
|
+
self.loggedIn = False
|
229
238
|
continue
|
230
239
|
|
231
240
|
ok = True
|
@@ -245,3 +254,12 @@ class BocaUploader:
|
|
245
254
|
'[warning]Check [item]https://www.php.net/manual/en/ini.core.php#ini.sect.file-uploads[/item] for more information.[/warning]'
|
246
255
|
)
|
247
256
|
raise typer.Exit(1)
|
257
|
+
|
258
|
+
|
259
|
+
@functools.lru_cache
|
260
|
+
def get_boca_uploader(
|
261
|
+
base_url: Optional[str] = None,
|
262
|
+
username: Optional[str] = None,
|
263
|
+
password: Optional[str] = None,
|
264
|
+
) -> BocaUploader:
|
265
|
+
return BocaUploader(base_url, username, password)
|
@@ -7,6 +7,7 @@ import typer
|
|
7
7
|
|
8
8
|
from rbx import annotations, console
|
9
9
|
from rbx.box import environment, header, package
|
10
|
+
from rbx.box.formatting import href
|
10
11
|
from rbx.box.naming import get_problem_name_with_contest_info
|
11
12
|
from rbx.box.package import get_build_path
|
12
13
|
from rbx.box.packaging.packager import BasePackager, BuiltStatement
|
@@ -62,7 +63,7 @@ async def run_packager(
|
|
62
63
|
console.console.print(
|
63
64
|
f'[success]Problem packaged for [item]{packager.name()}[/item]![/success]'
|
64
65
|
)
|
65
|
-
console.console.print(f'Package was saved at
|
66
|
+
console.console.print(f'Package was saved at {href(result_path)}')
|
66
67
|
return result_path
|
67
68
|
|
68
69
|
|
@@ -105,9 +106,9 @@ async def boca(
|
|
105
106
|
result_path = await run_packager(BocaPackager, verification=verification)
|
106
107
|
|
107
108
|
if upload:
|
108
|
-
from rbx.box.packaging.boca.upload import
|
109
|
+
from rbx.box.packaging.boca.upload import get_boca_uploader
|
109
110
|
|
110
|
-
uploader =
|
111
|
+
uploader = get_boca_uploader()
|
111
112
|
uploader.login_and_upload(result_path)
|
112
113
|
|
113
114
|
|
@@ -71,6 +71,10 @@ class SetterConfig(BaseModel):
|
|
71
71
|
default={},
|
72
72
|
description='Substitutions to apply to commands before running them.',
|
73
73
|
)
|
74
|
+
hyperlinks: bool = Field(
|
75
|
+
default=True,
|
76
|
+
description='Whether to use hyperlinks in the terminal output.',
|
77
|
+
)
|
74
78
|
|
75
79
|
def substitute_command(self, command: str, sanitized: bool = False) -> str:
|
76
80
|
exe = shlex.split(command)[0]
|
@@ -16,7 +16,7 @@ import typer
|
|
16
16
|
from pydantic import BaseModel
|
17
17
|
|
18
18
|
from rbx import console, utils
|
19
|
-
from rbx.box import checkers, environment, package
|
19
|
+
from rbx.box import checkers, environment, package, state
|
20
20
|
from rbx.box.code import (
|
21
21
|
SanitizationLevel,
|
22
22
|
compile_item,
|
@@ -26,7 +26,7 @@ from rbx.box.deferred import Deferred
|
|
26
26
|
from rbx.box.environment import (
|
27
27
|
VerificationLevel,
|
28
28
|
)
|
29
|
-
from rbx.box.formatting import get_formatted_memory, get_formatted_time
|
29
|
+
from rbx.box.formatting import get_formatted_memory, get_formatted_time, href
|
30
30
|
from rbx.box.generators import (
|
31
31
|
GenerationMetadata,
|
32
32
|
expand_generator_call,
|
@@ -87,6 +87,7 @@ class SolutionReportSkeleton(BaseModel):
|
|
87
87
|
groups: List[GroupSkeleton]
|
88
88
|
limits: Dict[str, Limits]
|
89
89
|
verification: VerificationLevel
|
90
|
+
capture_pipes: bool = False
|
90
91
|
|
91
92
|
def find_group_skeleton(self, group_name: str) -> Optional[GroupSkeleton]:
|
92
93
|
groups = [group for group in self.groups if group.name == group_name]
|
@@ -165,7 +166,7 @@ def compile_solutions(
|
|
165
166
|
):
|
166
167
|
continue
|
167
168
|
if progress:
|
168
|
-
progress.update(f'Compiling solution
|
169
|
+
progress.update(f'Compiling solution {href(solution.path)}...')
|
169
170
|
try:
|
170
171
|
compiled_solutions[solution.path] = compile_item(
|
171
172
|
solution,
|
@@ -175,7 +176,7 @@ def compile_solutions(
|
|
175
176
|
)
|
176
177
|
except:
|
177
178
|
console.console.print(
|
178
|
-
f'[error]Failed compiling solution
|
179
|
+
f'[error]Failed compiling solution {href(solution.path)}.[/error]'
|
179
180
|
)
|
180
181
|
raise
|
181
182
|
|
@@ -203,7 +204,7 @@ def _run_solution(
|
|
203
204
|
|
204
205
|
if progress:
|
205
206
|
progress.update(
|
206
|
-
f'Running solution
|
207
|
+
f'Running solution {href(solution.path)} on test [item]{group.name}[/item] / [item]{i}[/item]...'
|
207
208
|
)
|
208
209
|
|
209
210
|
async def run_fn(i=i, testcase=testcase, output_path=output_path):
|
@@ -303,6 +304,7 @@ def _get_report_skeleton(
|
|
303
304
|
limits=limits,
|
304
305
|
entries=entries,
|
305
306
|
verification=verification,
|
307
|
+
capture_pipes=state.STATE.debug_logs,
|
306
308
|
)
|
307
309
|
|
308
310
|
skeleton_file = runs_dir / 'skeleton.yml'
|
@@ -627,6 +629,7 @@ def _get_interactive_skeleton(
|
|
627
629
|
limits=limits,
|
628
630
|
entries=[],
|
629
631
|
verification=verification,
|
632
|
+
capture_pipes=True,
|
630
633
|
)
|
631
634
|
|
632
635
|
skeleton_file = irun_dir / 'skeleton.yml'
|
@@ -1023,8 +1026,8 @@ def _print_solution_header(
|
|
1023
1026
|
solution: SolutionSkeleton,
|
1024
1027
|
console: rich.console.Console,
|
1025
1028
|
):
|
1026
|
-
console.print(f'
|
1027
|
-
console.print(f'({solution.runs_dir})')
|
1029
|
+
console.print(f'{href(solution.path)}', end=' ')
|
1030
|
+
console.print(f'({href(solution.runs_dir, style="info")})')
|
1028
1031
|
|
1029
1032
|
|
1030
1033
|
@dataclasses.dataclass
|
@@ -1049,14 +1052,14 @@ class TimingSummary:
|
|
1049
1052
|
def print(self, console: rich.console.Console, tl: Optional[int] = None):
|
1050
1053
|
if self.slowest_good is not None:
|
1051
1054
|
console.print(
|
1052
|
-
f'Slowest [success]OK[/success] solution: {self.slowest_good.time} ms,
|
1055
|
+
f'Slowest [success]OK[/success] solution: {self.slowest_good.time} ms, {href(self.slowest_good.solution.path)}'
|
1053
1056
|
)
|
1054
1057
|
if self.fastest_slow is not None:
|
1055
1058
|
fastest_slow = self.fastest_slow.time
|
1056
1059
|
if tl is not None and self.fastest_slow.time > tl:
|
1057
1060
|
fastest_slow = f'>{tl}'
|
1058
1061
|
console.print(
|
1059
|
-
f'Fastest [error]slow[/error] solution: {fastest_slow} ms,
|
1062
|
+
f'Fastest [error]slow[/error] solution: {fastest_slow} ms, {href(self.fastest_slow.solution.path)}'
|
1060
1063
|
)
|
1061
1064
|
|
1062
1065
|
|
@@ -1181,7 +1184,7 @@ async def _render_detailed_group_table(
|
|
1181
1184
|
) -> rich.table.Table:
|
1182
1185
|
table = rich.table.Table()
|
1183
1186
|
for solution in skeleton.solutions:
|
1184
|
-
table.add_column(f'
|
1187
|
+
table.add_column(f'{href(solution.path)}', justify='full')
|
1185
1188
|
|
1186
1189
|
padded_rows = []
|
1187
1190
|
|
@@ -1421,7 +1424,7 @@ async def estimate_time_limit(
|
|
1421
1424
|
|
1422
1425
|
if not timings:
|
1423
1426
|
console.print(
|
1424
|
-
f'[warning]No timings for solution
|
1427
|
+
f'[warning]No timings for solution {href(solution.path)}.[/warning]'
|
1425
1428
|
)
|
1426
1429
|
continue
|
1427
1430
|
|
@@ -8,6 +8,7 @@ import typer
|
|
8
8
|
|
9
9
|
from rbx import annotations, console
|
10
10
|
from rbx.box import environment, naming, package
|
11
|
+
from rbx.box.formatting import href
|
11
12
|
from rbx.box.schema import Package
|
12
13
|
from rbx.box.statements.builders import (
|
13
14
|
BUILDER_LIST,
|
@@ -302,7 +303,7 @@ def build_statement(
|
|
302
303
|
console.console.print(
|
303
304
|
f'Statement built successfully for language '
|
304
305
|
f'[item]{statement.language}[/item] at '
|
305
|
-
f'
|
306
|
+
f'{href(statement_path)}'
|
306
307
|
)
|
307
308
|
return statement_path
|
308
309
|
|
@@ -7,6 +7,7 @@ from textual.screen import Screen
|
|
7
7
|
from textual.widgets import Footer, Header, Label, ListItem, ListView
|
8
8
|
|
9
9
|
from rbx.box import package
|
10
|
+
from rbx.box.schema import TaskType
|
10
11
|
from rbx.box.solutions import SolutionReportSkeleton, SolutionSkeleton
|
11
12
|
from rbx.box.testcase_extractors import (
|
12
13
|
GenerationTestcaseEntry,
|
@@ -64,6 +65,9 @@ class RunTestExplorerScreen(Screen):
|
|
64
65
|
self.query_one('#test-list').border_title = 'Tests'
|
65
66
|
self.query_one('#test-input').border_title = 'Input'
|
66
67
|
|
68
|
+
# Ensure the output is show, even for interactive tests
|
69
|
+
self.action_show_output()
|
70
|
+
|
67
71
|
await self._update_tests()
|
68
72
|
|
69
73
|
def _get_rendering_data(
|
@@ -118,8 +122,15 @@ class RunTestExplorerScreen(Screen):
|
|
118
122
|
def has_diffable_solution(self) -> bool:
|
119
123
|
return self.diff_solution is not None or package.get_main_solution() is not None
|
120
124
|
|
125
|
+
def should_show_interaction(self) -> bool:
|
126
|
+
pkg = package.find_problem_package_or_die()
|
127
|
+
return pkg.type == TaskType.COMMUNICATION and self.skeleton.capture_pipes
|
128
|
+
|
121
129
|
def action_show_output(self):
|
122
|
-
self.
|
130
|
+
if self.should_show_interaction():
|
131
|
+
self.query_one('#test-output', TwoSidedTestBoxWidget).show_interaction()
|
132
|
+
else:
|
133
|
+
self.query_one('#test-output', TwoSidedTestBoxWidget).show_output()
|
123
134
|
|
124
135
|
def action_show_stderr(self):
|
125
136
|
self.query_one('#test-output', TwoSidedTestBoxWidget).show_stderr()
|
@@ -5,6 +5,8 @@ from textual.containers import Horizontal, Vertical
|
|
5
5
|
from textual.screen import Screen
|
6
6
|
from textual.widgets import Footer, Header, Label, ListItem, ListView, RichLog
|
7
7
|
|
8
|
+
from rbx.box import package
|
9
|
+
from rbx.box.schema import TaskType
|
8
10
|
from rbx.box.testcase_extractors import (
|
9
11
|
GenerationTestcaseEntry,
|
10
12
|
extract_generation_testcases_from_groups,
|
@@ -42,6 +44,9 @@ class TestExplorerScreen(Screen):
|
|
42
44
|
self.query_one('#test-list').border_title = 'Tests'
|
43
45
|
self.query_one('#test-input').border_title = 'Input'
|
44
46
|
|
47
|
+
# Ensure either output or interaction is visible.
|
48
|
+
self.action_show_output()
|
49
|
+
|
45
50
|
metadata = self.query_one('#test-metadata', RichLogBox)
|
46
51
|
metadata.display = False
|
47
52
|
metadata.border_title = 'Metadata'
|
@@ -67,6 +72,7 @@ class TestExplorerScreen(Screen):
|
|
67
72
|
entry = self._entries[index]
|
68
73
|
input.path = entry.metadata.copied_to.inputPath
|
69
74
|
|
75
|
+
assert entry.metadata.copied_to.outputPath is not None
|
70
76
|
output.data = TestcaseRenderingData.from_one_path(
|
71
77
|
entry.metadata.copied_to.outputPath
|
72
78
|
)
|
@@ -105,8 +111,15 @@ class TestExplorerScreen(Screen):
|
|
105
111
|
[ListItem(Label(name)) for name in test_names]
|
106
112
|
)
|
107
113
|
|
114
|
+
def is_interactive(self) -> bool:
|
115
|
+
pkg = package.find_problem_package_or_die()
|
116
|
+
return pkg.type == TaskType.COMMUNICATION
|
117
|
+
|
108
118
|
def action_show_output(self):
|
109
|
-
self.
|
119
|
+
if self.is_interactive():
|
120
|
+
self.query_one('#test-output', TestBoxWidget).show_interaction()
|
121
|
+
else:
|
122
|
+
self.query_one('#test-output', TestBoxWidget).show_output()
|
110
123
|
|
111
124
|
def action_show_stderr(self):
|
112
125
|
self.query_one('#test-output', TestBoxWidget).show_stderr()
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import asyncio
|
2
|
+
import pathlib
|
3
|
+
from typing import Optional
|
4
|
+
|
5
|
+
import rich.text
|
6
|
+
from textual import work
|
7
|
+
from textual.reactive import reactive
|
8
|
+
|
9
|
+
from rbx.box import testcase_utils
|
10
|
+
from rbx.box.ui.widgets.rich_log_box import RichLogBox
|
11
|
+
|
12
|
+
BATCH_SIZE = 1024
|
13
|
+
|
14
|
+
|
15
|
+
class InteractionBox(RichLogBox):
|
16
|
+
DEFAULT_CSS = """
|
17
|
+
InteractionBox {
|
18
|
+
border: solid $accent;
|
19
|
+
height: 1fr;
|
20
|
+
width: 1fr;
|
21
|
+
}
|
22
|
+
"""
|
23
|
+
|
24
|
+
path: reactive[Optional[pathlib.Path]] = reactive(None)
|
25
|
+
|
26
|
+
def on_mount(self):
|
27
|
+
super().on_mount()
|
28
|
+
self.auto_scroll = False
|
29
|
+
self.can_focus = False
|
30
|
+
|
31
|
+
@work(exclusive=True)
|
32
|
+
async def _load_file(self, path: pathlib.Path):
|
33
|
+
self.clear()
|
34
|
+
path_str = str(path.relative_to(pathlib.Path.cwd()))
|
35
|
+
self.border_subtitle = f'{path_str} (loading...)'
|
36
|
+
|
37
|
+
interaction = await asyncio.to_thread(testcase_utils.parse_interaction, path)
|
38
|
+
|
39
|
+
for entry in interaction.entries:
|
40
|
+
if entry.pipe == 0:
|
41
|
+
self.write(rich.text.Text(entry.data.rstrip(), style='green'))
|
42
|
+
else:
|
43
|
+
self.write(rich.text.Text(entry.data.rstrip()))
|
44
|
+
|
45
|
+
self.border_subtitle = path_str
|
46
|
+
|
47
|
+
async def watch_path(self, path: Optional[pathlib.Path]):
|
48
|
+
self.clear()
|
49
|
+
|
50
|
+
if path is None:
|
51
|
+
self.border_subtitle = '(no file selected)'
|
52
|
+
return
|
53
|
+
|
54
|
+
if not path.is_file():
|
55
|
+
path_str = str(path.relative_to(pathlib.Path.cwd()))
|
56
|
+
self.border_subtitle = f'{path_str} (does not exist)'
|
57
|
+
return
|
58
|
+
|
59
|
+
self._load_file(path)
|
@@ -9,6 +9,7 @@ from textual.widget import Widget
|
|
9
9
|
from textual.widgets import ContentSwitcher
|
10
10
|
|
11
11
|
from rbx.box.ui.widgets.file_log import FileLog
|
12
|
+
from rbx.box.ui.widgets.interaction_box import InteractionBox
|
12
13
|
from rbx.box.ui.widgets.rich_log_box import RichLogBox
|
13
14
|
|
14
15
|
|
@@ -17,6 +18,7 @@ class TestcaseRenderingData:
|
|
17
18
|
input_path: Optional[pathlib.Path] = None
|
18
19
|
output_path: Optional[pathlib.Path] = None
|
19
20
|
stderr_path: Optional[pathlib.Path] = None
|
21
|
+
interaction_path: Optional[pathlib.Path] = None
|
20
22
|
log_path: Optional[pathlib.Path] = None
|
21
23
|
rich_content: Optional[str] = None
|
22
24
|
|
@@ -27,6 +29,7 @@ class TestcaseRenderingData:
|
|
27
29
|
output_path=path.with_suffix('.out'),
|
28
30
|
stderr_path=path.with_suffix('.err'),
|
29
31
|
log_path=path.with_suffix('.log'),
|
32
|
+
interaction_path=path.with_suffix('.pio'),
|
30
33
|
)
|
31
34
|
|
32
35
|
|
@@ -41,12 +44,14 @@ class TestBoxWidget(Widget, can_focus=False):
|
|
41
44
|
output: FileLog
|
42
45
|
stderr: FileLog
|
43
46
|
log: FileLog
|
47
|
+
interaction: FileLog
|
44
48
|
|
45
49
|
def logs(self) -> Logs:
|
46
50
|
return self.Logs(
|
47
51
|
output=self.query_one('#test-box-output', FileLog),
|
48
52
|
stderr=self.query_one('#test-box-stderr', FileLog),
|
49
53
|
log=self.query_one('#test-box-log', FileLog),
|
54
|
+
interaction=self.query_one('#test-box-interaction', InteractionBox),
|
50
55
|
)
|
51
56
|
|
52
57
|
def compose(self) -> ComposeResult:
|
@@ -55,6 +60,7 @@ class TestBoxWidget(Widget, can_focus=False):
|
|
55
60
|
yield FileLog(id='test-box-output')
|
56
61
|
yield FileLog(id='test-box-stderr')
|
57
62
|
yield FileLog(id='test-box-log')
|
63
|
+
yield InteractionBox(id='test-box-interaction')
|
58
64
|
yield RichLogBox(id='test-box-metadata')
|
59
65
|
|
60
66
|
def on_mount(self):
|
@@ -62,7 +68,7 @@ class TestBoxWidget(Widget, can_focus=False):
|
|
62
68
|
logs.output.border_title = 'Output'
|
63
69
|
logs.stderr.border_title = 'Stderr'
|
64
70
|
logs.log.border_title = 'Log'
|
65
|
-
|
71
|
+
logs.interaction.border_title = 'Interaction'
|
66
72
|
metadata = self.query_one('#test-box-metadata', RichLogBox)
|
67
73
|
metadata.display = False
|
68
74
|
metadata.border_title = 'Metadata'
|
@@ -78,7 +84,7 @@ class TestBoxWidget(Widget, can_focus=False):
|
|
78
84
|
logs.output.path = data.output_path
|
79
85
|
logs.stderr.path = data.stderr_path
|
80
86
|
logs.log.path = data.log_path
|
81
|
-
|
87
|
+
logs.interaction.path = data.interaction_path
|
82
88
|
metadata = self.query_one('#test-box-metadata', RichLogBox)
|
83
89
|
metadata.clear()
|
84
90
|
if data.rich_content is not None:
|
@@ -98,6 +104,9 @@ class TestBoxWidget(Widget, can_focus=False):
|
|
98
104
|
def show_log(self):
|
99
105
|
self.query_one(ContentSwitcher).current = 'test-box-log'
|
100
106
|
|
107
|
+
def show_interaction(self):
|
108
|
+
self.query_one(ContentSwitcher).current = 'test-box-interaction'
|
109
|
+
|
101
110
|
def toggle_metadata(self):
|
102
111
|
metadata = self.query_one('#test-box-metadata', RichLogBox)
|
103
112
|
metadata.display = not metadata.display
|
@@ -51,6 +51,10 @@ class TwoSidedTestBoxWidget(Widget, can_focus=False):
|
|
51
51
|
self.query_one('#test-box-1', TestBoxWidget).show_log()
|
52
52
|
self.query_one('#test-box-2', TestBoxWidget).show_log()
|
53
53
|
|
54
|
+
def show_interaction(self):
|
55
|
+
self.query_one('#test-box-1', TestBoxWidget).show_interaction()
|
56
|
+
self.query_one('#test-box-2', TestBoxWidget).show_interaction()
|
57
|
+
|
54
58
|
def toggle_metadata(self):
|
55
59
|
self.query_one('#test-box-1', TestBoxWidget).toggle_metadata()
|
56
60
|
self.query_one('#test-box-2', TestBoxWidget).toggle_metadata()
|
@@ -1,10 +0,0 @@
|
|
1
|
-
def get_formatted_memory(memory_in_bytes: int, mib_decimal_places: int = 0) -> str:
|
2
|
-
if memory_in_bytes < 1024 * 1024:
|
3
|
-
if memory_in_bytes < 1024:
|
4
|
-
return f'{memory_in_bytes} B'
|
5
|
-
return f'{memory_in_bytes / 1024:.0f} KiB'
|
6
|
-
return f'{memory_in_bytes / (1024 * 1024):.{mib_decimal_places}f} MiB'
|
7
|
-
|
8
|
-
|
9
|
-
def get_formatted_time(time_in_ms: int) -> str:
|
10
|
-
return f'{time_in_ms} ms'
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|