Permalink
Browse files

Fix time output in totals.py

- Convert UTC time to local time in output
- Change single quote to double quote
- Use new style python formatting
- Make tests use current time
- Fix test for open interval
  • Loading branch information...
lauft committed May 9, 2018
1 parent ca7951c commit 147865b50b99c3f6b07aed2a4f15c97a5832ddaf
Showing with 84 additions and 55 deletions.
  1. +39 −30 ext/totals.py
  2. +45 −25 test/test_totals.t
@@ -28,6 +28,7 @@
import sys
import json
import datetime
from dateutil import tz


def format_seconds(seconds):
@@ -39,101 +40,109 @@ def format_seconds(seconds):
hours = int(seconds / 3600)
minutes = int(seconds % 3600) / 60
seconds = seconds % 60
return '%4d:%02d:%02d' % (hours, minutes, seconds)
return "%4d:%02d:%02d" % (hours, minutes, seconds)


DATEFORMAT = '%Y%m%dT%H%M%SZ'
DATEFORMAT = "%Y%m%dT%H%M%SZ"

# Extract the configuration settings.
header = 1
configuration = dict()
body = ''
body = ""
for line in sys.stdin:
if header:
if line == '\n':
if line == "\n":
header = 0
else:
fields = line.strip().split(': ', 2)
fields = line.strip().split(": ", 2)
if len(fields) == 2:
configuration[fields[0]] = fields[1]
else:
configuration[fields[0]] = ''
configuration[fields[0]] = ""
else:
body += line

# Sum the second tracked by tag.
totals = dict()
untagged = None

from_zone = tz.tzutc()
to_zone = tz.tzlocal()

j = json.loads(body)
for object in j:
start = datetime.datetime.strptime(object['start'], DATEFORMAT)
start = datetime.datetime.strptime(object["start"], DATEFORMAT)

if 'end' in object:
end = datetime.datetime.strptime(object['end'], DATEFORMAT)
if "end" in object:
end = datetime.datetime.strptime(object["end"], DATEFORMAT)
else:
end = datetime.datetime.utcnow()

tracked = end - start

if 'tags' not in object or object['tags'] == []:
if "tags" not in object or object["tags"] == []:
if untagged is None:
untagged = tracked
else:
untagged += tracked
else:
for tag in object['tags']:
for tag in object["tags"]:
if tag in totals:
totals[tag] += tracked
else:
totals[tag] = tracked

# Determine largest tag width.
max_width = len('Total')
max_width = len("Total")
for tag in totals:
if len(tag) > max_width:
max_width = len(tag)

if 'temp.report.start' not in configuration:
print('There is no data in the database')
if "temp.report.start" not in configuration:
print("There is no data in the database")
exit()

start = datetime.datetime.strptime(configuration['temp.report.start'], DATEFORMAT)
start_utc = datetime.datetime.strptime(configuration["temp.report.start"], DATEFORMAT)
start_utc = start_utc.replace(tzinfo=from_zone)
start = start_utc.astimezone(to_zone)

if 'temp.report.end' in configuration:
end = datetime.datetime.strptime(configuration['temp.report.end'], DATEFORMAT)
if "temp.report.end" in configuration:
end_utc = datetime.datetime.strptime(configuration["temp.report.end"], DATEFORMAT)
end_utc = end_utc.replace(tzinfo=from_zone)
end = end_utc.astimezone(to_zone)
else:
end = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
end = datetime.datetime.now()

if max_width > 0:
# Compose report header.
print('\nTotal by Tag, for %s - %s\n' % (start, end))
print("\nTotal by Tag, for {:%Y-%m-%d %H:%M:%S} - {:%Y-%m-%d %H:%M:%S}\n".format(start, end))

# Compose table header.
if configuration['color'] == 'on':
print('[4m%-*s[0m [4m%10s[0m' % (max_width, 'Tag', 'Total'))
if configuration["color"] == "on":
print("[4m{:{width}}[0m [4m{:>10}[0m".format("Tag", "Total", width=max_width))
else:
print('%-*s %10s' % (max_width, 'Tag', 'Total'))
print('{} {}'.format('-' * max_width, '----------'))
print("{:{width}} {:>10}".format("Tag", "Total", width=max_width))
print("{} {}".format("-" * max_width, "----------"))

# Compose table rows.
grand_total = 0
for tag in sorted(totals):
formatted = format_seconds(totals[tag].seconds)
grand_total += totals[tag].seconds
print('%-*s %10s' % (max_width, tag, formatted))
print("%-*s %10s" % (max_width, tag, formatted))

if untagged is not None:
formatted = format_seconds(untagged.seconds)
grand_total += untagged.seconds
print('%-*s %10s' % (max_width, '', formatted))
print("%-*s %10s" % (max_width, "", formatted))

# Compose total.
if configuration['color'] == 'on':
print('{} {}'.format(' ' * max_width, '[4m [0m'))
if configuration["color"] == "on":
print("{} {}".format(" " * max_width, "[4m [0m"))
else:
print('{} {}'.format(' ' * max_width, '----------'))
print("{} {}".format(" " * max_width, "----------"))

print('%-*s %10s' % (max_width, 'Total', format_seconds(grand_total)))
print("%-*s %10s" % (max_width, "Total", format_seconds(grand_total)))

else:
print('No data in the range %s - %s' % (start, end))
print("No data in the range {:%Y-%m-%d %H:%M:%S} - {:%Y-%m-%d %H:%M:%S}".format(start, end))
@@ -56,86 +56,106 @@ temp.report.start:
temp.report.end:
[
]\
]
""")

self.assertEqual('There is no data in the database\n', out)
self.assertEqual('', err)

def test_totals_with_filled_database(self):
"""totals extension should print report for filled database"""
now = datetime.datetime.now()
one_hour_before = now - datetime.timedelta(hours=1)

now_utc = now.utcnow()
one_hour_before_utc = now_utc - datetime.timedelta(hours=1)

out, err = self.process.communicate(input="""\
color: off
debug: off
temp.report.start: 20160101T070000Z
temp.report.end: 20160101T080000Z
temp.report.start: {0:%Y%m%dT%H%M%S}Z
temp.report.end: {1:%Y%m%dT%H%M%S}Z
[
{"start":"20160101T070000Z","end":"20160101T080000Z","tags":["foo"]}
]\
""")
{{"start":"{0:%Y%m%dT%H%M%S}Z","end":"{1:%Y%m%dT%H%M%S}Z","tags":["foo"]}}
]
""".format(one_hour_before_utc, now_utc))

self.assertRegexpMatches(out, """
Total by Tag, for 2016-01-01 07:00:00 - 2016-01-01 08:00:00
Total by Tag, for {0:%Y-%m-%d %H:%M}:\d{{2}} - {1:%Y-%m-%d %H:%M}:\d{{2}}
Tag Total
----- ----------
foo 1:00:0[01]
----------
Total 1:00:0[01]
""")
""".format(one_hour_before, now))
self.assertEqual('', err)

def test_totals_with_interval_without_tags(self):
"""totals extension should handle interval without tags"""
now = datetime.datetime.now()
one_hour_before = now - datetime.timedelta(hours=1)

now_utc = now.utcnow()
one_hour_before_utc = now_utc - datetime.timedelta(hours=1)

out, err = self.process.communicate(input="""\
color: off
debug: off
temp.report.start: 20160101T070000Z
temp.report.end: 20160101T080000Z
temp.report.start: {0:%Y%m%dT%H%M%S}Z
temp.report.end: {1:%Y%m%dT%H%M%S}Z
[{"start":"20160101T070000Z","end":"20160101T080000Z"}]\
""")
[
{{"start":"{0:%Y%m%dT%H%M%S}Z","end":"{1:%Y%m%dT%H%M%S}Z"}}
]
""".format(one_hour_before_utc, now_utc))

self.assertRegexpMatches(out, """
Total by Tag, for 2016-01-01 07:00:00 - 2016-01-01 08:00:00
Total by Tag, for {0:%Y-%m-%d %H:%M}:\d{{2}} - {1:%Y-%m-%d %H:%M}:\d{{2}}
Tag Total
----- ----------
1:00:0[01]
----------
Total 1:00:0[01]
""")
""".format(one_hour_before, now))
self.assertEqual('', err)

def test_totals_with_interval_with_empty_tag_list(self):
"""totals extension should handle interval with empty tag list"""
now = datetime.datetime.now()
one_hour_before = now - datetime.timedelta(hours=1)

now_utc = now.utcnow()
one_hour_before_utc = now_utc - datetime.timedelta(hours=1)

out, err = self.process.communicate(input="""\
color: off
debug: off
temp.report.start: 20160101T070000Z
temp.report.end: 20160101T080000Z
temp.report.start: {0:%Y%m%dT%H%M%S}Z
temp.report.end: {1:%Y%m%dT%H%M%S}Z
[
{"start":"20160101T070000Z","end":"20160101T080000Z","tags":[]}
]\
""")
{{"start":"{0:%Y%m%dT%H%M%S}Z","end":"{1:%Y%m%dT%H%M%S}Z", "tags":[]}}
]
""".format(one_hour_before_utc, now_utc))

self.assertRegexpMatches(out, """
Total by Tag, for 2016-01-01 07:00:00 - 2016-01-01 08:00:00
Total by Tag, for {0:%Y-%m-%d %H:%M}:\d{{2}} - {1:%Y-%m-%d %H:%M}:\d{{2}}
Tag Total
----- ----------
1:00:0[01]
----------
Total 1:00:0[01]
""")
""".format(one_hour_before, now))
self.assertEqual('', err)

def test_totals_with_open_interval(self):
"""totals extension should handle open interval"""
now = datetime.datetime.now()
two_hours_before = now - datetime.timedelta(hours=2)
one_hour_before = now - datetime.timedelta(hours=1)

now_utc = now.utcnow()
one_hour_before_utc = now_utc - datetime.timedelta(hours=1)
@@ -148,18 +168,18 @@ temp.report.end:
[
{{"start":"{0:%Y%m%dT%H%M%S}Z","tags":["foo"]}}
]\
]
""".format(one_hour_before_utc))

self.assertRegexpMatches(out, """
Total by Tag, for {:%Y-%m-%d %H:%M}:\d{{2}} - {:%Y-%m-%d %H:%M}:\d{{2}}
Total by Tag, for {0:%Y-%m-%d %H:%M}:\d{{2}} - {1:%Y-%m-%d %H:%M}:\d{{2}}
Tag Total
----- ----------
foo 1:00:0[01]
----------
Total 1:00:0[01]
""".format(two_hours_before, now))
""".format(one_hour_before, now))
self.assertEqual('', err)


0 comments on commit 147865b

Please sign in to comment.