Release v3.3.1 (#3087)

* Update release notes
* Bump version
* Bump pyright version and solve reported issues

---------

Co-authored-by: Alexander Kukushkin <[email protected]>
This commit is contained in:
Polina Bungina
2024-06-17 17:45:10 +02:00
committed by GitHub
co-authored by Alexander Kukushkin
parent d4fd782038
commit 6b7ec49282
8 changed files with 51 additions and 12 deletions
+1 -1
View File
@@ -186,7 +186,7 @@ jobs:
- uses: jakebailey/pyright-action@v2 - uses: jakebailey/pyright-action@v2
with: with:
version: 1.1.356 version: 1.1.367
docs: docs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
+27
View File
@@ -3,6 +3,33 @@
Release notes Release notes
============= =============
Version 3.3.1
-------------
Released 2024-06-17
**Stability improvements**
- Compatibility with Python 3.12 (Alexander Kukushkin)
Handle a new attribute added to ``logging.LogRecord``.
**Bugfixes**
- Fix infinite recursion in ``replicatefrom`` tags handling (Alexander Kukushkin)
As a part of this fix, also improve ``is_physical_slot()`` check and adjust documentation.
- Fix wrong role reporting in standby clusters (Alexander Kukushkin)
`synchronous_standby_names` and synchronous replication only work on a real primary node and in the case of cascading replication are simply ignored by Postgres. Before this fix, `patronictl list` and `GET /cluster` were falsely reporting some nodes as synchronous.
- Fix availability of the ``allow_in_place_tablespaces`` GUC (Polina Bungina)
``allow_in_place_tablespaces`` was not only added to PostgreSQL 15 but also backpatched to PostgreSQL 10-14.
Version 3.3.0 Version 3.3.0
------------- -------------
+16 -6
View File
@@ -62,6 +62,15 @@ def error_exception(self: logging.Logger, msg: object, *args: Any, **kwargs: Any
self.error(msg, *args, exc_info=exc_info, **kwargs) self.error(msg, *args, exc_info=exc_info, **kwargs)
def _type(value: Any) -> str:
"""Get type of the *value*.
:param value: any arbitrary value.
:returns: a string with a type name.
"""
return value.__class__.__name__
class QueueHandler(logging.Handler): class QueueHandler(logging.Handler):
"""Queue-based logging handler. """Queue-based logging handler.
@@ -292,7 +301,7 @@ class PatroniLogger(Thread):
""" """
if not isinstance(logformat, str): if not isinstance(logformat, str):
_LOGGER.warning('Expected log format to be a string when log type is plain, but got "%s"', type(logformat)) _LOGGER.warning('Expected log format to be a string when log type is plain, but got "%s"', _type(logformat))
logformat = PatroniLogger.DEFAULT_FORMAT logformat = PatroniLogger.DEFAULT_FORMAT
return logging.Formatter(logformat, dateformat) return logging.Formatter(logformat, dateformat)
@@ -330,13 +339,13 @@ class PatroniLogger(Thread):
else: else:
_LOGGER.warning( _LOGGER.warning(
'Expected renamed log field to be a string, but got "%s"', 'Expected renamed log field to be a string, but got "%s"',
type(renamed_field) _type(renamed_field)
) )
else: else:
_LOGGER.warning( _LOGGER.warning(
'Expected each item of log format to be a string or dictionary, but got "%s"', 'Expected each item of log format to be a string or dictionary, but got "%s"',
type(field) _type(field)
) )
if len(log_fields) > 0: if len(log_fields) > 0:
@@ -346,11 +355,12 @@ class PatroniLogger(Thread):
else: else:
jsonformat = PatroniLogger.DEFAULT_FORMAT jsonformat = PatroniLogger.DEFAULT_FORMAT
rename_fields = {} rename_fields = {}
_LOGGER.warning('Expected log format to be a string or a list, but got "%s"', type(logformat)) _LOGGER.warning('Expected log format to be a string or a list, but got "%s"', _type(logformat))
try: try:
from pythonjsonlogger import jsonlogger from pythonjsonlogger import jsonlogger
if hasattr(jsonlogger, 'RESERVED_ATTRS') and 'taskName' not in jsonlogger.RESERVED_ATTRS: if hasattr(jsonlogger, 'RESERVED_ATTRS') \
and 'taskName' not in jsonlogger.RESERVED_ATTRS: # pyright: ignore [reportUnnecessaryContains]
# compatibility with python 3.12, that added a new attribute to LogRecord # compatibility with python 3.12, that added a new attribute to LogRecord
jsonlogger.RESERVED_ATTRS += ('taskName',) jsonlogger.RESERVED_ATTRS += ('taskName',)
@@ -380,7 +390,7 @@ class PatroniLogger(Thread):
static_fields = config.get('static_fields', {}) static_fields = config.get('static_fields', {})
if dateformat is not None and not isinstance(dateformat, str): if dateformat is not None and not isinstance(dateformat, str):
_LOGGER.warning('Expected log dateformat to be a string, but got "%s"', type(dateformat)) _LOGGER.warning('Expected log dateformat to be a string, but got "%s"', _type(dateformat))
dateformat = None dateformat = None
if logtype == 'json': if logtype == 'json':
+2 -1
View File
@@ -893,7 +893,8 @@ class ConfigHandler(object):
return re.sub(r'([:\\])', r'\\\1', str(value)) return re.sub(r'([:\\])', r'\\\1', str(value))
# 'host' could be several comma-separated hostnames, in this case we need to write on pgpass line per host # 'host' could be several comma-separated hostnames, in this case we need to write on pgpass line per host
hosts = map(escape, filter(None, map(str.strip, (record.get('host') or '*').split(',')))) hosts = map(escape, filter(None, map(str.strip,
(record.get('host', '') or '*').split(',')))) # pyright: ignore [reportUnknownArgumentType]
record = {n: escape(record.get(n) or '*') for n in ('port', 'user', 'password')} record = {n: escape(record.get(n) or '*') for n in ('port', 'user', 'password')}
return '\n'.join('{host}:{port}:*:{user}:{password}'.format(**record, host=host) for host in hosts) return '\n'.join('{host}:{port}:*:{user}:{password}'.format(**record, host=host) for host in hosts)
+2 -1
View File
@@ -428,7 +428,8 @@ class CitusHandler(Citus, AbstractMPPHandler, Thread):
# citus extension must be on the first place in shared_preload_libraries # citus extension must be on the first place in shared_preload_libraries
shared_preload_libraries = list(filter( shared_preload_libraries = list(filter(
lambda el: el and el != 'citus', lambda el: el and el != 'citus',
[p.strip() for p in parameters.get('shared_preload_libraries', '').split(',')])) map(str.strip, parameters.get('shared_preload_libraries', '').split(',')))
) # pyright: ignore [reportUnknownArgumentType]
parameters['shared_preload_libraries'] = ','.join(['citus'] + shared_preload_libraries) parameters['shared_preload_libraries'] = ','.join(['citus'] + shared_preload_libraries)
# if not explicitly set Citus overrides max_prepared_transactions to max_connections*2 # if not explicitly set Citus overrides max_prepared_transactions to max_connections*2
+1 -1
View File
@@ -2,4 +2,4 @@
:var __version__: the current Patroni version. :var __version__: the current Patroni version.
""" """
__version__ = '3.3.0' __version__ = '3.3.1'
+1 -1
View File
@@ -19,7 +19,7 @@
"reportMissingImports": true, "reportMissingImports": true,
"reportMissingTypeStubs": false, "reportMissingTypeStubs": false,
"pythonVersion": "3.11", "pythonVersion": "3.12",
"pythonPlatform": "All", "pythonPlatform": "All",
"typeCheckingMode": "strict" "typeCheckingMode": "strict"
+1 -1
View File
@@ -187,7 +187,7 @@ class TestPatroniLogger(unittest.TestCase):
self.assertEqual(captured_log_level, 'WARNING') self.assertEqual(captured_log_level, 'WARNING')
self.assertRegex( self.assertRegex(
captured_log_message, captured_log_message,
fr'Expected log dateformat to be a string, but got "{type(config["dateformat"])}"' r'Expected log dateformat to be a string, but got "int"'
) )
def test_invalid_plain_format(self): def test_invalid_plain_format(self):