import re
# Third party modules
+# from fb_tools.common import pp
from fb_tools.obj import FbGenericBaseObject
# Own modules
_ = XLATOR.gettext
ngettext = XLATOR.ngettext
-__version__ = '0.2.0'
+__version__ = '0.3.0'
LOG = logging.getLogger(__name__)
self.auth = auth
self.client_addr = client_addr
self.client_host = client_host
+ self.end = end
+ self.start = start
+
+ # -------------------------------------------------------------------------
+ @classmethod
+ def date_fromisoformat(cls, datestr):
+ """Try to convert a string with an ISO-fromatted timestamp into a datetime object."""
+ m = cls.re_isodatetime.search(datestr)
+ if not m:
+ return None
+
+ params = {
+ 'year': int(m['year']),
+ 'month': int(m['month']),
+ 'day': int(m['day']),
+ 'minute': int(m['min']),
+ }
+ if m['sec'] is not None:
+ params['second'] = int(m['sec'])
+
+ if m['nsec'] is not None:
+ params['microsecond'] = int(round(float('0.' + m['nsec']) * 1000000))
+
+ if m['utc']:
+ params['tzinfo'] = UTC
+ elif m['tz_hours'] is not None:
+ prefix = m['tz_hours'][0]
+ offset = 0
+ if m['tz_mins'] is not None:
+ offset = int(m['tz_mins']) * 60
+ offset += int(m['tz_hours'][1:]) * 3600
+ if prefix == '-':
+ offset *= -1
+
+ params['tzinfo'] = datetime.timezone(datetime.timedelta(seconds=offset))
+
+ return datetime.datetime(**params)
# -----------------------------------------------------------
@property
return
self._client_host = val
+ # -----------------------------------------------------------
+ @property
+ def duration(self):
+ """Return the timediff between start and end of the SMRP transaction."""
+ if not isinstance(self.start, datetime.datetime):
+ return None
+ if not isinstance(self.end, datetime.datetime):
+ return None
+ return self.end - self.start
+
+ # -----------------------------------------------------------
+ @property
+ def end(self):
+ """Return the timestamp of the end of the SMTP dialogue."""
+ return self._end
+
+ @end.setter
+ def end(self, value):
+ if value is None:
+ self._end = None
+ return
+
+ if isinstance(value, datetime.datetime):
+ self._end = value
+ return
+
+ val = str(value).strip()
+ if val == '':
+ self._end = None
+ return
+
+ ts_end = self.date_fromisoformat(val)
+ if ts_end:
+ self._end = ts_end
+ return
+ self._end = val
+
+ # -----------------------------------------------------------
+ @property
+ def start(self):
+ """Return the timestamp of the starting of the SMTP dialogue."""
+ return self._start
+
+ @start.setter
+ def start(self, value):
+ if value is None:
+ self._start = None
+ return
+
+ if isinstance(value, datetime.datetime):
+ self._start = value
+ return
+
+ val = str(value).strip()
+ if val == '':
+ self._start = None
+ return
+
+ ts_start = self.date_fromisoformat(val)
+ if ts_start:
+ self._start = ts_start
+ return
+ self._start = val
+
# -------------------------------------------------------------------------
def __repr__(self):
"""Typecast into a string for reproduction."""
fields.append('client_addr={!r}'.format(str(self.client_addr)))
if self.client_host is not None:
fields.append('client_host={!r}'.format(str(self.client_host)))
+ if self.end is not None:
+ if isinstance(self.end, datetime.datetime):
+ ts = self.end.isoformat(' ')
+ else:
+ ts = self.end
+ fields.append('end={!r}'.format(ts))
+ if self.start is not None:
+ if isinstance(self.start, datetime.datetime):
+ ts = self.start.isoformat(' ')
+ else:
+ ts = self.start
+ fields.append('start={!r}'.format(ts))
if fields:
out += ', '.join(fields)
res['auth'] = self.auth
res['client_addr'] = self.client_addr
res['client_host'] = self.client_host
+ res['duration'] = self.duration
+ res['end'] = self.end
+ res['start'] = self.start
return res