From 20b8d7f4021490aacb78c52f8edd93d193629a55 Mon Sep 17 00:00:00 2001 From: Mateusz Masiarz <matimasiarz@gmail.com> Date: Mon, 9 Sep 2024 13:28:21 +0200 Subject: [PATCH 1/2] Use oicompare as default checker --- src/sinol_make/__init__.py | 3 +- src/sinol_make/helpers/oicompare.py | 56 ++++++++++++++++++++++++++++ src/sinol_make/task_type/__init__.py | 21 ++++++++++- tests/conftest.py | 4 +- 4 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 src/sinol_make/helpers/oicompare.py diff --git a/src/sinol_make/__init__.py b/src/sinol_make/__init__.py index 4603ba6a..ae077244 100644 --- a/src/sinol_make/__init__.py +++ b/src/sinol_make/__init__.py @@ -5,7 +5,7 @@ import argcomplete from sinol_make import util, sio2jail -from sinol_make.helpers import cache +from sinol_make.helpers import cache, oicompare # Required for side effects from sinol_make.task_type.normal import NormalTaskType # noqa @@ -76,6 +76,7 @@ def main_exn(): parser.print_help() exit(1) check_sio2jail() + oicompare.check_and_download() for curr_args in arguments: args = parser.parse_args(curr_args) diff --git a/src/sinol_make/helpers/oicompare.py b/src/sinol_make/helpers/oicompare.py new file mode 100644 index 00000000..e72f8f88 --- /dev/null +++ b/src/sinol_make/helpers/oicompare.py @@ -0,0 +1,56 @@ +import os +import requests +import subprocess + +from sinol_make import util + + +__OICOMAPRE_VERSION = 'v1.0.2' + + +def get_path(): + return os.path.expanduser('~/.local/bin/oicompare') + + +def check_installed(): + path = get_path() + if not os.path.exists(path): + return False + try: + output = subprocess.run([path, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + except PermissionError: + return False + if output.returncode != 0: + return False + if output.stdout.decode().strip() != f'oicompare version {__OICOMAPRE_VERSION[1:]}': + return False + return True + + +def download_oicomapare(): + url = f'https://github.com/sio2project/oicompare/releases/download/{__OICOMAPRE_VERSION}/oicompare' + if util.is_macos_arm(): + url += '-arm64' + path = get_path() + os.makedirs(os.path.dirname(path), exist_ok=True) + manual_download_msg = ("You can try downloading it manually from " + f"https://github.com/sio2project/oicompare/releases/tag/{__OICOMAPRE_VERSION}/ and placing " + f"it in ~/.local/bin/oicomapre") + try: + request = requests.get(url) + except requests.exceptions.ConnectionError: + util.exit_with_error("Couldn't download oicompare (couldn't connect). " + manual_download_msg) + if request.status_code != 200: + util.exit_with_error(f"Couldn't download oicompare (returned status code: {request.status_code}). " + + manual_download_msg) + with open(path, 'wb') as f: + f.write(request.content) + os.chmod(path, 0o755) + + +def check_and_download(): + if check_installed(): + return + download_oicomapare() + if not check_installed(): + util.exit_with_error("Couldn't download oicompare. Please try again later or download it manually.") diff --git a/src/sinol_make/task_type/__init__.py b/src/sinol_make/task_type/__init__.py index e37c20c9..ca02a86c 100644 --- a/src/sinol_make/task_type/__init__.py +++ b/src/sinol_make/task_type/__init__.py @@ -6,7 +6,7 @@ from sinol_make import util from sinol_make.executors.sio2jail import Sio2jailExecutor from sinol_make.executors.time import TimeExecutor -from sinol_make.helpers import package_util, paths, cache +from sinol_make.helpers import package_util, paths, cache, oicompare from sinol_make.helpers.classinit import RegisteredSubclassesBase from sinol_make.interfaces.Errors import CheckerException from sinol_make.structs.status_structs import ExecutionResult @@ -162,6 +162,23 @@ def _run_diff(self, output_file_path, answer_file_path) -> Tuple[bool, Fraction, else: return False, Fraction(0, 1), "" + def _run_oicompare(self, output_file_path, answer_file_path) -> Tuple[bool, Fraction, str]: + path = oicompare.get_path() + proc = subprocess.Popen([path, output_file_path, answer_file_path, 'english_abbreviated'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + proc.wait() + output, stderr = proc.communicate() + if proc.returncode == 0: + return True, Fraction(100, 1), "" + elif proc.returncode == 1: + return False, Fraction(0, 1), output.decode('utf-8').strip() + else: + raise CheckerException(f"!!! oicompare failed with code {proc.returncode}. This is a huge bug, please report" + f" it here https://github.com/sio2project/sinol-make/issues/new/choose and provide " + f"these files: {output_file_path}, {answer_file_path}.\n" + f"Output: {output.decode('utf-8').strip()}\n" + f"Stderr: {stderr.decode('utf-8').strip()}") + def check_output(self, input_file_path, output_file_path, answer_file_path) -> Tuple[bool, Fraction, str]: """ Runs the checker (or runs diff) and returns a tuple of three values: @@ -171,6 +188,8 @@ def check_output(self, input_file_path, output_file_path, answer_file_path) -> T """ if self.has_checker: return self._run_checker(input_file_path, output_file_path, answer_file_path) + elif oicompare.check_installed(): + return self._run_oicompare(output_file_path, answer_file_path) else: return self._run_diff(output_file_path, answer_file_path) diff --git a/tests/conftest.py b/tests/conftest.py index 4998aaf3..9683c6fe 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,7 +8,7 @@ import multiprocessing as mp from sinol_make import util -from sinol_make.helpers import compile, paths, cache +from sinol_make.helpers import compile, paths, cache, oicompare from sinol_make.interfaces.Errors import CompilationError @@ -91,6 +91,8 @@ def pytest_configure(config): except FileNotFoundError: pass + oicompare.check_and_download() + def pytest_generate_tests(metafunc): if "time_tool" in metafunc.fixturenames: From b31890e1afe760f8e4a60f55151b9d933688e3bb Mon Sep 17 00:00:00 2001 From: Mateusz Masiarz <matimasiarz@gmail.com> Date: Mon, 9 Sep 2024 14:21:46 +0200 Subject: [PATCH 2/2] Bump version --- src/sinol_make/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sinol_make/__init__.py b/src/sinol_make/__init__.py index ae077244..a7b99549 100644 --- a/src/sinol_make/__init__.py +++ b/src/sinol_make/__init__.py @@ -12,7 +12,7 @@ from sinol_make.task_type.interactive import InteractiveTaskType # noqa -__version__ = "1.8.2" +__version__ = "1.8.3" def configure_parsers():