commit
2cf503abac
4 changed files with 96 additions and 28 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,4 +1,9 @@
|
||||||
|
__pycache__/
|
||||||
lib/ctt/__pycache__/
|
lib/ctt/__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# -vim
|
||||||
|
.*.swp
|
||||||
|
|
||||||
# Manpages
|
# Manpages
|
||||||
*.1
|
*.1
|
||||||
|
|
|
@ -4,6 +4,12 @@ Changelog
|
||||||
* Changes are always commented with their author in (braces)
|
* Changes are always commented with their author in (braces)
|
||||||
* Exception: No braces means author == Nico Schottelius
|
* Exception: No braces means author == Nico Schottelius
|
||||||
|
|
||||||
|
Next:
|
||||||
|
* Added -s, --summary option (Darko Poljak)
|
||||||
|
* No args error (Darko Poljak)
|
||||||
|
* Report project name as file path basename (Darko Poljak)
|
||||||
|
* Report globbing (Darko Poljak)
|
||||||
|
|
||||||
1.0: 2014-07-01
|
1.0: 2014-07-01
|
||||||
* Added installer (Oz Nahum)
|
* Added installer (Oz Nahum)
|
||||||
* Bugfix in listprojects (Oz Nahum)
|
* Bugfix in listprojects (Oz Nahum)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# 2012 Nico Schottelius (nico-ctt at schottelius.org)
|
# 2012 Nico Schottelius (nico-ctt at schottelius.org)
|
||||||
|
# 2016 Darko Poljak (darko.poljak at gmail.com)
|
||||||
#
|
#
|
||||||
# This file is part of ctt.
|
# This file is part of ctt.
|
||||||
#
|
#
|
||||||
|
@ -31,6 +32,7 @@ import os.path
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import glob
|
import glob
|
||||||
|
import collections
|
||||||
|
|
||||||
import ctt
|
import ctt
|
||||||
import ctt.listprojects
|
import ctt.listprojects
|
||||||
|
@ -70,14 +72,62 @@ class Report(object):
|
||||||
projects.extend(fnames)
|
projects.extend(fnames)
|
||||||
|
|
||||||
total_time = 0
|
total_time = 0
|
||||||
|
reports = collections.OrderedDict()
|
||||||
for project in projects:
|
for project in projects:
|
||||||
report = cls(project, args.start, args.end, args.output_format, args.regexp, args.ignore_case)
|
report = cls(project=project, start_date=args.start,
|
||||||
report.report()
|
end_date=args.end, output_format=args.output_format,
|
||||||
|
regexp=args.regexp, ignore_case=args.ignore_case)
|
||||||
|
report_data = report.report()
|
||||||
|
reports[report.project] = (report, report_data)
|
||||||
total_time = total_time + report.total_time
|
total_time = total_time + report.total_time
|
||||||
|
cls.print_reports(reports, args.output_format, args.summary)
|
||||||
|
|
||||||
cls.summary(total_time)
|
cls.summary(total_time)
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def print_report_time_entries(report_data, output_format, summary):
|
||||||
|
''' Print time entries from report_data report using output_format.
|
||||||
|
|
||||||
|
If summary is True then the order of times (keys) is
|
||||||
|
sorted.
|
||||||
|
'''
|
||||||
|
if summary:
|
||||||
|
keys = sorted(report_data.keys())
|
||||||
|
else:
|
||||||
|
keys = report_data.keys()
|
||||||
|
for time in keys:
|
||||||
|
entries = report_data[time]
|
||||||
|
for entry in entries:
|
||||||
|
print(output_format.format_map(entry))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def print_reports(reports, output_format, summary):
|
||||||
|
''' Print reports using output_format for each entry.
|
||||||
|
|
||||||
|
If summary is True then all time entries from all
|
||||||
|
projects is extracted to one report dict.
|
||||||
|
Otherwise, all time entries by each project is printed.
|
||||||
|
'''
|
||||||
|
if summary:
|
||||||
|
summary_report = {}
|
||||||
|
for project in reports:
|
||||||
|
report, report_data = reports[project]
|
||||||
|
for time in report_data:
|
||||||
|
if summary:
|
||||||
|
if not time in summary_report:
|
||||||
|
summary_report[time] = report_data[time]
|
||||||
|
else:
|
||||||
|
summary_report[time].extend(report_data[time])
|
||||||
|
else:
|
||||||
|
report.header()
|
||||||
|
Report.print_report_time_entries(report_data,
|
||||||
|
output_format, summary)
|
||||||
|
if summary:
|
||||||
|
Report.print_report_time_entries(summary_report,
|
||||||
|
output_format, summary)
|
||||||
|
|
||||||
|
|
||||||
def _init_date(self, start_date, end_date):
|
def _init_date(self, start_date, end_date):
|
||||||
"""Setup date - either default or user given values"""
|
"""Setup date - either default or user given values"""
|
||||||
|
|
||||||
|
@ -154,10 +204,6 @@ class Report(object):
|
||||||
else:
|
else:
|
||||||
log.debug("Skipping: %s" % dirname)
|
log.debug("Skipping: %s" % dirname)
|
||||||
|
|
||||||
def report(self):
|
|
||||||
self.header()
|
|
||||||
self.list_entries()
|
|
||||||
|
|
||||||
def header(self):
|
def header(self):
|
||||||
project_name = os.path.basename(self.project)
|
project_name = os.path.basename(self.project)
|
||||||
print("Report for %s between %s and %s" %
|
print("Report for %s between %s and %s" %
|
||||||
|
@ -183,15 +229,10 @@ class Report(object):
|
||||||
return count
|
return count
|
||||||
|
|
||||||
|
|
||||||
def list_entries(self):
|
def _get_report_entry(self, time, entry):
|
||||||
"""Return total time tracked"""
|
''' Get one time entry data.
|
||||||
|
'''
|
||||||
sorted_times = sorted(self._report_db.keys())
|
|
||||||
|
|
||||||
for time in sorted_times:
|
|
||||||
entry = self._report_db[time]
|
|
||||||
report = {}
|
report = {}
|
||||||
|
|
||||||
start_datetime = datetime.datetime.strptime(time, ctt.DATETIMEFORMAT)
|
start_datetime = datetime.datetime.strptime(time, ctt.DATETIMEFORMAT)
|
||||||
delta = datetime.timedelta(seconds=int(float(entry['delta'])))
|
delta = datetime.timedelta(seconds=int(float(entry['delta'])))
|
||||||
end_datetime = (start_datetime + delta).replace(microsecond = 0)
|
end_datetime = (start_datetime + delta).replace(microsecond = 0)
|
||||||
|
@ -207,5 +248,19 @@ class Report(object):
|
||||||
report['comment'] = entry['comment']
|
report['comment'] = entry['comment']
|
||||||
else:
|
else:
|
||||||
report['comment'] = False
|
report['comment'] = False
|
||||||
|
return report
|
||||||
|
|
||||||
print(self.output_format.format_map(report))
|
|
||||||
|
def report(self):
|
||||||
|
"""Return total time tracked"""
|
||||||
|
|
||||||
|
entries = {}
|
||||||
|
time_keys = self._report_db.keys()
|
||||||
|
for time in time_keys:
|
||||||
|
entry = self._report_db[time]
|
||||||
|
report = self._get_report_entry(time, entry)
|
||||||
|
if not time in entries:
|
||||||
|
entries[time] = [report]
|
||||||
|
else:
|
||||||
|
entries[time].append(report)
|
||||||
|
return entries
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# 2012-2015 Nico Schottelius (nico-ctt at schottelius.org)
|
# 2012-2015 Nico Schottelius (nico-ctt at schottelius.org)
|
||||||
|
# 2016 Darko Poljak (darko.poljak at gmail.com)
|
||||||
#
|
#
|
||||||
# This file is part of ctt.
|
# This file is part of ctt.
|
||||||
#
|
#
|
||||||
|
@ -78,6 +79,7 @@ def parse_argv(argv, version):
|
||||||
parser['report'].add_argument("-i", "--ignore-case", help="ignore case distinctions", action="store_true")
|
parser['report'].add_argument("-i", "--ignore-case", help="ignore case distinctions", action="store_true")
|
||||||
parser['report'].add_argument("-f", "--format", help="output format (default: %s)" % ctt.REPORTFORMAT,
|
parser['report'].add_argument("-f", "--format", help="output format (default: %s)" % ctt.REPORTFORMAT,
|
||||||
default=ctt.REPORTFORMAT, dest="output_format")
|
default=ctt.REPORTFORMAT, dest="output_format")
|
||||||
|
parser['report'].add_argument("-s", "--summary", help="hie project names and list time entries in chronological order", action="store_true")
|
||||||
|
|
||||||
#parser['track'].add_argument("-t", "--tag", help="Add tags",
|
#parser['track'].add_argument("-t", "--tag", help="Add tags",
|
||||||
# action="store_true")
|
# action="store_true")
|
||||||
|
|
Loading…
Reference in a new issue