rbx.cp 0.5.64__tar.gz → 0.5.66__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.64 → rbx_cp-0.5.66}/PKG-INFO +1 -1
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/pyproject.toml +1 -1
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/cli.py +30 -13
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/formatting.py +5 -1
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/package.py +13 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/packaging/boca/upload.py +39 -1
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/solutions.py +95 -16
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/testcase_utils.py +6 -1
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/css/app.tcss +14 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/main.py +21 -0
- rbx_cp-0.5.66/rbx/box/ui/screens/differ.py +29 -0
- rbx_cp-0.5.66/rbx/box/ui/widgets/diff_box.py +38 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/unit.py +0 -2
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/LICENSE +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/README.md +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/annotations.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/autoenum.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/builder.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/cd.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/checkers.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/code.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/compile.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/conftest.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/contest/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/contest/build_contest_statements.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/contest/contest_package.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/contest/contest_utils.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/contest/main.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/contest/schema.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/contest/statements.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/creation.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/deferred.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/download.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/dump_schemas.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/environment.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/extensions.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/generators.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/generators_test.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/git_utils.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/header.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/lazy_importing_main.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/lazy_importing_test.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/main.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/naming.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/packaging/boca/extension.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/packaging/boca/packager.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/packaging/contest_main.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/packaging/main.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/packaging/moj/packager.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/packaging/packager.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/packaging/polygon/packager.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/packaging/polygon/polygon_api.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/packaging/polygon/test.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/packaging/polygon/upload.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/packaging/polygon/xml_schema.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/presets/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/presets/fetch.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/presets/lock_schema.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/presets/schema.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/retries.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/sanitizers/warning_stack.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/schema.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/setter_config.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/solutions_test.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/state.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/statements/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/statements/build_statements.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/statements/builders.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/statements/joiners.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/statements/latex.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/statements/latex_jinja.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/statements/schema.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/stresses.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/stressing/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/stressing/finder_parser.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/stressing/generator_parser.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/tasks.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/testcase_extractors.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/testcases/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/testcases/main.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/captured_log.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/screens/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/screens/build.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/screens/command.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/screens/error.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/screens/run.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/screens/run_explorer.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/screens/run_test_explorer.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/screens/selector.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/screens/test_explorer.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/utils/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/utils/run_ui.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/widgets/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/widgets/file_log.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/widgets/interaction_box.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/widgets/rich_log_box.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/widgets/test_output_box.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/ui/widgets/two_sided_test_output_box.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/validators.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/box/validators_test.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/checker.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/clone.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/config.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/conftest.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/console.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/create.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/edit.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/caching.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/conftest.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/judge/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/judge/cacher.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/judge/digester.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/judge/sandbox.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/judge/sandboxes/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/judge/sandboxes/isolate.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/judge/sandboxes/stupid_sandbox.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/judge/sandboxes/timeit.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/judge/storage.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/judge/test.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/judge/testiso.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/limits.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/processing_context.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/steps.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/steps_with_caching.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading/steps_with_caching_run_test.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/grading_utils.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/hydration.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/main.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/metadata.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/providers/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/providers/codeforces.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/providers/provider.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/checkers/boilerplate.cpp +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/default_config.json +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/default_setter_config.mac.yml +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/default_setter_config.yml +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/envs/default.rbx.yml +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/envs/isolate.rbx.yml +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/checker.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/compare.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/compile/c +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/compile/cc +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/compile/cpp +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/compile/java +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/compile/kt +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/compile/pas +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/compile/py2 +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/compile/py3 +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/interactive/c +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/interactive/cc +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/interactive/cpp +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/interactive/java +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/interactive/kt +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/interactive/py2 +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/interactive/py3 +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/interactor_compile.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/run/bkp +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/run/c +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/run/cc +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/run/cpp +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/run/java +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/run/kt +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/run/py2 +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/boca/run/py3 +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/c/compile.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/c/prep.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/c/run.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/compare.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/cpp/compile.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/cpp/prep.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/cpp/run.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/interactor_prep.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/interactor_run.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/java/compile.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/java/prep.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/java/run.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/py2/compile.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/py2/prep.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/py2/run.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/py3/compile.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/py3/prep.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/packagers/moj/scripts/py3/run.sh +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/contest/contest.rbx.yml +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/contest/statement/contest.rbx.tex +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/contest/statement/olymp.sty +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/contest/statement/template.rbx.tex +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/preset.rbx.yml +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/.gitignore +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/gen.cpp +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/problem.rbx.yml +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/random.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/random.txt +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/sols/main.cpp +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/sols/slow.cpp +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/sols/wa.cpp +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/statement/olymp.sty +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/statement/projecao.png +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/statement/statement.rbx.tex +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/statement/template.rbx.tex +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/tests/samples/000.in +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/tests/samples/001.in +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/validator.cpp +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/presets/default/problem/wcmp.cpp +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/templates/rbx.h +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/resources/templates/template.cpp +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/run.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/schema.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/submit.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/submitors/__init__.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/submitors/codeforces.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/submitors/submitor.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/test.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/testcase.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/testcase_rendering.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/testing_utils.py +0 -0
- {rbx_cp-0.5.64 → rbx_cp-0.5.66}/rbx/utils.py +0 -0
@@ -3,7 +3,7 @@ import shlex
|
|
3
3
|
import shutil
|
4
4
|
import sys
|
5
5
|
import tempfile
|
6
|
-
from typing import Annotated, Optional
|
6
|
+
from typing import Annotated, List, Optional
|
7
7
|
|
8
8
|
import rich
|
9
9
|
import rich.prompt
|
@@ -136,6 +136,13 @@ def ui():
|
|
136
136
|
ui_pkg.start()
|
137
137
|
|
138
138
|
|
139
|
+
@app.command('diff', hidden=True)
|
140
|
+
def diff(path1: pathlib.Path, path2: pathlib.Path):
|
141
|
+
from rbx.box.ui import main as ui_pkg
|
142
|
+
|
143
|
+
ui_pkg.start_differ(path1, path2)
|
144
|
+
|
145
|
+
|
139
146
|
@app.command('serve', hidden=True)
|
140
147
|
def serve():
|
141
148
|
from textual_serve.server import Server
|
@@ -178,10 +185,10 @@ async def build(verification: environment.VerificationParam):
|
|
178
185
|
@syncer.sync
|
179
186
|
async def run(
|
180
187
|
verification: environment.VerificationParam,
|
181
|
-
|
182
|
-
Optional[str],
|
188
|
+
solutions: Annotated[
|
189
|
+
Optional[List[str]],
|
183
190
|
typer.Argument(
|
184
|
-
help='Path to
|
191
|
+
help='Path to solutions to run. If not specified, will run all solutions.'
|
185
192
|
),
|
186
193
|
] = None,
|
187
194
|
outcome: Optional[str] = typer.Option(
|
@@ -235,11 +242,16 @@ async def run(
|
|
235
242
|
str(solution.path)
|
236
243
|
for solution in get_matching_solutions(ExpectedOutcome(outcome))
|
237
244
|
}
|
238
|
-
if
|
239
|
-
tracked_solutions =
|
245
|
+
if solutions:
|
246
|
+
tracked_solutions = set(solutions)
|
240
247
|
|
241
248
|
if choice:
|
242
|
-
tracked_solutions = set(
|
249
|
+
tracked_solutions = set(
|
250
|
+
await pick_solutions(
|
251
|
+
tracked_solutions,
|
252
|
+
extra_solutions=solutions,
|
253
|
+
)
|
254
|
+
)
|
243
255
|
if not tracked_solutions:
|
244
256
|
console.console.print('[error]No solutions selected. Exiting.[/error]')
|
245
257
|
raise typer.Exit(1)
|
@@ -395,10 +407,10 @@ async def time(
|
|
395
407
|
@syncer.sync
|
396
408
|
async def irun(
|
397
409
|
verification: environment.VerificationParam,
|
398
|
-
|
399
|
-
Optional[str],
|
410
|
+
solutions: Annotated[
|
411
|
+
Optional[List[str]],
|
400
412
|
typer.Argument(
|
401
|
-
help='Path to
|
413
|
+
help='Path to solutions to run. If not specified, will run all solutions.'
|
402
414
|
),
|
403
415
|
] = None,
|
404
416
|
outcome: Optional[str] = typer.Option(
|
@@ -466,11 +478,16 @@ async def irun(
|
|
466
478
|
str(solution.path)
|
467
479
|
for solution in get_matching_solutions(ExpectedOutcome(outcome))
|
468
480
|
}
|
469
|
-
if
|
470
|
-
tracked_solutions =
|
481
|
+
if solutions:
|
482
|
+
tracked_solutions = set(solutions)
|
471
483
|
|
472
484
|
if choice:
|
473
|
-
tracked_solutions = set(
|
485
|
+
tracked_solutions = set(
|
486
|
+
await pick_solutions(
|
487
|
+
tracked_solutions,
|
488
|
+
extra_solutions=solutions,
|
489
|
+
)
|
490
|
+
)
|
474
491
|
if not tracked_solutions:
|
475
492
|
console.console.print('[error]No solutions selected. Exiting.[/error]')
|
476
493
|
raise typer.Exit(1)
|
@@ -20,7 +20,11 @@ def href(url: os.PathLike[str], text: Optional[str] = None, style: str = 'item')
|
|
20
20
|
|
21
21
|
if isinstance(url, pathlib.Path):
|
22
22
|
url = url.resolve()
|
23
|
-
|
23
|
+
|
24
|
+
url_str = str(url)
|
25
|
+
if pathlib.Path(url_str).exists():
|
26
|
+
url_str = f'file://{url_str}'
|
27
|
+
return f'[{style}][link={url_str}]{text}[/link][/{style}]'
|
24
28
|
|
25
29
|
|
26
30
|
def get_formatted_memory(memory_in_bytes: int, mib_decimal_places: int = 0) -> str:
|
@@ -150,6 +150,19 @@ def get_problem_cache_dir(root: pathlib.Path = pathlib.Path()) -> pathlib.Path:
|
|
150
150
|
return cache_dir
|
151
151
|
|
152
152
|
|
153
|
+
@functools.cache
|
154
|
+
def get_problem_remote_dir(
|
155
|
+
platform: Optional[str] = None, root: pathlib.Path = pathlib.Path()
|
156
|
+
) -> pathlib.Path:
|
157
|
+
remote_dir = get_problem_cache_dir(root) / '.remote'
|
158
|
+
remote_dir.mkdir(parents=True, exist_ok=True)
|
159
|
+
|
160
|
+
if platform is not None:
|
161
|
+
remote_dir = remote_dir / platform
|
162
|
+
remote_dir.mkdir(parents=True, exist_ok=True)
|
163
|
+
return remote_dir
|
164
|
+
|
165
|
+
|
153
166
|
@functools.cache
|
154
167
|
def get_problem_storage_dir(root: pathlib.Path = pathlib.Path()) -> pathlib.Path:
|
155
168
|
storage_dir = get_problem_cache_dir(root) / '.storage'
|
@@ -4,6 +4,7 @@ import hashlib
|
|
4
4
|
import os
|
5
5
|
import pathlib
|
6
6
|
import re
|
7
|
+
import shutil
|
7
8
|
import typing
|
8
9
|
from typing import Any, NoReturn, Optional, Tuple
|
9
10
|
|
@@ -248,13 +249,50 @@ class BocaUploader:
|
|
248
249
|
'[error]Persistent error while uploading problem to BOCA website.[/error]'
|
249
250
|
)
|
250
251
|
console.console.print(
|
251
|
-
'[warning]This might be caused by PHP max upload size limit (which usually defaults to
|
252
|
+
'[warning]This might be caused by PHP max upload size limit (which usually defaults to 2MB).[/warning]'
|
252
253
|
)
|
253
254
|
console.console.print(
|
254
255
|
'[warning]Check [item]https://www.php.net/manual/en/ini.core.php#ini.sect.file-uploads[/item] for more information.[/warning]'
|
255
256
|
)
|
256
257
|
raise typer.Exit(1)
|
257
258
|
|
259
|
+
def download_run(self, run_number: int, site_number: int, into_dir: pathlib.Path):
|
260
|
+
url = f'{self.base_url}/admin/runedit.php?runnumber={run_number}&runsitenumber={site_number}'
|
261
|
+
_, html = self.open(
|
262
|
+
url,
|
263
|
+
error_msg=f'Error while downloading BOCA run [item]{run_number}-{site_number}[/item]',
|
264
|
+
)
|
265
|
+
|
266
|
+
soup = BeautifulSoup(html, 'html.parser')
|
267
|
+
rows = soup.select('tr')
|
268
|
+
|
269
|
+
href: Optional[str] = None
|
270
|
+
filename: Optional[pathlib.Path] = None
|
271
|
+
|
272
|
+
for row in rows:
|
273
|
+
row_text = row.select('td')[0].text.strip().lower()
|
274
|
+
if row_text != "team's code:":
|
275
|
+
continue
|
276
|
+
link_col = row.select_one('td:nth-of-type(2) a:nth-of-type(1)')
|
277
|
+
if link_col is None:
|
278
|
+
continue
|
279
|
+
href = str(link_col.attrs['href'])
|
280
|
+
filename = pathlib.Path(link_col.text.strip())
|
281
|
+
break
|
282
|
+
|
283
|
+
if href is None or filename is None:
|
284
|
+
self.raw_error(
|
285
|
+
"Error while downloading run:\nNo link to team's code found."
|
286
|
+
)
|
287
|
+
|
288
|
+
link = self.br.find_link(url=href)
|
289
|
+
tmp_file, _ = self.br.retrieve(link.absolute_url)
|
290
|
+
if tmp_file is None:
|
291
|
+
self.raw_error('Error while downloading run:\nDownloaded file is None.')
|
292
|
+
final_path = into_dir / filename.with_stem(f'{run_number}-{site_number}')
|
293
|
+
shutil.move(tmp_file, final_path)
|
294
|
+
return final_path
|
295
|
+
|
258
296
|
|
259
297
|
@functools.lru_cache
|
260
298
|
def get_boca_uploader(
|
@@ -159,12 +159,10 @@ def compile_solutions(
|
|
159
159
|
|
160
160
|
compiled_solutions = {}
|
161
161
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
):
|
167
|
-
continue
|
162
|
+
if tracked_solutions is None:
|
163
|
+
tracked_solutions = set(str(sol.path) for sol in pkg.solutions)
|
164
|
+
|
165
|
+
for solution in expand_solutions(list(tracked_solutions)):
|
168
166
|
if progress:
|
169
167
|
progress.update(f'Compiling solution {href(solution.path)}...')
|
170
168
|
try:
|
@@ -254,11 +252,7 @@ def _get_solutions_for_skeleton(
|
|
254
252
|
if verification.value >= VerificationLevel.ALL_SOLUTIONS.value or is_fast(sol)
|
255
253
|
]
|
256
254
|
if tracked_solutions is not None:
|
257
|
-
solutions =
|
258
|
-
solution
|
259
|
-
for solution in solutions
|
260
|
-
if str(solution.path) in tracked_solutions
|
261
|
-
]
|
255
|
+
solutions = expand_solutions(list(tracked_solutions))
|
262
256
|
return solutions
|
263
257
|
|
264
258
|
|
@@ -726,20 +720,105 @@ def _get_solution_repr(sol: Solution) -> List[Tuple[str, str]]:
|
|
726
720
|
]
|
727
721
|
|
728
722
|
|
729
|
-
|
723
|
+
# TODO: refactor this function
|
724
|
+
def _expand_remote_sol(sol: str) -> Optional[str]:
|
725
|
+
from rbx.box.packaging.boca import upload as boca_upload
|
726
|
+
|
727
|
+
# Only BOCA supported for now.
|
728
|
+
assert sol.startswith('@')
|
729
|
+
sol = sol[1:]
|
730
|
+
if '-' in sol:
|
731
|
+
run_number, site_number = sol.split('-', 1)
|
732
|
+
run_number = int(run_number)
|
733
|
+
site_number = int(site_number)
|
734
|
+
else:
|
735
|
+
run_number = int(sol)
|
736
|
+
site_number = 1
|
737
|
+
|
738
|
+
expected_glob = (
|
739
|
+
package.get_problem_remote_dir('boca') / f'{run_number}-{site_number}.*'
|
740
|
+
)
|
741
|
+
expected_glob = expected_glob.relative_to(pathlib.Path.cwd())
|
742
|
+
for path in pathlib.Path.cwd().glob(str(expected_glob)):
|
743
|
+
if path.is_file():
|
744
|
+
relpath = path.resolve().relative_to(pathlib.Path.cwd())
|
745
|
+
console.console.print(f'Retrieving {href(relpath)} from cache...')
|
746
|
+
return str(relpath)
|
747
|
+
|
748
|
+
boca_uploader = boca_upload.get_boca_uploader()
|
749
|
+
boca_uploader.login()
|
750
|
+
sol_path = boca_uploader.download_run(
|
751
|
+
run_number, site_number, package.get_problem_remote_dir('boca')
|
752
|
+
)
|
753
|
+
console.console.print(f'Downloaded {href(sol_path)} from BOCA...')
|
754
|
+
return str(sol_path.resolve().relative_to(pathlib.Path.cwd()))
|
755
|
+
|
756
|
+
|
757
|
+
def _expand_remote_sols(sols: List[str]) -> List[str]:
|
758
|
+
res = []
|
759
|
+
for sol in sols:
|
760
|
+
if not sol.startswith('@'):
|
761
|
+
res.append(sol)
|
762
|
+
continue
|
763
|
+
expanded = _expand_remote_sol(sol)
|
764
|
+
if expanded is None:
|
765
|
+
continue
|
766
|
+
res.append(expanded)
|
767
|
+
return res
|
768
|
+
|
769
|
+
|
770
|
+
def expand_solutions(sols: List[str]) -> List[Solution]:
|
730
771
|
pkg = package.find_problem_package_or_die()
|
731
|
-
|
732
|
-
|
772
|
+
seen_sols = {str(sol.path): sol for sol in pkg.solutions}
|
773
|
+
|
774
|
+
# Download remote sols.
|
775
|
+
sols = _expand_remote_sols(sols)
|
776
|
+
|
777
|
+
# Ensure sols exist.
|
778
|
+
sols = [sol for sol in sols if pathlib.Path(sol).is_file()]
|
779
|
+
|
780
|
+
res = []
|
781
|
+
for sol in sols:
|
782
|
+
if sol in seen_sols:
|
783
|
+
res.append(seen_sols[sol])
|
784
|
+
else:
|
785
|
+
res.append(
|
786
|
+
Solution(path=pathlib.Path(sol), outcome=ExpectedOutcome.ACCEPTED)
|
787
|
+
)
|
788
|
+
return res
|
789
|
+
|
733
790
|
|
791
|
+
async def pick_solutions(
|
792
|
+
tracked_solutions: Optional[Set[str]],
|
793
|
+
extra_solutions: Optional[List[str]] = None,
|
794
|
+
) -> List[str]:
|
795
|
+
pkg = package.find_problem_package_or_die()
|
734
796
|
# Store in a separate list to maintain order with the package declaration.
|
735
797
|
import questionary
|
736
798
|
|
737
799
|
choices = [
|
738
|
-
questionary.Choice(
|
800
|
+
questionary.Choice(
|
801
|
+
title=_get_solution_repr(sol),
|
802
|
+
value=str(sol.path),
|
803
|
+
checked=tracked_solutions is None or str(sol.path) in tracked_solutions,
|
804
|
+
)
|
739
805
|
for sol in pkg.solutions
|
740
|
-
if str(sol.path) in tracked_solutions
|
741
806
|
]
|
742
807
|
|
808
|
+
seen_sols = set(str(sol.path) for sol in pkg.solutions)
|
809
|
+
|
810
|
+
if extra_solutions is not None:
|
811
|
+
# Add only new solutions.
|
812
|
+
choices.extend(
|
813
|
+
questionary.Choice(
|
814
|
+
title=_get_solution_repr(sol),
|
815
|
+
value=str(sol.path),
|
816
|
+
checked=True,
|
817
|
+
)
|
818
|
+
for sol in expand_solutions(extra_solutions)
|
819
|
+
if str(sol.path) not in seen_sols
|
820
|
+
)
|
821
|
+
|
743
822
|
picked = await questionary.checkbox('Select solutions', choices=choices).ask_async()
|
744
823
|
if picked is None:
|
745
824
|
raise typer.Abort()
|
@@ -172,6 +172,7 @@ def parse_interaction(file: pathlib.Path) -> TestcaseInteraction:
|
|
172
172
|
)
|
173
173
|
raise typer.Exit(1) from None
|
174
174
|
|
175
|
+
# Crop file.
|
175
176
|
rest = f.read()
|
176
177
|
start = 0
|
177
178
|
|
@@ -202,13 +203,17 @@ def parse_interaction(file: pathlib.Path) -> TestcaseInteraction:
|
|
202
203
|
nxt_start, _ = nxt
|
203
204
|
return (pipe, (prefix_end, nxt_start))
|
204
205
|
|
205
|
-
|
206
|
+
# TODO: optimize
|
207
|
+
blocks = 0
|
208
|
+
MAX_BLOCKS = 1024
|
209
|
+
while blocks < MAX_BLOCKS:
|
206
210
|
block = _find_next_block()
|
207
211
|
if block is None:
|
208
212
|
break
|
209
213
|
pipe, (st, nd) = block
|
210
214
|
entries.append(TestcaseInteractionEntry(data=rest[st:nd], pipe=pipe))
|
211
215
|
start = nd
|
216
|
+
blocks += 1
|
212
217
|
|
213
218
|
return TestcaseInteraction(
|
214
219
|
prefixes=(interactor_prefix, solution_prefix),
|
@@ -21,6 +21,20 @@ OptionList {
|
|
21
21
|
border: solid $accent;
|
22
22
|
}
|
23
23
|
|
24
|
+
DiffBox {
|
25
|
+
border: solid $accent;
|
26
|
+
height: 1fr;
|
27
|
+
width: 1fr;
|
28
|
+
Markdown {
|
29
|
+
height: 1fr;
|
30
|
+
width: 1fr;
|
31
|
+
|
32
|
+
.code_inline {
|
33
|
+
background: $background;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
24
38
|
Button {
|
25
39
|
width: 1fr;
|
26
40
|
background: $accent;
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import pathlib
|
1
2
|
from typing import Type
|
2
3
|
|
3
4
|
from textual.app import App, ComposeResult
|
@@ -5,6 +6,7 @@ from textual.containers import Center
|
|
5
6
|
from textual.screen import Screen
|
6
7
|
from textual.widgets import Footer, Header, OptionList
|
7
8
|
|
9
|
+
from rbx.box.ui.screens.differ import DifferScreen
|
8
10
|
from rbx.box.ui.screens.run_explorer import RunExplorerScreen
|
9
11
|
from rbx.box.ui.screens.test_explorer import TestExplorerScreen
|
10
12
|
|
@@ -35,6 +37,25 @@ class rbxApp(App):
|
|
35
37
|
self.push_screen(screen_cls())
|
36
38
|
|
37
39
|
|
40
|
+
class rbxDifferApp(App):
|
41
|
+
TITLE = 'rbx differ'
|
42
|
+
CSS_PATH = 'css/app.tcss'
|
43
|
+
BINDINGS = [('q', 'quit', 'Quit')]
|
44
|
+
|
45
|
+
def __init__(self, path1: pathlib.Path, path2: pathlib.Path):
|
46
|
+
super().__init__()
|
47
|
+
self.path1 = path1
|
48
|
+
self.path2 = path2
|
49
|
+
|
50
|
+
def on_mount(self):
|
51
|
+
self.push_screen(DifferScreen(self.path1, self.path2))
|
52
|
+
|
53
|
+
|
38
54
|
def start():
|
39
55
|
app = rbxApp()
|
40
56
|
app.run()
|
57
|
+
|
58
|
+
|
59
|
+
def start_differ(path1: pathlib.Path, path2: pathlib.Path):
|
60
|
+
app = rbxDifferApp(path1, path2)
|
61
|
+
app.run()
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import pathlib
|
2
|
+
|
3
|
+
from textual.app import ComposeResult
|
4
|
+
from textual.containers import Vertical
|
5
|
+
from textual.screen import Screen
|
6
|
+
from textual.widgets import Footer, Header
|
7
|
+
|
8
|
+
from rbx.box.ui.widgets.diff_box import DiffBox
|
9
|
+
|
10
|
+
|
11
|
+
class DifferScreen(Screen):
|
12
|
+
BINDINGS = [
|
13
|
+
('q', 'quit', 'Quit'),
|
14
|
+
]
|
15
|
+
|
16
|
+
def __init__(self, path1: pathlib.Path, path2: pathlib.Path):
|
17
|
+
super().__init__()
|
18
|
+
self.path1 = path1
|
19
|
+
self.path2 = path2
|
20
|
+
|
21
|
+
def compose(self) -> ComposeResult:
|
22
|
+
yield Header()
|
23
|
+
yield Footer()
|
24
|
+
with Vertical():
|
25
|
+
yield DiffBox()
|
26
|
+
|
27
|
+
def on_mount(self):
|
28
|
+
diff = self.query_one(DiffBox)
|
29
|
+
diff.paths = (self.path1, self.path2)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import difflib
|
2
|
+
import pathlib
|
3
|
+
from typing import Optional, Tuple
|
4
|
+
|
5
|
+
from rich.markdown import Markdown
|
6
|
+
from textual.app import ComposeResult
|
7
|
+
from textual.reactive import reactive
|
8
|
+
from textual.widget import Widget
|
9
|
+
from textual.widgets import RichLog
|
10
|
+
|
11
|
+
|
12
|
+
def compute_diff(file1: pathlib.Path, file2: pathlib.Path) -> str:
|
13
|
+
lines1 = file1.read_text().splitlines(keepends=True)
|
14
|
+
lines2 = file2.read_text().splitlines(keepends=True)
|
15
|
+
return ''.join(difflib.ndiff(lines1, lines2))
|
16
|
+
|
17
|
+
|
18
|
+
class DiffBox(Widget, can_focus=False):
|
19
|
+
paths: reactive[Optional[Tuple[pathlib.Path, pathlib.Path]]] = reactive(None)
|
20
|
+
|
21
|
+
def __init__(self):
|
22
|
+
super().__init__()
|
23
|
+
|
24
|
+
def compose(self) -> ComposeResult:
|
25
|
+
md = RichLog()
|
26
|
+
md.border_title = 'Differ'
|
27
|
+
yield md
|
28
|
+
|
29
|
+
async def watch_paths(self, paths: Optional[Tuple[pathlib.Path, pathlib.Path]]):
|
30
|
+
log = self.query_one(RichLog)
|
31
|
+
log.clear()
|
32
|
+
if paths is None:
|
33
|
+
return
|
34
|
+
file1, file2 = paths
|
35
|
+
md = Markdown(
|
36
|
+
f'```diff\n{compute_diff(file1, file2)}\n```', code_theme='monokai'
|
37
|
+
)
|
38
|
+
log.write(md)
|
@@ -148,8 +148,6 @@ async def run_validator_unit_tests(progress: StatusProgress):
|
|
148
148
|
|
149
149
|
async def run_checker_unit_tests(progress: StatusProgress):
|
150
150
|
pkg = package.find_problem_package_or_die()
|
151
|
-
if not pkg.unitTests.checker:
|
152
|
-
return
|
153
151
|
|
154
152
|
if not package.get_checker():
|
155
153
|
console.console.print(
|
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
|
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
|