Use pendulum instead of plain datetime

because it is more intuitive to use and doesn't require the
tz_aware_datetime-workaround.
This commit is contained in:
Thor77 2017-05-20 00:31:26 +02:00
parent 3d469ce28c
commit 65a8379261
6 changed files with 38 additions and 62 deletions

View File

@ -1 +1,2 @@
Jinja2>=2.8
pendulum

View File

@ -4,13 +4,13 @@ import logging
import re
from codecs import open
from collections import namedtuple
from datetime import datetime
from glob import glob
from os.path import basename
from time import time
import pendulum
from tsstats.client import Client, Clients
from tsstats.utils import tz_aware_datime
re_log_filename = re.compile(r'ts3server_(?P<date>\d{4}-\d\d-\d\d)'
'__(?P<time>\d\d_\d\d_\d\d.\d+)_(?P<sid>\d).log')
@ -23,8 +23,6 @@ re_disconnect_invoker = re.compile(
r'invokername=(.*)\ invokeruid=(.*)\ reasonmsg'
)
log_timestamp_format = '%Y-%m-%d %H:%M:%S.%f'
TimedLog = namedtuple('TimedLog', ['path', 'timestamp'])
Server = namedtuple('Server', ['sid', 'clients'])
@ -81,9 +79,9 @@ def _bundle_logs(logs):
match = re_log_filename.match(basename(log))
if match:
match = match.groupdict()
timestamp = datetime.strptime('{0} {1}'.format(
match['date'], match['time'].replace('_', ':')),
log_timestamp_format)
timestamp = pendulum.parse('{0} {1}'.format(
match['date'], match['time'].replace('_', ':'))
)
tl = TimedLog(log, timestamp)
sid = match['sid']
if sid in vserver_logfiles:
@ -136,8 +134,7 @@ def _parse_details(log_path, ident_map=None, clients=None, online_dc=True):
logger.debug('No match: "%s"', line)
continue
match = match.groupdict()
logdatetime = tz_aware_datime(datetime.strptime(match['timestamp'],
log_timestamp_format))
logdatetime = pendulum.parse(match['timestamp'])
message = match['message']
if message.startswith('client'):
match = re_dis_connect.match(message)
@ -178,7 +175,7 @@ def _parse_details(log_path, ident_map=None, clients=None, online_dc=True):
]
if online_dc:
def _reconnect(client):
client.disconnect(tz_aware_datime(datetime.utcnow()))
client.disconnect(pendulum.now())
client.connected += 1
[_reconnect(client) for client in clients if client.connected]
logger.debug(

View File

@ -2,14 +2,13 @@
import logging
from collections import namedtuple
from datetime import datetime
from os.path import dirname, join
import pendulum
from jinja2 import ChoiceLoader, Environment, FileSystemLoader, PackageLoader
from tsstats.log import Server
from tsstats.utils import (filter_threshold, seconds_to_text, sort_clients,
tz_aware_datime)
from tsstats.utils import filter_threshold, seconds_to_text, sort_clients
logger = logging.getLogger('tsstats')
@ -43,8 +42,7 @@ def prepare_clients(clients, onlinetime_threshold=-1):
clients, lambda c: c.onlinetime.total_seconds()
)
# filter clients not matching threshold
onlinetime_ = filter_threshold(onlinetime_,
onlinetime_threshold)
onlinetime_ = filter_threshold(onlinetime_, onlinetime_threshold)
# convert timespans to text
onlinetime = [
(client, seconds_to_text(int(onlinetime)))
@ -105,6 +103,6 @@ def render_servers(servers, output, title='TeamspeakStats',
logger.debug('Rendering template %s', template)
template.stream(title=title, servers=prepared_servers,
debug=logger.level <= logging.DEBUG,
creation_time=tz_aware_datime(datetime.utcnow()))\
creation_time=pendulum.utcnow())\
.dump(output, encoding='utf-8')
logger.debug('Wrote rendered template to %s', output)

View File

@ -1,6 +1,4 @@
from datetime import datetime, timedelta
from time import sleep
import pendulum
import pytest
from tsstats.exceptions import InvalidLog
@ -20,8 +18,10 @@ def test_log_client_count(clients):
def test_log_onlinetime(clients):
assert clients['1'].onlinetime == timedelta(0, 402, 149208)
assert clients['2'].onlinetime == timedelta(0, 19, 759644)
assert clients['1'].onlinetime == pendulum.Interval(
seconds=402, microseconds=149208)
assert clients['2'].onlinetime == pendulum.Interval(
seconds=19, microseconds=759644)
def test_log_kicks(clients):
@ -52,12 +52,20 @@ def test_log_pbans(clients):
],
{
'1': [
TimedLog('ts3server_2016-06-06__14_22_09.527229_1.log',
datetime(year=2016, month=6, day=6, hour=14,
minute=22, second=9, microsecond=527229)),
TimedLog('ts3server_2017-07-07__15_23_10.638340_1.log',
datetime(year=2017, month=7, day=7, hour=15,
minute=23, second=10, microsecond=638340))
TimedLog(
'ts3server_2016-06-06__14_22_09.527229_1.log',
pendulum.create(
year=2016, month=6, day=6, hour=14, minute=22,
second=9, microsecond=527229
)
),
TimedLog(
'ts3server_2017-07-07__15_23_10.638340_1.log',
pendulum.create(
year=2017, month=7, day=7, hour=15, minute=23,
second=10, microsecond=638340
)
)
]
}
)
@ -71,11 +79,14 @@ def test_log_invalid():
_parse_details('tsstats/tests/res/test.log.broken')
@pytest.mark.slowtest
def test_log_client_online():
current_time = pendulum.now()
pendulum.set_test_now(current_time)
clients = _parse_details(testlog_path)
old_onlinetime = int(clients['1'].onlinetime.total_seconds())
sleep(2)
pendulum.set_test_now(current_time.add(seconds=2)) # add 2s to .now()
clients = _parse_details(testlog_path)
assert int(clients['1'].onlinetime.total_seconds()) == old_onlinetime + 2

View File

@ -1,6 +1,6 @@
import logging
from datetime import timedelta
import pendulum
import pytest
from bs4 import BeautifulSoup
@ -44,7 +44,7 @@ def test_onlinetime(soup):
onlinetime = onlinetime.text
# find corresponding client-object
client = list(filter(
lambda c: c.nick == nick and c.onlinetime > timedelta(0),
lambda c: c.nick == nick and c.onlinetime > pendulum.Interval(),
clients
))
# assert existence

View File

@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
import datetime
def sort_clients(clients, key_l):
'''
sort `clients` by `key`
@ -52,34 +49,6 @@ def filter_threshold(clients, threshold):
return list(filter(lambda c: c[1] > threshold, clients))
class UTC(datetime.tzinfo):
'''
Reimplementation of `timezone.utc` for Python2-Compatibility
'''
def utcoffset(self, dt):
return datetime.timedelta(0)
def dst(self, dt):
return datetime.timedelta(0)
def tzname(self, dt):
return 'UTC'
def tz_aware_datime(datetime, timezone=UTC()):
'''
Make `datetime` aware of it's timezone (UTC by default)
:param datetime: Target datetime
:param timezone: Target timezone
:type datetime: datetime.datetime
:type timezone: datetime.timezone
'''
return datetime.replace(tzinfo=timezone)
def transform_pretty_identmap(pretty_identmap):
'''
Transforms a list of client ID mappings from a more descriptive format