From 8dee5d213c9abdfae8739033ff01484a4cb4e3c0 Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 22:20:50 +0300 Subject: [PATCH 01/18] rename: ProcessIsZombie_soft_check --- src/impl/platforms/darwin/internal_platform_utils.py | 2 +- src/impl/platforms/internal_platform_utils.py | 2 +- src/impl/platforms/linux/internal_platform_utils.py | 2 +- src/impl/platforms/win32/internal_platform_utils.py | 2 +- src/utils.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/impl/platforms/darwin/internal_platform_utils.py b/src/impl/platforms/darwin/internal_platform_utils.py index ce8fdb4f..738e9d5e 100644 --- a/src/impl/platforms/darwin/internal_platform_utils.py +++ b/src/impl/platforms/darwin/internal_platform_utils.py @@ -248,7 +248,7 @@ def _FindPostmaster( ) # -------------------------------------------------------------------- - def ProcessIsZombi_soft_check( + def ProcessIsZombie_soft_check( self, os_ops: OsOperations, pid: int, diff --git a/src/impl/platforms/internal_platform_utils.py b/src/impl/platforms/internal_platform_utils.py index e9b121b6..0003c4b5 100644 --- a/src/impl/platforms/internal_platform_utils.py +++ b/src/impl/platforms/internal_platform_utils.py @@ -61,7 +61,7 @@ def FindPostmaster( assert type(data_dir) is str raise NotImplementedError("InternalPlatformUtils::FindPostmaster is not implemented.") - def ProcessIsZombi_soft_check( + def ProcessIsZombie_soft_check( self, os_ops: OsOperations, pid: int, diff --git a/src/impl/platforms/linux/internal_platform_utils.py b/src/impl/platforms/linux/internal_platform_utils.py index 1021b735..61c3c32a 100644 --- a/src/impl/platforms/linux/internal_platform_utils.py +++ b/src/impl/platforms/linux/internal_platform_utils.py @@ -247,7 +247,7 @@ def _FindPostmaster( ) # -------------------------------------------------------------------- - def ProcessIsZombi_soft_check( + def ProcessIsZombie_soft_check( self, os_ops: OsOperations, pid: int, diff --git a/src/impl/platforms/win32/internal_platform_utils.py b/src/impl/platforms/win32/internal_platform_utils.py index c6df6378..71aa1c71 100644 --- a/src/impl/platforms/win32/internal_platform_utils.py +++ b/src/impl/platforms/win32/internal_platform_utils.py @@ -17,7 +17,7 @@ def FindPostmaster( assert type(data_dir) is str return __class__.FindPostmasterResult.create_not_implemented() - def ProcessIsZombi_soft_check( + def ProcessIsZombie_soft_check( self, os_ops: OsOperations, pid: int, diff --git a/src/utils.py b/src/utils.py index eb63694d..1546b80b 100644 --- a/src/utils.py +++ b/src/utils.py @@ -566,7 +566,7 @@ def exec( assert pid != 0 # ----------------- detect zombie - if platform_utils_provider.get().ProcessIsZombi_soft_check(os_ops, pid) is True: + if platform_utils_provider.get().ProcessIsZombie_soft_check(os_ops, pid) is True: internal_utils.send_log_debug("Postmaster process {} is a zombie.".format( pid, )) From a4ef39b7363b2fcded6652a200dee8a304ad389e Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 22:21:39 +0300 Subject: [PATCH 02/18] RaiseError.method_is_not_implemented is added --- src/impl/platforms/internal_platform_utils.py | 6 ++++-- src/port_manager.py | 7 +++++-- src/raise_error.py | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/impl/platforms/internal_platform_utils.py b/src/impl/platforms/internal_platform_utils.py index 0003c4b5..df96db1f 100644 --- a/src/impl/platforms/internal_platform_utils.py +++ b/src/impl/platforms/internal_platform_utils.py @@ -1,5 +1,7 @@ from __future__ import annotations +from ...raise_error import RaiseError + import enum import typing @@ -59,7 +61,7 @@ def FindPostmaster( assert isinstance(os_ops, OsOperations) assert type(bin_dir) is str assert type(data_dir) is str - raise NotImplementedError("InternalPlatformUtils::FindPostmaster is not implemented.") + RaiseError.method_is_not_implemented(__class__, "FindPostmaster") def ProcessIsZombie_soft_check( self, @@ -68,4 +70,4 @@ def ProcessIsZombie_soft_check( ) -> typing.Optional[bool]: assert isinstance(os_ops, OsOperations) assert type(pid) is int - raise NotImplementedError("InternalPlatformUtils::ProcessIsZombi_soft_ver is not implemented.") + RaiseError.method_is_not_implemented(__class__, "ProcessIsZombie_soft_check") diff --git a/src/port_manager.py b/src/port_manager.py index c003a038..338da2f1 100644 --- a/src/port_manager.py +++ b/src/port_manager.py @@ -1,10 +1,13 @@ +from .raise_error import RaiseError + + class PortManager: def __init__(self): super().__init__() def reserve_port(self) -> int: - raise NotImplementedError("PortManager::reserve_port is not implemented.") + RaiseError.method_is_not_implemented(__class__, "reserve_port") def release_port(self, number: int) -> None: assert type(number) is int - raise NotImplementedError("PortManager::release_port is not implemented.") + RaiseError.method_is_not_implemented(__class__, "release_port") diff --git a/src/raise_error.py b/src/raise_error.py index aa6a910b..751ceb6e 100644 --- a/src/raise_error.py +++ b/src/raise_error.py @@ -5,6 +5,20 @@ class RaiseError: + @staticmethod + def method_is_not_implemented( + class_type: type, + method_name: str, + ) -> typing.NoReturn: + assert type(class_type) is type + assert type(method_name) is str + + err_msg = "Method {}::{} is not implemented.".format( + class_type.__name__, + method_name, + ) + raise NotImplementedError(err_msg) + @staticmethod def pg_ctl_returns_an_empty_string(_params) -> typing.NoReturn: errLines = [] From 256cc79ff86fc9c5fb7704cb87e5ee52ac39f639 Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 22:22:16 +0300 Subject: [PATCH 03/18] linux/internal_platform_utils: ProcessIsZombie_soft_check is updated --- src/impl/platforms/linux/internal_platform_utils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/impl/platforms/linux/internal_platform_utils.py b/src/impl/platforms/linux/internal_platform_utils.py index 61c3c32a..faba7c2c 100644 --- a/src/impl/platforms/linux/internal_platform_utils.py +++ b/src/impl/platforms/linux/internal_platform_utils.py @@ -264,7 +264,10 @@ def ProcessIsZombie_soft_check( try: # Read one line from /proc/PID/stat - stat_content = os_ops.read_binary(proc_stat_file, 0).decode("utf-8", errors="ignore") + stat_content_b = os_ops.read_binary(proc_stat_file, 0) + assert type(stat_content_b) is bytes + + stat_content = stat_content_b.decode("utf-8", errors="ignore") # We look for the closing parenthesis of the process name to ensure that # we start from it and not depend on spaces inside the parentheses! From c4caa8bcce9a5b2bde611425f3c8f737354d88a8 Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 22:23:14 +0300 Subject: [PATCH 04/18] linux/internal_platform_utils: (rename) _is_zombie_file_exception --- src/impl/platforms/linux/internal_platform_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/impl/platforms/linux/internal_platform_utils.py b/src/impl/platforms/linux/internal_platform_utils.py index faba7c2c..f05e59bf 100644 --- a/src/impl/platforms/linux/internal_platform_utils.py +++ b/src/impl/platforms/linux/internal_platform_utils.py @@ -284,13 +284,13 @@ def ProcessIsZombie_soft_check( result = proc_status == "Z" except Exception as e: # If the file disappeared right during reading, it means the process is completely erased - if __class__._is_file_not_found_exception(e): + if __class__._is_zombie_file_exception(e): result = False return result @staticmethod - def _is_file_not_found_exception(e: Exception) -> bool: + def _is_zombie_file_exception(e: Exception) -> bool: if isinstance(e, FileNotFoundError): return True From 20f32b0e97f99a3a4190ccdb4b700981bc0e987e Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 23:07:56 +0300 Subject: [PATCH 05/18] import cleanup: from collections.abc import Iterable --- src/node.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/node.py b/src/node.py index ded039ec..b4de142d 100644 --- a/src/node.py +++ b/src/node.py @@ -81,10 +81,7 @@ import time import typing -try: - from collections.abc import Iterable -except ImportError: - from collections import Iterable +from collections.abc import Iterable # we support both pg8000 and psycopg2 try: From d793776d2ebb132d259b52576160beb78f845325 Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 23:09:46 +0300 Subject: [PATCH 06/18] Usage typing.Iterable instead collections.abc.Iterable (cleanup) --- src/node.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/node.py b/src/node.py index b4de142d..a2490aff 100644 --- a/src/node.py +++ b/src/node.py @@ -81,8 +81,6 @@ import time import typing -from collections.abc import Iterable - # we support both pg8000 and psycopg2 try: import psycopg2 as pglib @@ -2064,10 +2062,10 @@ def set_synchronous_standbys(self, standbys): """ if self._pg_version >= utils.PgVer('9.6'): - if isinstance(standbys, Iterable): + if isinstance(standbys, typing.Iterable): standbys = First(1, standbys) else: - if isinstance(standbys, Iterable): + if isinstance(standbys, typing.Iterable): standbys = u", ".join(u"\"{}\"".format(r.name) for r in standbys) else: From 54b2f0980e0238d6dabdedd8408562e59069c31f Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 23:16:41 +0300 Subject: [PATCH 07/18] cleanup old strings: u"..." -> "..." --- src/node.py | 3 +-- src/standby.py | 10 ++++++---- src/utils.py | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/node.py b/src/node.py index a2490aff..aa412570 100644 --- a/src/node.py +++ b/src/node.py @@ -2066,8 +2066,7 @@ def set_synchronous_standbys(self, standbys): standbys = First(1, standbys) else: if isinstance(standbys, typing.Iterable): - standbys = u", ".join(u"\"{}\"".format(r.name) - for r in standbys) + standbys = ", ".join("\"{}\"".format(r.name) for r in standbys) else: raise TestgresException( "Feature isn't supported in " diff --git a/src/standby.py b/src/standby.py index 859f874e..aeeea922 100644 --- a/src/standby.py +++ b/src/standby.py @@ -21,9 +21,10 @@ def __init__(self, sync_num, standbys): self.standbys = standbys def __str__(self): - return u"{} ({})".format( + return "{} ({})".format( self.sync_num, - u", ".join(u"\"{}\"".format(r.name) for r in self.standbys)) + ", ".join("\"{}\"".format(r.name) for r in self.standbys), + ) @six.python_2_unicode_compatible @@ -44,6 +45,7 @@ def __init__(self, sync_num, standbys): self.standbys = standbys def __str__(self): - return u"ANY {} ({})".format( + return "ANY {} ({})".format( self.sync_num, - u", ".join(u"\"{}\"".format(r.name) for r in self.standbys)) + ", ".join("\"{}\"".format(r.name) for r in self.standbys), + ) diff --git a/src/utils.py b/src/utils.py index 1546b80b..218006a1 100644 --- a/src/utils.py +++ b/src/utils.py @@ -404,8 +404,8 @@ def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) -def options_string(separator=u" ", **kwargs): - return separator.join(u"{}={}".format(k, v) for k, v in iteritems(kwargs)) +def options_string(separator=" ", **kwargs): + return separator.join("{}={}".format(k, v) for k, v in iteritems(kwargs)) @contextmanager From f959e7411798a021d4b3f2c3e43d2250356d78de Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 23:20:07 +0300 Subject: [PATCH 08/18] cleanup: unuse six.iteritems --- src/enums.py | 3 +-- src/node.py | 8 ++++---- src/utils.py | 3 +-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/enums.py b/src/enums.py index a483c5b4..da52dc34 100644 --- a/src/enums.py +++ b/src/enums.py @@ -1,5 +1,4 @@ from enum import Enum, IntEnum -from six import iteritems from psutil import NoSuchProcess @@ -83,7 +82,7 @@ def from_process(process): if cmdline.startswith(ptype.value.replace(' ', '')): return ptype - for ptype, names in iteritems(alternative_names): + for ptype, names in alternative_names.items(): for name in names: if cmdline.startswith(name.replace(' ', '')): return ptype diff --git a/src/node.py b/src/node.py index aa412570..f241bcff 100644 --- a/src/node.py +++ b/src/node.py @@ -90,7 +90,7 @@ except ImportError: raise ImportError("You must have psycopg2 or pg8000 modules installed") -from six import raise_from, iteritems, text_type +from six import raise_from, text_type InternalError = pglib.InternalError @@ -1067,7 +1067,7 @@ def append_conf(self, line='', filename=PG_CONF_FILE, **kwargs): lines = [line] - for option, value in iteritems(kwargs): + for option, value in kwargs.items(): if isinstance(value, bool): value = 'on' if value else 'off' elif not str(value).replace('.', '', 1).isdigit(): @@ -1710,7 +1710,7 @@ def _psql( ] # yapf: disable # set variables before execution - for key, value in iteritems(variables): + for key, value in variables.items(): psql_params.extend(["--set", '{}={}'.format(key, value)]) # select query source @@ -2277,7 +2277,7 @@ def pgbench_run( "-U", username or self._os_ops.username ] + options # yapf: disable - for key, value in iteritems(kwargs): + for key, value in kwargs.items(): # rename keys for pgbench key = key.replace('_', '-') diff --git a/src/utils.py b/src/utils.py index 218006a1..16d6784e 100644 --- a/src/utils.py +++ b/src/utils.py @@ -30,7 +30,6 @@ import re import typing -from six import iteritems from contextlib import contextmanager from packaging.version import Version, InvalidVersion @@ -405,7 +404,7 @@ def eprint(*args, **kwargs): def options_string(separator=" ", **kwargs): - return separator.join("{}={}".format(k, v) for k, v in iteritems(kwargs)) + return separator.join("{}={}".format(k, v) for k, v in kwargs.items()) @contextmanager From 9510504f5b764af351aeb30dc4ab294ab6bf9e69 Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 23:28:39 +0300 Subject: [PATCH 09/18] cleanup: replace 'rause_from(e2, e1)' with 'raise e2 from e1' --- src/backup.py | 4 +--- src/cache.py | 8 +++----- src/node.py | 8 ++++---- src/pubsub.py | 4 +--- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/backup.py b/src/backup.py index 9c54be17..666abed0 100644 --- a/src/backup.py +++ b/src/backup.py @@ -1,7 +1,5 @@ # coding: utf-8 -from six import raise_from - from .enums import XLogMethod from .consts import \ @@ -131,7 +129,7 @@ def _prepare_dir(self, destroy): # Copy backup to new data dir self.os_ops.copytree(data1, data2) except Exception as e: - raise_from(BackupException('Failed to copy files'), e) + raise BackupException('Failed to copy files') from e else: dest_base_dir = self.base_dir diff --git a/src/cache.py b/src/cache.py index e205a510..06d7ba4a 100644 --- a/src/cache.py +++ b/src/cache.py @@ -1,7 +1,5 @@ # coding: utf-8 -from six import raise_from - from .config import testgres_config from .consts import XLOG_CONTROL_FILE @@ -49,7 +47,7 @@ def call_initdb(initdb_dir, log=logfile): log, ) except ExecUtilException as e: - raise_from(InitNodeException("Failed to run initdb"), e) + raise InitNodeException("Failed to run initdb") from e if params or not testgres_config.cache_initdb or not cached: call_initdb(data_dir, logfile) @@ -89,7 +87,7 @@ def call_initdb(initdb_dir, log=logfile): except ExecUtilException as e: msg = "Failed to reset WAL for system id" - raise_from(InitNodeException(msg), e) + raise InitNodeException(msg) from e except Exception as e: - raise_from(InitNodeException("Failed to spawn a node"), e) + raise InitNodeException("Failed to spawn a node") from e diff --git a/src/node.py b/src/node.py index f241bcff..039b079a 100644 --- a/src/node.py +++ b/src/node.py @@ -90,7 +90,7 @@ except ImportError: raise ImportError("You must have psycopg2 or pg8000 modules installed") -from six import raise_from, text_type +from six import text_type InternalError = pglib.InternalError @@ -1363,7 +1363,7 @@ def _raise_cannot_start_node( assert from_exception is None or isinstance(from_exception, Exception) assert type(msg) is str files = self._collect_special_files() - raise_from(StartNodeException(msg, files), from_exception) + raise StartNodeException(msg, files) from from_exception def stop( self, @@ -1466,7 +1466,7 @@ def restart(self, params=[]): except ExecUtilException as e: msg = 'Cannot restart node' files = self._collect_special_files() - raise_from(StartNodeException(msg, files), e) + raise StartNodeException(msg, files) from e self._maybe_start_logger() @@ -2106,7 +2106,7 @@ def catchup(self, dbname=None, username=None): max_attempts=0, ) except Exception as e: - raise_from(CatchUpException("Failed to catch up."), e) + raise CatchUpException("Failed to catch up.") from e def publish(self, name, **kwargs): """ diff --git a/src/pubsub.py b/src/pubsub.py index c8a446ef..0a006da0 100644 --- a/src/pubsub.py +++ b/src/pubsub.py @@ -42,8 +42,6 @@ [(1, 1), (2, 2)] """ -from six import raise_from - from .consts import LOGICAL_REPL_MAX_CATCHUP_ATTEMPTS from .defaults import default_dbname, default_username2 from .exceptions import CatchUpException @@ -341,4 +339,4 @@ def catchup(self, username=None): max_attempts=LOGICAL_REPL_MAX_CATCHUP_ATTEMPTS, ) except Exception as e: - raise_from(CatchUpException("Failed to catch up"), e) + raise CatchUpException("Failed to catch up") from e From aee1181879e90b4384275c7393219ee52f1a08ae Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 23:30:52 +0300 Subject: [PATCH 10/18] cleaup: replace 'text_type(x)' with 'str(x)' --- src/node.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/node.py b/src/node.py index 039b079a..360675f8 100644 --- a/src/node.py +++ b/src/node.py @@ -90,8 +90,6 @@ except ImportError: raise ImportError("You must have psycopg2 or pg8000 modules installed") -from six import text_type - InternalError = pglib.InternalError ProgrammingError = pglib.ProgrammingError @@ -1081,7 +1079,7 @@ def append_conf(self, line='', filename=PG_CONF_FILE, **kwargs): config_name = self._os_ops.build_path(self.data_dir, filename) conf_text = '' for line in lines: - conf_text += text_type(line) + '\n' + conf_text += str(line) + '\n' self._os_ops.write(config_name, conf_text) return self From 01aee9b887ab020ce6f4a8fa101396f5569e352c Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 23:34:34 +0300 Subject: [PATCH 11/18] replace six.string_types with str --- tests/test_testgres_common.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_testgres_common.py b/tests/test_testgres_common.py index 8604933e..32fab746 100644 --- a/tests/test_testgres_common.py +++ b/tests/test_testgres_common.py @@ -50,7 +50,6 @@ from contextlib import contextmanager import pytest -import six import logging import time import tempfile @@ -161,7 +160,7 @@ def test_version_management(self, node_svc: PostgresNodeService): version = get_pg_version2(node_svc.os_ops) with __class__.helper__get_node(node_svc) as node: - assert (isinstance(version, six.string_types)) + assert (isinstance(version, str)) assert (isinstance(node.version, PgVer)) assert (node.version == PgVer(version)) From 63b67d5635ce110b2132e792f54700d2946d199e Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 23:34:54 +0300 Subject: [PATCH 12/18] [del] @six.python_2_unicode_compatible --- src/standby.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/standby.py b/src/standby.py index aeeea922..4e0912af 100644 --- a/src/standby.py +++ b/src/standby.py @@ -1,9 +1,6 @@ # coding: utf-8 -import six - -@six.python_2_unicode_compatible class First: """ Specifies a priority-based synchronous replication and makes transaction @@ -27,7 +24,6 @@ def __str__(self): ) -@six.python_2_unicode_compatible class Any: """ Specifies a quorum-based synchronous replication and makes transaction From 3890583c9eb6d897b573a3e46e9dd679051f0dab Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 23:37:28 +0300 Subject: [PATCH 13/18] [del] six.iterkeys --- src/decorators.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/decorators.py b/src/decorators.py index 7f383ae7..98b10ea7 100644 --- a/src/decorators.py +++ b/src/decorators.py @@ -1,4 +1,3 @@ -import six import functools @@ -18,7 +17,7 @@ def some_api_func(...) for case in special_cases: k = len(case) - assert k not in six.iterkeys(cases), 'len must be unique' + assert k not in cases, 'len must be unique' cases[k] = case def decorator(function): @@ -26,7 +25,7 @@ def decorator(function): def wrapper(*args, **kwargs): k = len(args) - if k in six.iterkeys(cases): + if k in cases: case = cases[k] for i in range(0, k): From 8cd9093d3e11fb1336d5d5d9936470f3463ba2a3 Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 23:38:39 +0300 Subject: [PATCH 14/18] [del] @six.python_2_unicode_compatible --- src/exceptions.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/exceptions.py b/src/exceptions.py index 13de787a..2911ba79 100644 --- a/src/exceptions.py +++ b/src/exceptions.py @@ -44,7 +44,6 @@ def __repr__(self) -> str: return result -@six.python_2_unicode_compatible class QueryException(TestgresException): _description: typing.Optional[str] _query: typing.Optional[str] @@ -162,7 +161,6 @@ def __repr__(self) -> str: return result -@six.python_2_unicode_compatible class StartNodeException(TestgresException): _description: typing.Optional[str] _files: typing.Optional[typing.Iterable] From afb002a8b062f746ef197c19502e445a03b770c3 Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 23:39:44 +0300 Subject: [PATCH 15/18] replace six.text_type('\n') with '\n' --- src/exceptions.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/exceptions.py b/src/exceptions.py index 2911ba79..d00de700 100644 --- a/src/exceptions.py +++ b/src/exceptions.py @@ -1,6 +1,5 @@ # coding: utf-8 -import six import typing from testgres.operations.exceptions import TestgresException @@ -75,7 +74,7 @@ def message(self) -> str: if self._query: msg.append(u'Query: {}'.format(self._query)) - r = six.text_type('\n').join(msg) + r = '\n'.join(msg) assert type(r) is str return r @@ -194,7 +193,7 @@ def message(self) -> str: assert type(lines) in [str, bytes] msg.append(u'{}\n----\n{}\n'.format(f, lines)) - return six.text_type('\n').join(msg) + return '\n'.join(msg) @property def description(self) -> typing.Optional[str]: From 299f81780378c3a47f6d222fd9757d0f259f2310 Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 23:45:21 +0300 Subject: [PATCH 16/18] [del] usage of 'six' --- pyproject.toml | 1 - tests/requirements.txt | 1 - 2 files changed, 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 985aec28..7c51b331 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,7 +62,6 @@ classifiers = [ dependencies = [ "pg8000", "port-for>=0.4", - "six>=1.9.0", "psutil", "packaging", "testgres.os_ops>=3.3.3,<4.0.0", diff --git a/tests/requirements.txt b/tests/requirements.txt index fd3d7c75..b85c6074 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -2,7 +2,6 @@ pytest pytest-env pytest-xdist psutil -six psycopg2 testgres.os_ops>=3.3.3,<4.0.0 testgres.postgres_configuration>=0.2.2,<1.0.0 From 1ae3c3be2137f049cbabd6a49e310e642961f773 Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 23:51:45 +0300 Subject: [PATCH 17/18] node: top level 'import ipaddress' --- src/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node.py b/src/node.py index 360675f8..8041e1aa 100644 --- a/src/node.py +++ b/src/node.py @@ -74,6 +74,7 @@ from testgres.operations.os_ops import OsProcessController from testgres.operations.local_ops import LocalOperations +import ipaddress import logging import signal import subprocess @@ -749,7 +750,6 @@ def _create_recovery_conf(self, username, slot=None): # host is tricky try: - import ipaddress ipaddress.ip_address(master.host) conninfo["hostaddr"] = master.host except ValueError: From 38d9ef5be37d3b4c27f6922f91bae952c40401c6 Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 23 Sep 2026 23:55:03 +0300 Subject: [PATCH 18/18] [de] inheriting from object --- src/backup.py | 2 +- src/config.py | 2 +- src/connection.py | 2 +- src/node.py | 4 ++-- src/pubsub.py | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/backup.py b/src/backup.py index 666abed0..75ac1af2 100644 --- a/src/backup.py +++ b/src/backup.py @@ -20,7 +20,7 @@ clean_on_error -class NodeBackup(object): +class NodeBackup: """ Smart object responsible for backups """ diff --git a/src/config.py b/src/config.py index 1d09ccb8..41c2108e 100644 --- a/src/config.py +++ b/src/config.py @@ -17,7 +17,7 @@ logging.basicConfig(level=log_level, format=log_format) -class GlobalConfig(object): +class GlobalConfig: """ Global configuration object which allows user to override default settings. """ diff --git a/src/connection.py b/src/connection.py index b16edb23..ec455124 100644 --- a/src/connection.py +++ b/src/connection.py @@ -25,7 +25,7 @@ OperationalError = pglib.OperationalError -class NodeConnection(object): +class NodeConnection: """ Transaction wrapper returned by Node """ diff --git a/src/node.py b/src/node.py index 8041e1aa..b2e81684 100644 --- a/src/node.py +++ b/src/node.py @@ -100,7 +100,7 @@ assert TimeoutException == QueryTimeoutException -class ProcessProxy(object): +class ProcessProxy: """ Wrapper for psutil.Process @@ -144,7 +144,7 @@ def ptype(self) -> ProcessType: return self._ptype -class PostgresNode(object): +class PostgresNode: # a max number of node start attempts _C_MAX_START_ATEMPTS = 5 diff --git a/src/pubsub.py b/src/pubsub.py index 0a006da0..07b1ec29 100644 --- a/src/pubsub.py +++ b/src/pubsub.py @@ -48,7 +48,7 @@ from .utils import options_string -class Publication(object): +class Publication: def __init__(self, name, node, tables=None, dbname=None, username=None): """ Constructor. Use :meth:`.PostgresNode.publish()` instead of direct @@ -132,7 +132,7 @@ def add_tables(self, tables, dbname=None, username=None): ) -class Subscription(object): +class Subscription: def __init__( self, node,