From ebe691db6040f2ac6e8eb6dc363dcd670b539930 Mon Sep 17 00:00:00 2001 From: MartinXPN Date: Thu, 14 Sep 2023 20:16:48 +0400 Subject: [PATCH] Python 3.11 syntax upgrade --- .pre-commit-config.yaml | 2 +- coderunners/checkers.py | 35 +++++++++++++++++------------------ coderunners/process.py | 3 +-- coderunners/scoring.py | 3 +-- coderunners/services.py | 2 +- coderunners/util.py | 3 +-- models.py | 39 +++++++++++++++++++-------------------- 7 files changed, 41 insertions(+), 46 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2123c38..b417ea4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,7 +18,7 @@ repos: rev: v3.3.1 hooks: - id: pyupgrade - args: [--py39-plus] + args: [--py311-plus] - repo: https://github.com/pycqa/isort rev: 5.12.0 diff --git a/coderunners/checkers.py b/coderunners/checkers.py index 71921e2..eaa420a 100644 --- a/coderunners/checkers.py +++ b/coderunners/checkers.py @@ -5,7 +5,6 @@ from dataclasses import dataclass from pathlib import Path from tempfile import NamedTemporaryFile, TemporaryDirectory -from typing import Optional from coderunners.process import Process from coderunners.util import is_float, save_code @@ -17,13 +16,13 @@ class Checker(ABC): def check( self, inputs: str, output: str, target: str, code: dict[str, str], - input_files: Optional[dict[str, str]] = None, - output_files: Optional[dict[str, str]] = None, - target_files: Optional[dict[str, str]] = None, - input_assets: Optional[dict[str, bytes]] = None, - output_assets: Optional[dict[str, bytes]] = None, - target_assets: Optional[dict[str, bytes]] = None, - ) -> tuple[Status, float, Optional[str]]: + input_files: dict[str, str] | None = None, + output_files: dict[str, str] | None = None, + target_files: dict[str, str] | None = None, + input_assets: dict[str, bytes] | None = None, + output_assets: dict[str, bytes] | None = None, + target_assets: dict[str, bytes] | None = None, + ) -> tuple[Status, float, str | None]: """ Check if the program behaved correctly and return the verdict :param inputs: all the input of the program @@ -42,8 +41,8 @@ def check( @staticmethod def from_mode(mode: str, - float_precision: Optional[float] = None, delimiter: Optional[str] = None, - executable_path: Optional[Path] = None) -> 'Checker': + float_precision: float | None = None, delimiter: str | None = None, + executable_path: Path | None = None) -> 'Checker': if mode == 'ok': return OkChecker() if mode == 'whole': @@ -60,10 +59,10 @@ def from_mode(mode: str, class OkChecker(Checker): def check( self, inputs: str, output: str, target: str, code: dict[str, str], - input_files: Optional[dict[str, str]] = None, output_files: Optional[dict[str, str]] = None, - target_files: Optional[dict[str, str]] = None, input_assets: Optional[dict[str, bytes]] = None, - output_assets: Optional[dict[str, bytes]] = None, target_assets: Optional[dict[str, bytes]] = None, - ) -> tuple[Status, float, Optional[str]]: + input_files: dict[str, str] | None = None, output_files: dict[str, str] | None = None, + target_files: dict[str, str] | None = None, input_assets: dict[str, bytes] | None = None, + output_assets: dict[str, bytes] | None = None, target_assets: dict[str, bytes] | None = None, + ) -> tuple[Status, float, str | None]: return Status.OK, 100, None @@ -72,7 +71,7 @@ def check( self, inputs, output, target, code, input_files=None, output_files=None, target_files=None, input_assets=None, output_assets=None, target_assets=None, - ) -> tuple[Status, float, Optional[str]]: + ) -> tuple[Status, float, str | None]: files_match = [output_files[file].strip() == target_files[file].strip() if file in output_files else False for file in (target_files or {}).keys()] @@ -86,7 +85,7 @@ def check( @dataclass class TokenEquality(Checker): float_precision: float = 1e-5 - delimiter: Optional[str] = None + delimiter: str | None = None def is_correct(self, output: str, target: str) -> bool: output = output.strip().split(self.delimiter) @@ -113,7 +112,7 @@ def check( self, inputs, output, target, code, input_files=None, output_files=None, target_files=None, input_assets=None, output_assets=None, target_assets=None, - ) -> tuple[Status, float, Optional[str]]: + ) -> tuple[Status, float, str | None]: files_match = [self.is_correct(output_files[file], target_files[file]) if file in output_files else False for file in (target_files or {}).keys()] @@ -132,7 +131,7 @@ def check( self, inputs, output, target, code, input_files=None, output_files=None, target_files=None, input_assets=None, output_assets=None, target_assets=None, - ) -> tuple[Status, float, Optional[str]]: + ) -> tuple[Status, float, str | None]: # TODO: How to support files and assets for custom checkers? with NamedTemporaryFile('w') as inf, NamedTemporaryFile('w') as ouf, NamedTemporaryFile('w') as tg, \ TemporaryDirectory() as code_dir: diff --git a/coderunners/process.py b/coderunners/process.py index 0e163a5..e1ca18c 100644 --- a/coderunners/process.py +++ b/coderunners/process.py @@ -7,7 +7,6 @@ from dataclasses import dataclass, field from pathlib import Path from threading import Thread -from typing import Union import psutil @@ -62,7 +61,7 @@ def read_stderr(process: subprocess.Popen, res: Outputs) -> None: @dataclass class Process: - command: Union[str, Iterable[str]] + command: str | Iterable[str] timeout: float memory_limit_mb: int output_limit_mb: float = 1 diff --git a/coderunners/scoring.py b/coderunners/scoring.py index af17ef3..e45cc1b 100644 --- a/coderunners/scoring.py +++ b/coderunners/scoring.py @@ -1,7 +1,6 @@ from abc import ABC, abstractmethod from dataclasses import dataclass from decimal import Decimal, getcontext -from typing import Optional from models import RunResult, Status, TestGroup @@ -16,7 +15,7 @@ def score(self, test_results: list[RunResult]) -> tuple[float, list[float]]: ... @staticmethod - def from_request(test_groups: Optional[list[TestGroup]] = None) -> 'Scorer': + def from_request(test_groups: list[TestGroup] | None = None) -> 'Scorer': return SubtaskScorer(test_groups=test_groups) if test_groups else PerTestScorer() diff --git a/coderunners/services.py b/coderunners/services.py index ea6892c..43b4478 100644 --- a/coderunners/services.py +++ b/coderunners/services.py @@ -17,7 +17,7 @@ class EqualityChecker(SubmissionRequest): ROOT: Path = Path('/tmp/') - def compile(self, code_paths: list[Path], language: str) -> tuple[Optional[Path], RunResult]: + def compile(self, code_paths: list[Path], language: str) -> tuple[Path | None, RunResult]: """ Compiles and returns (executable path | None, compilation result) """ compiler = Compiler.from_language(language=language) executable_path, compilation = compiler.compile(submission_paths=code_paths) diff --git a/coderunners/util.py b/coderunners/util.py index a66892b..92cd891 100644 --- a/coderunners/util.py +++ b/coderunners/util.py @@ -1,6 +1,5 @@ import errno from pathlib import Path -from typing import Union def is_float(value: str) -> bool: @@ -13,7 +12,7 @@ def is_float(value: str) -> bool: return False -def save_code(save_dir: Path, code: dict[str, Union[str, dict[str, str]]]) -> list[Path]: +def save_code(save_dir: Path, code: dict[str, str | dict[str, str]]) -> list[Path]: saved_paths: list[Path] = [] save_dir.mkdir(parents=True, exist_ok=True) diff --git a/models.py b/models.py index 90324a3..abd9d25 100644 --- a/models.py +++ b/models.py @@ -1,6 +1,5 @@ from dataclasses import dataclass from enum import Enum -from typing import Optional from dataclasses_json import DataClassJsonMixin, LetterCase, Undefined, config @@ -25,10 +24,10 @@ class Status(Enum): class TestCase(DataClassJsonCamelMixIn): input: str target: str - input_files: Optional[dict[str, str]] = None # list of (filename, textual content) - target_files: Optional[dict[str, str]] = None # list of (filename, textual content) - input_assets: Optional[dict[str, str]] = None # list of (filename, base64 encoded string) - target_assets: Optional[dict[str, str]] = None # list of (filename, base64 encoded string) + input_files: dict[str, str] | None = None # list of (filename, textual content) + target_files: dict[str, str] | None = None # list of (filename, textual content) + input_assets: dict[str, str] | None = None # list of (filename, base64 encoded string) + target_assets: dict[str, str] | None = None # list of (filename, base64 encoded string) @dataclass @@ -52,9 +51,9 @@ class SubmissionRequest(DataClassJsonCamelMixIn): output_limit: float = 1 # MB # In case of both problem and test_cases being provided, tests = test_cases + problem.tests - problem: Optional[str] = None # used to find the test cases in the EFS - test_cases: Optional[list[TestCase]] = None # list of test cases - test_groups: Optional[list[TestGroup]] = None + problem: str | None = None # used to find the test cases in the EFS + test_cases: list[TestCase] | None = None # list of test cases + test_groups: list[TestGroup] | None = None return_outputs: bool = False stop_on_first_fail: bool = True @@ -63,12 +62,12 @@ class SubmissionRequest(DataClassJsonCamelMixIn): # Checker parameters comparison_mode: str = 'whole' # whole | token | custom float_precision: float = 1e-5 # Floating point precision - delimiter: Optional[str] = None - checker_code: Optional[dict[str, str]] = None - checker_language: Optional[str] = None + delimiter: str | None = None + checker_code: dict[str, str] | None = None + checker_language: str | None = None - callback_url: Optional[str] = None # Where to send the results when they're ready - encryption_key: Optional[str] = None + callback_url: str | None = None # Where to send the results when they're ready + encryption_key: str | None = None def __post_init__(self): self.language = self.language.lower() @@ -89,19 +88,19 @@ class RunResult(DataClassJsonCamelMixIn): time: float return_code: int score: float = 0 - message: Optional[str] = None - outputs: Optional[str] = None - errors: Optional[str] = None - output_files: Optional[dict[str, str]] = None - output_assets: Optional[dict[str, str]] = None + message: str | None = None + outputs: str | None = None + errors: str | None = None + output_files: dict[str, str] | None = None + output_assets: dict[str, str] | None = None @dataclass class SubmissionResult(DataClassJsonCamelMixIn): overall: RunResult compile_result: RunResult - linting_result: Optional[RunResult] = None - test_results: Optional[list[RunResult]] = None + linting_result: RunResult | None = None + test_results: list[RunResult] | None = None @dataclass