Skip to content

Commit

Permalink
Use pendulum instead of plain datetime
Browse files Browse the repository at this point in the history
because it is more intuitive to use and doesn't require the
tz_aware_datetime-workaround.
  • Loading branch information
Thor77 committed Jul 7, 2017
1 parent 3d469ce commit 65a8379
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 62 deletions.
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Jinja2>=2.8
pendulum
17 changes: 7 additions & 10 deletions tsstats/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
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')
Expand All @@ -23,8 +23,6 @@
r'invokername=(.*)\ invokeruid=(.*)\ reasonmsg'
)

log_timestamp_format = '%Y-%m-%d %H:%M:%S.%f'

TimedLog = namedtuple('TimedLog', ['path', 'timestamp'])
Server = namedtuple('Server', ['sid', 'clients'])

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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(
Expand Down
10 changes: 4 additions & 6 deletions tsstats/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand Down Expand Up @@ -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)))
Expand Down Expand Up @@ -105,6 +103,6 @@ def frmttime(timestamp):
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)
37 changes: 24 additions & 13 deletions tsstats/tests/test_log.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
from datetime import datetime, timedelta
from time import sleep

import pendulum
import pytest

from tsstats.exceptions import InvalidLog
Expand All @@ -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):
Expand Down Expand Up @@ -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
)
)
]
}
)
Expand All @@ -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

Expand Down
4 changes: 2 additions & 2 deletions tsstats/tests/test_template.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging
from datetime import timedelta

import pendulum
import pytest
from bs4 import BeautifulSoup

Expand Down Expand Up @@ -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
Expand Down
31 changes: 0 additions & 31 deletions tsstats/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
import datetime


def sort_clients(clients, key_l):
'''
sort `clients` by `key`
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 65a8379

Please sign in to comment.