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:
parent
3d469ce28c
commit
65a8379261
|
@ -1 +1,2 @@
|
|||
Jinja2>=2.8
|
||||
pendulum
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue