From b878b407468fbf07e6df63447be256684777712c Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Tue, 9 Apr 2024 18:07:12 +0200 Subject: [PATCH] Substitute a failing get_localzone() --- lib/pp_admintools/__init__.py | 3 +- lib/pp_admintools/handler/pflogparse.py | 12 ++++- lib/pp_admintools/postfix_chain.py | 66 +++++++++++++++++++++++-- test/test_25_postfix_logparser.py | 1 + 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/lib/pp_admintools/__init__.py b/lib/pp_admintools/__init__.py index f98a578..1c7875f 100644 --- a/lib/pp_admintools/__init__.py +++ b/lib/pp_admintools/__init__.py @@ -15,12 +15,13 @@ import shutil # Own modules import fb_tools.common -__version__ = '1.0.2' +__version__ = '1.0.3' MAX_PORT_NUMBER = (2 ** 16) - 1 DEFAULT_CONFIG_DIR = 'pixelpark' DEFAULT_TERMINAL_WIDTH = 99 DEFAULT_TERMINAL_HEIGHT = 40 +DEFAULT_TZ_OFFSET = '+2h' # ============================================================================= diff --git a/lib/pp_admintools/handler/pflogparse.py b/lib/pp_admintools/handler/pflogparse.py index 75e6790..9ae7ee8 100644 --- a/lib/pp_admintools/handler/pflogparse.py +++ b/lib/pp_admintools/handler/pflogparse.py @@ -66,6 +66,8 @@ class PostfixLogfileParser(HandlingObject): r'^\s*from=<(?P[^>]*)>,\s+size=(?P\d+),\s+nrcpt=(?P\d+)', re.IGNORECASE) + warn_on_parse_error = True + # ------------------------------------------------------------------------- def __init__( self, appname=None, verbose=0, version=__version__, base_dir=None, @@ -82,6 +84,10 @@ class PostfixLogfileParser(HandlingObject): terminal_has_colors=terminal_has_colors, initialized=False, ) + if not self.warn_on_parse_error: + SmtpAction.warn_on_parse_error = False + PostfixLogchainInfo.warn_on_parse_error = False + self.reset(no_warnings=True) if initialized: @@ -323,7 +329,11 @@ class PostfixLogfileParser(HandlingObject): self, postfix_id, timestamp=None, host=None, pid=None, message=None): """Evaluate a postfix/smtp action log line.""" if postfix_id not in self.chain: - LOG.warn(_('Postfix transaction {!r} does not exists.').format(postfix_id)) + msg = _('Postfix transaction {!r} does not exists.').format(postfix_id) + if self.warn_on_parse_error: + LOG.warn(msg) + else: + LOG.debug(msg) return action = SmtpAction.from_log_entry( diff --git a/lib/pp_admintools/postfix_chain.py b/lib/pp_admintools/postfix_chain.py index df54b57..861fae7 100644 --- a/lib/pp_admintools/postfix_chain.py +++ b/lib/pp_admintools/postfix_chain.py @@ -18,21 +18,29 @@ from collections.abc import Sequence # Third party modules from fb_tools.common import pp +from fb_tools.common import timeinterval2delta from fb_tools.common import to_bool from fb_tools.errors import InvalidMailAddressError from fb_tools.mailaddress import MailAddress from fb_tools.obj import FbGenericBaseObject # Own modules +from . import DEFAULT_TZ_OFFSET from .errors import DateFormatError from .errors import WrongDateIsoformatError -from .tzlocal import get_localzone from .xlate import XLATOR +HAS_GET_LOCALZONE = False +try: + from .tzlocal import get_localzone + HAS_GET_LOCALZONE = True +except ImportError: + pass + _ = XLATOR.gettext ngettext = XLATOR.ngettext -__version__ = '0.7.2' +__version__ = '0.7.3' LOG = logging.getLogger(__name__) @@ -45,6 +53,55 @@ PATTERN_ISOTIMEZONE = r'((?PZ)|(?P[+-][01]\d)(?::?(?P[0- RE_ISODATETIME = re.compile(PATTERN_ISODATE + r'[T\s]' + PATTERN_ISOTIME + PATTERN_ISOTIMEZONE) +PATTERN_DEFAULT_TZ = r'^\s*(?P[+-])\s*(?P.*)' +RE_DEFAULT_TZ = re.compile(PATTERN_DEFAULT_TZ) + +RE_TZ = re.compile(r'^\s*(?P[01]\d)(?::?(?P[0-5]\d))?') + +DEFAULT_TZ = UTC + +# ============================================================================= +def get_default_tz_from_offset(offset=None): + """Return the given offset in seconds as a datetime.timezone object.""" + if offset is None: + offset = DEFAULT_TZ_OFFSET + + default_tz = datetime.timedelta() + + if not offset: + return default_tz + + if isinstance(offset, (int, float)): + return datetime.timezone(datetime.timedelta(seconds=float(offset))) + + offset = str(offset) + omatch = RE_DEFAULT_TZ.match(offset) + if not omatch: + msg = _('Could not interprete {!r} as a timezone offset.').format(offset) + raise ValueError(msg) + + sign = omatch['sign'] + offset_abs = omatch['offset'] + + tz_match = RE_TZ.match(offset_abs) + if tz_match: + res_offset = 0 + if tz_match['tz_mins']: + res_offset = int(tz_match['tz_mins']) * 60 + res_offset += int(tz_match['tz_hours']) * 3600 + if sign == '-': + res_offset *= -1 + return datetime.timezone(datetime.timedelta(seconds=res_offset)) + + delta = timeinterval2delta(offset_abs) + if sign == '-': + delta *= -1 + return datetime.timezone(delta) + + +# ============================================================================= +DEFAULT_TZ = get_default_tz_from_offset(DEFAULT_TZ_OFFSET) + # ============================================================================= def fromisoformat(datestr): @@ -85,7 +142,10 @@ def fromisoformat(datestr): params['tzinfo'] = datetime.timezone(datetime.timedelta(seconds=offset)) else: - params['tzinfo'] = get_localzone() + if HAS_GET_LOCALZONE: + params['tzinfo'] = get_localzone() + else: + params['tzinfo'] = DEFAULT_TZ return datetime.datetime(**params) diff --git a/test/test_25_postfix_logparser.py b/test/test_25_postfix_logparser.py index 2f3dafd..446afef 100755 --- a/test/test_25_postfix_logparser.py +++ b/test/test_25_postfix_logparser.py @@ -88,6 +88,7 @@ class TestPostfixLogparser(PpAdminToolsTestcase): from pp_admintools.handler.pflogparse import PostfixLogfileParser + PostfixLogfileParser.warn_on_parse_error = False parser = PostfixLogfileParser(appname=APPNAME, verbose=self.verbose) LOG.debug('PostfixLogfileParser %r: {!r}'.format(parser)) -- 2.39.5