From 888b171f2ff90c26a3398b792e7deac470750a1b Mon Sep 17 00:00:00 2001
From: Jarkko Jaakola <jarkko.jaakola@aiven.io>
Date: Tue, 23 Jul 2024 16:02:26 +0300
Subject: [PATCH] chore: update for Python 3.12

---
 .github/workflows/lint.yml            | 4 ++--
 .github/workflows/schema.yml          | 2 +-
 .github/workflows/tests.yml           | 2 +-
 .pre-commit-config.yaml               | 6 +++---
 .pylintrc                             | 1 +
 karapace/backup/api.py                | 3 ++-
 karapace/backup/backends/v2.py        | 5 ++++-
 karapace/backup/safe_writer.py        | 9 ++++++---
 karapace/protobuf/known_dependency.py | 2 +-
 karapace/protobuf/message_element.py  | 2 +-
 karapace/protobuf/proto_type.py       | 2 +-
 karapace/protobuf/syntax_reader.py    | 3 +--
 karapace/schema_registry.py           | 2 ++
 karapace/utils.py                     | 2 +-
 14 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 4d90fd3df..d029ff9f2 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -23,7 +23,7 @@ jobs:
     - uses: actions/setup-python@v5
       with:
         cache: pip
-        python-version: '3.11'
+        python-version: '3.12'
     - name: Install libsnappy-dev
       run: sudo apt install libsnappy-dev
     # required for pylint
@@ -42,7 +42,7 @@ jobs:
     - uses: actions/setup-python@v5
       with:
         cache: pip
-        python-version: '3.11'
+        python-version: '3.12'
     - name: Install libsnappy-dev
       run: sudo apt install libsnappy-dev
     - run: pip install -r requirements/requirements.txt -r requirements/requirements-typing.txt
diff --git a/.github/workflows/schema.yml b/.github/workflows/schema.yml
index fed313a5f..1ee9a8049 100644
--- a/.github/workflows/schema.yml
+++ b/.github/workflows/schema.yml
@@ -15,7 +15,7 @@ jobs:
           fetch-depth: 0
       - uses: actions/setup-python@v5
         with:
-          python-version: "3.11"
+          python-version: "3.12"
           cache: pip
           cache-dependency-path:
             requirements.txt
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index da2839a3d..fd9a63c2b 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        python-version: [ '3.8', '3.9', '3.10', '3.11' ]
+        python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12' ]
     env:
       PYTEST_ADDOPTS: >-
         --log-dir=/tmp/ci-logs
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 8af01f93a..a975b52ec 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -21,7 +21,7 @@ repos:
     entry: ./copyright.sh
 
 - repo: https://github.com/shellcheck-py/shellcheck-py
-  rev: v0.9.0.2
+  rev: v0.10.0.1
   hooks:
   - id: shellcheck
 
@@ -56,7 +56,7 @@ repos:
   - id: black
 
 - repo: https://github.com/PyCQA/flake8
-  rev: 6.0.0
+  rev: 7.1.0
   hooks:
   - id: flake8
 
@@ -73,6 +73,6 @@ repos:
 - repo: https://github.com/PyCQA/pylint
   # Note: pre-commit autoupdate changes to an alpha version. Instead, manually find the
   # latest stable version here: https://github.com/pylint-dev/pylint/releases
-  rev: v2.17.4
+  rev: v3.2.6
   hooks:
   - id: pylint
diff --git a/.pylintrc b/.pylintrc
index 414336499..e2c2f6242 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -10,6 +10,7 @@ disable=
   duplicate-code,
   fixme,
   import-outside-toplevel,
+  invalid-field-call,
   invalid-name,
   missing-docstring,
   too-few-public-methods,
diff --git a/karapace/backup/api.py b/karapace/backup/api.py
index 8f2b09f14..7b243586b 100644
--- a/karapace/backup/api.py
+++ b/karapace/backup/api.py
@@ -22,6 +22,7 @@
 from .poll_timeout import PollTimeout
 from .topic_configurations import ConfigSource, get_topic_configurations
 from aiokafka.errors import KafkaError, TopicAlreadyExistsError
+from collections.abc import Sized
 from concurrent.futures import Future
 from confluent_kafka import Message, TopicPartition
 from enum import Enum
@@ -41,7 +42,7 @@
 from pathlib import Path
 from rich.console import Console
 from tenacity import retry, retry_if_exception_type, RetryCallState, stop_after_delay, wait_fixed
-from typing import Callable, Iterator, Literal, Mapping, NewType, Sized, TypeVar
+from typing import Callable, Iterator, Literal, Mapping, NewType, TypeVar
 
 import contextlib
 import datetime
diff --git a/karapace/backup/backends/v2.py b/karapace/backup/backends/v2.py
index 7a7386ded..7472e9b2f 100644
--- a/karapace/backup/backends/v2.py
+++ b/karapace/backup/backends/v2.py
@@ -33,7 +33,10 @@ def safe_writer(
     ) -> Generator[IO[str], None, None]:
         with super().safe_writer(target, allow_overwrite) as buffer:
             buffer.write(V2_MARKER.decode())
-            yield buffer
+            try:
+                yield buffer
+            finally:
+                pass
 
 
 class SchemaBackupV2Writer(_BaseV2Writer):
diff --git a/karapace/backup/safe_writer.py b/karapace/backup/safe_writer.py
index 45181a7d7..57970b950 100644
--- a/karapace/backup/safe_writer.py
+++ b/karapace/backup/safe_writer.py
@@ -109,9 +109,12 @@ def str_writer(
     safe_context = _safe_temporary_descriptor(target.absolute(), allow_overwrite)
 
     with safe_context as fd, open(fd, "w") as buffer:
-        yield buffer
-        buffer.flush()
-        os.fsync(fd)
+        try:
+            yield buffer
+            buffer.flush()
+            os.fsync(fd)
+        finally:
+            pass
 
 
 def _check_destination_directory(destination: Path) -> None:
diff --git a/karapace/protobuf/known_dependency.py b/karapace/protobuf/known_dependency.py
index 31c4a8b33..5b322929b 100644
--- a/karapace/protobuf/known_dependency.py
+++ b/karapace/protobuf/known_dependency.py
@@ -16,7 +16,7 @@ def static_init(cls: Any) -> object:
     return cls
 
 
-@static_init
+@static_init  # pylint: disable=used-before-assignment
 class KnownDependency:
     index: Dict = dict()
     index_simple: Dict = dict()
diff --git a/karapace/protobuf/message_element.py b/karapace/protobuf/message_element.py
index 57eb03fa6..c7f2ddb10 100644
--- a/karapace/protobuf/message_element.py
+++ b/karapace/protobuf/message_element.py
@@ -91,7 +91,7 @@ def to_schema(self) -> str:
         return "".join(result)
 
     def compare(self, other: TypeElement, result: CompareResult, types: CompareTypes) -> None:
-        from karapace.protobuf.compare_type_lists import compare_type_lists
+        from karapace.protobuf.compare_type_lists import compare_type_lists  # pylint: disable=cyclic-import
 
         if not isinstance(other, MessageElement):
             result.add_modification(Modification.TYPE_ALTER)
diff --git a/karapace/protobuf/proto_type.py b/karapace/protobuf/proto_type.py
index 94a278044..9dad49163 100644
--- a/karapace/protobuf/proto_type.py
+++ b/karapace/protobuf/proto_type.py
@@ -19,7 +19,7 @@ def static_init(cls) -> object:
     return cls
 
 
-@static_init
+@static_init  # pylint: disable=used-before-assignment
 class ProtoType:
     @property
     def simple_name(self) -> str:
diff --git a/karapace/protobuf/syntax_reader.py b/karapace/protobuf/syntax_reader.py
index 560e63b85..13c3238e9 100644
--- a/karapace/protobuf/syntax_reader.py
+++ b/karapace/protobuf/syntax_reader.py
@@ -103,7 +103,6 @@ def read_quoted_string(self) -> str:
                 self.newline()
 
         self.unexpected("unterminated string")
-        return ""
 
     def read_numeric_escape(self, radix: int, length: int) -> str:
         value = -1
@@ -180,7 +179,7 @@ def read_word(self) -> str:
         self.expect(start < self.pos, "expected a word")
         return self.data[start : self.pos]
 
-    def read_int(self) -> int:  # pylint: disable=inconsistent-return-statements
+    def read_int(self) -> int:
         """Reads an integer and returns it."""
         tag: str = self.read_word()
         try:
diff --git a/karapace/schema_registry.py b/karapace/schema_registry.py
index e4d24db2e..6594663ad 100644
--- a/karapace/schema_registry.py
+++ b/karapace/schema_registry.py
@@ -179,6 +179,8 @@ async def subject_delete_local(self, subject: Subject, permanent: bool) -> list[
                     version_list = list(schema_versions_live)
                     if version_list:
                         latest_version_id = version_list[-1]
+                    else:
+                        return []
 
                 referenced_by = self.schema_reader.get_referenced_by(subject, latest_version_id)
                 if referenced_by and len(referenced_by) > 0:
diff --git a/karapace/utils.py b/karapace/utils.py
index 8066c5565..96f87da8c 100644
--- a/karapace/utils.py
+++ b/karapace/utils.py
@@ -203,7 +203,7 @@ def convert_to_int(object_: dict, key: str, content_type: str) -> None:
     try:
         object_[key] = int(object_[key])
     except ValueError:
-        from karapace.rapu import http_error
+        from karapace.rapu import http_error  # pylint: disable=cyclic-import
 
         http_error(
             message=f"{key} is not a valid int: {object_[key]}",