From 9adc35f78bfc6047d8c070d1bb9d2c32db7cd464 Mon Sep 17 00:00:00 2001 From: Darko Poljak Date: Mon, 7 Nov 2016 08:47:12 +0100 Subject: [PATCH 1/2] Fix summary option output. --- lib/ctt/report.py | 15 ++++++------ lib/ctt/test/test_report.py | 48 ++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/lib/ctt/report.py b/lib/ctt/report.py index b3830ec..4ad7ff8 100755 --- a/lib/ctt/report.py +++ b/lib/ctt/report.py @@ -42,7 +42,7 @@ log = logging.getLogger(__name__) class Report(object): """Create a report on tracked time""" - def __init__(self, project, start_date, end_date, + def __init__(self, project, start_date, end_date, output_format, regexp, ignore_case): self.project = project @@ -117,9 +117,10 @@ class Report(object): report.header() Report.print_report_time_entries(report_data, output_format, summary) - if summary: - Report.print_report_time_entries(summary_report, - output_format, summary) + # For summary do not print time entries. + # if summary: + # Report.print_report_time_entries(summary_report, + # output_format, summary) def _init_date(self, start_date, end_date): @@ -154,7 +155,7 @@ class Report(object): self.end_date = self.end_date.replace(hour=23,minute=59,second=59) if self.start_date >= self.end_date: - raise ctt.Error("End date must be after start date (%s >= %s)" % + raise ctt.Error("End date must be after start date (%s >= %s)" % (self.start_date, self.end_date)) def _init_report_db(self): @@ -180,7 +181,7 @@ class Report(object): if os.path.exists(comment_filename): with open(comment_filename, "r") as fd: comment = fd.read().rstrip('\n') - + # If regular expression given, but not matching, skip entry if self.regexp and not re.search(self.regexp, comment, self.search_flags): continue @@ -205,7 +206,7 @@ class Report(object): @staticmethod def summary(total_time): - hours, minutes, seconds = ctt.user_timedelta(total_time) + hours, minutes, seconds = ctt.user_timedelta(total_time) print("Total time tracked: %sh %sm %ss." % (hours, minutes, seconds)) diff --git a/lib/ctt/test/test_report.py b/lib/ctt/test/test_report.py index c715a1d..4a6e375 100755 --- a/lib/ctt/test/test_report.py +++ b/lib/ctt/test/test_report.py @@ -99,7 +99,7 @@ class ReportTestCase(ctt.test.CttTestCase): def test_print_reports(self): reports = collections.OrderedDict() for project in ('foo1', 'foo2'): - rep = report.Report(project, ('2016-04-07',), ('2016-04-08',), + rep = report.Report(project, ('2016-04-07',), ('2016-04-08',), ctt.REPORTFORMAT, None, None) report_data = rep.report() reports[project] = (rep, report_data) @@ -114,25 +114,25 @@ class ReportTestCase(ctt.test.CttTestCase): output = self._get_output() self.assertEqual(output, expected_output) - def test_print_reports_summary(self): - reports = collections.OrderedDict() - for project in ('foo1', 'foo2'): - rep = report.Report(project, ('2016-04-07',), ('2016-04-08',), - ctt.REPORTFORMAT, None, None) - report_data = rep.report() - reports[project] = (rep, report_data) - expected_output = ( - "2016-04-07-0810 (0:00:10): foo2\n" - "2016-04-07-0826 (0:00:06): foo1\n" - "2016-04-08-1200 (1:23:20): foo1 12" - ) - rep.print_reports(reports, ctt.REPORTFORMAT, summary=True) - output = self._get_output() - self.assertEqual(output, expected_output) - + # Summary should not print time entries + # def test_print_reports_summary(self): + # reports = collections.OrderedDict() + # for project in ('foo1', 'foo2'): + # rep = report.Report(project, ('2016-04-07',), ('2016-04-08',), + # ctt.REPORTFORMAT, None, None) + # report_data = rep.report() + # reports[project] = (rep, report_data) + # expected_output = ( + # "2016-04-07-0810 (0:00:10): foo2\n" + # "2016-04-07-0826 (0:00:06): foo1\n" + # "2016-04-08-1200 (1:23:20): foo1 12" + # ) + # rep.print_reports(reports, ctt.REPORTFORMAT, summary=True) + # output = self._get_output() + # self.assertEqual(output, expected_output) def test__init_date(self): - rep = report.Report('foo1', ('2016-04-07',), ('2016-04-07',), + rep = report.Report('foo1', ('2016-04-07',), ('2016-04-07',), ctt.REPORTFORMAT, None, None) expected_start_date = datetime.datetime(2016, 4, 7) expected_end_date = datetime.datetime(2016, 4, 7, 23, 59, 59) @@ -141,7 +141,7 @@ class ReportTestCase(ctt.test.CttTestCase): @unittest.expectedFailure def test__init_date_fail(self): - rep = report.Report('foo1', ('2016-04-08',), ('2016-04-07',), + rep = report.Report('foo1', ('2016-04-08',), ('2016-04-07',), ctt.REPORTFORMAT, None, None) def test__init_date_defaults(self): @@ -158,11 +158,11 @@ class ReportTestCase(ctt.test.CttTestCase): @unittest.expectedFailure def test__init_report_db_fail(self): - rep = report.Report('unexisting', ('2016-04-07',), ('2016-04-07',), + rep = report.Report('unexisting', ('2016-04-07',), ('2016-04-07',), ctt.REPORTFORMAT, None, None) def test__init_report_db(self): - rep = report.Report('foo1', ('2016-04-07',), ('2016-04-07',), + rep = report.Report('foo1', ('2016-04-07',), ('2016-04-07',), ctt.REPORTFORMAT, None, None) expected_db = { '2016-04-07-0826': { @@ -173,7 +173,7 @@ class ReportTestCase(ctt.test.CttTestCase): self.assertEqual(rep._report_db, expected_db) def test_header(self): - rep = report.Report('foo1', ('2016-04-07',), ('2016-04-07',), + rep = report.Report('foo1', ('2016-04-07',), ('2016-04-07',), ctt.REPORTFORMAT, None, None) rep.header() output = self._get_output() @@ -186,14 +186,14 @@ class ReportTestCase(ctt.test.CttTestCase): self.assertEqual(output, "Total time tracked: 0h 0m 10s.") def test_total_time(self): - rep = report.Report('foo1', ('2016-04-07',), ('2016-04-07',), + rep = report.Report('foo1', ('2016-04-07',), ('2016-04-07',), ctt.REPORTFORMAT, None, None) total_time = rep.total_time expected_total_time = 6.248274 self.assertEqual(total_time, expected_total_time) def test_report(self): - rep = report.Report('foo1', ('2016-04-07',), ('2016-04-08',), + rep = report.Report('foo1', ('2016-04-07',), ('2016-04-08',), ctt.REPORTFORMAT, None, None) expected_entries = { '2016-04-07-0826': [ From bfded4d90345ea41aba7aa1ba2d1aa1c2f97db38 Mon Sep 17 00:00:00 2001 From: Darko Poljak Date: Mon, 7 Nov 2016 09:18:08 +0100 Subject: [PATCH 2/2] pep8 --- lib/ctt/__init__.py | 8 ++- lib/ctt/listprojects.py | 2 +- lib/ctt/report.py | 81 +++++++++++---------- lib/ctt/test/__init__.py | 4 +- lib/ctt/test/test_listprojects.py | 5 +- lib/ctt/test/test_report.py | 112 ++++++++++++++++-------------- lib/ctt/test/test_tracker.py | 31 +++++---- lib/ctt/tracker.py | 18 ++--- scripts/ctt | 75 +++++++++++++------- setup.py | 7 +- 10 files changed, 194 insertions(+), 149 deletions(-) diff --git a/lib/ctt/__init__.py b/lib/ctt/__init__.py index f8b9572..d37356c 100644 --- a/lib/ctt/__init__.py +++ b/lib/ctt/__init__.py @@ -36,11 +36,13 @@ MAIL = 'nico-ctt at schottelius.org' WWW = 'http://www.nico.schottelius.org/software/ctt/' # Name of the folder to create - should not contain special characters # to ensure cross-os compatibility -DISKFORMAT = DATETIMEFORMAT +DISKFORMAT = DATETIMEFORMAT + class Error(Exception): pass + # Our output format def user_timedelta(seconds): """Format timedelta for the user""" @@ -59,15 +61,17 @@ def user_timedelta(seconds): return (hours, minutes, seconds) + def ctt_dir(): home = os.environ['HOME'] ctt_dir = os.path.join(home, ".ctt") return ctt_dir + def project_dir(project): project_dir = os.path.join(ctt_dir(), project) return project_dir - return os.listdir(ctt_dir) + # return os.listdir(ctt_dir) diff --git a/lib/ctt/listprojects.py b/lib/ctt/listprojects.py index c4d0d87..95bbe26 100755 --- a/lib/ctt/listprojects.py +++ b/lib/ctt/listprojects.py @@ -26,6 +26,7 @@ import os log = logging.getLogger(__name__) + class ListProjects(object): """Return existing projects""" @@ -33,7 +34,6 @@ class ListProjects(object): def commandline(cls, args): cls.print_projects() - @classmethod def print_projects(cls): for project in cls.list_projects(): diff --git a/lib/ctt/report.py b/lib/ctt/report.py index 4ad7ff8..aabb0c5 100755 --- a/lib/ctt/report.py +++ b/lib/ctt/report.py @@ -21,16 +21,13 @@ # # -import calendar import datetime import logging -import time import os import os.path import re -import sys import glob import collections @@ -39,11 +36,12 @@ import ctt.listprojects log = logging.getLogger(__name__) + class Report(object): """Create a report on tracked time""" def __init__(self, project, start_date, end_date, - output_format, regexp, ignore_case): + output_format, regexp, ignore_case): self.project = project self.project_dir = ctt.project_dir(self.project) @@ -63,7 +61,7 @@ class Report(object): def commandline(cls, args): # Report time for all projects if args.all: - projects=ctt.listprojects.ListProjects.list_projects() + projects = ctt.listprojects.ListProjects.list_projects() else: projects = [] @@ -75,8 +73,8 @@ class Report(object): reports = collections.OrderedDict() for project in projects: report = cls(project=project, start_date=args.start, - end_date=args.end, output_format=args.output_format, - regexp=args.regexp, ignore_case=args.ignore_case) + 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 @@ -84,7 +82,6 @@ class Report(object): 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. @@ -109,54 +106,58 @@ class Report(object): report, report_data = reports[project] if summary: for time in report_data: - if not time in summary_report: + if time not 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) + output_format, summary) # For summary do not print time entries. # if summary: # Report.print_report_time_entries(summary_report, # output_format, summary) - def _init_date(self, start_date, end_date): """Setup date - either default or user given values""" - now = datetime.datetime.now() - first_day_this_month = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0) - next_month = first_day_this_month.replace(day=28) + datetime.timedelta(days=4) + first_day_this_month = now.replace( + day=1, hour=0, minute=0, second=0, microsecond=0) + next_month = first_day_this_month.replace( + day=28) + datetime.timedelta(days=4) first_day_next_month = next_month.replace(day=1) - last_day_this_month = first_day_next_month - datetime.timedelta(seconds=1) + last_day_this_month = first_day_next_month - datetime.timedelta( + seconds=1) default_start_date = first_day_this_month default_end_date = last_day_this_month - #default_end_date = first_day - datetime.timedelta(days=1) - #default_start_date = default_end_date.replace(day=1) + # default_end_date = first_day - datetime.timedelta(days=1) + # default_start_date = default_end_date.replace(day=1) try: if start_date: - self.start_date = datetime.datetime.strptime(start_date[0], ctt.DATEFORMAT) + self.start_date = datetime.datetime.strptime( + start_date[0], ctt.DATEFORMAT) else: self.start_date = default_start_date if end_date: - self.end_date = datetime.datetime.strptime(end_date[0], ctt.DATEFORMAT) + self.end_date = datetime.datetime.strptime( + end_date[0], ctt.DATEFORMAT) else: self.end_date = default_end_date except ValueError as e: raise ctt.Error(e) - self.end_date = self.end_date.replace(hour=23,minute=59,second=59) + self.end_date = self.end_date.replace( + hour=23, minute=59, second=59) if self.start_date >= self.end_date: raise ctt.Error("End date must be after start date (%s >= %s)" % - (self.start_date, self.end_date)) + (self.start_date, self.end_date)) def _init_report_db(self): """Read all contents from db""" @@ -168,13 +169,19 @@ class Report(object): for dirname in os.listdir(self.project_dir): log.debug("Dirname: %s" % dirname) try: - dir_datetime = datetime.datetime.strptime(dirname, ctt.DISKFORMAT) + dir_datetime = datetime.datetime.strptime( + dirname, ctt.DISKFORMAT) except ValueError: - raise ctt.Error("Invalid time entry {entry} for project {project}, aborting!".format(entry=dirname, project=self.project)) + raise ctt.Error(("Invalid time entry {entry} for project " + "{project}, aborting!").format( + entry=dirname, project=self.project)) - if dir_datetime >= self.start_date and dir_datetime <= self.end_date: - filename = os.path.join(self.project_dir, dirname, ctt.FILE_DELTA) - comment_filename = os.path.join(self.project_dir, dirname, ctt.FILE_COMMENT) + if (dir_datetime >= self.start_date and + dir_datetime <= self.end_date): + filename = os.path.join( + self.project_dir, dirname, ctt.FILE_DELTA) + comment_filename = os.path.join( + self.project_dir, dirname, ctt.FILE_COMMENT) # Check for matching comment comment = None @@ -183,10 +190,11 @@ class Report(object): comment = fd.read().rstrip('\n') # If regular expression given, but not matching, skip entry - if self.regexp and not re.search(self.regexp, comment, self.search_flags): + if (self.regexp and + not re.search(self.regexp, comment, + self.search_flags)): continue - self._report_db[dirname] = {} if comment: self._report_db[dirname]['comment'] = comment @@ -194,7 +202,8 @@ class Report(object): with open(filename, "r") as fd: self._report_db[dirname]['delta'] = fd.read().rstrip('\n') - log.debug("Recording: %s: %s" % (dirname, self._report_db[dirname]['delta'])) + log.debug("Recording: %s: %s" + % (dirname, self._report_db[dirname]['delta'])) else: log.debug("Skipping: %s" % dirname) @@ -202,14 +211,14 @@ class Report(object): def header(self): project_name = os.path.basename(self.project) print("Report for %s between %s and %s" % - (project_name, self.start_date, self.end_date)) + (project_name, self.start_date, self.end_date)) @staticmethod def summary(total_time): hours, minutes, seconds = ctt.user_timedelta(total_time) print("Total time tracked: %sh %sm %ss." % - (hours, minutes, seconds)) + (hours, minutes, seconds)) @property def total_time(self): @@ -223,17 +232,16 @@ class Report(object): return count - def _get_report_entry(self, time, entry): ''' Get one time entry data. ''' 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']))) - end_datetime = (start_datetime + delta).replace(microsecond = 0) + end_datetime = (start_datetime + delta).replace(microsecond=0) report['start_datetime'] = start_datetime.strftime(ctt.DATETIMEFORMAT) - report['end_datetime'] = end_datetime.strftime(ctt.DATETIMEFORMAT) + report['end_datetime'] = end_datetime.strftime(ctt.DATETIMEFORMAT) report['delta'] = delta report['delta_seconds'] = int(float(entry['delta'])) @@ -245,7 +253,6 @@ class Report(object): report['comment'] = False return report - def report(self): """Return total time tracked""" @@ -254,7 +261,7 @@ class Report(object): for time in time_keys: entry = self._report_db[time] report = self._get_report_entry(time, entry) - if not time in entries: + if time not in entries: entries[time] = [report] else: entries[time].append(report) diff --git a/lib/ctt/test/__init__.py b/lib/ctt/test/__init__.py index c638736..107a24a 100644 --- a/lib/ctt/test/__init__.py +++ b/lib/ctt/test/__init__.py @@ -22,7 +22,9 @@ import os import unittest -fixtures_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "fixtures")) +fixtures_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), + "fixtures")) + class CttTestCase(unittest.TestCase): def setUp(self): diff --git a/lib/ctt/test/test_listprojects.py b/lib/ctt/test/test_listprojects.py index 17ddfe7..6425bc4 100755 --- a/lib/ctt/test/test_listprojects.py +++ b/lib/ctt/test/test_listprojects.py @@ -25,12 +25,13 @@ import ctt import ctt.listprojects as cttls import ctt.test + class ListProjectsTestCase(ctt.test.CttTestCase): def test_list_projects(self): projects = cttls.ListProjects.list_projects() - expected_projects = [ 'foo1', 'foo2', 'foo3', 'spam-eggs', - 'test-1', 'test-2', 'test-3', ] + expected_projects = ['foo1', 'foo2', 'foo3', 'spam-eggs', + 'test-1', 'test-2', 'test-3', ] gotten_projects = sorted(projects) self.assertEqual(gotten_projects, expected_projects) diff --git a/lib/ctt/test/test_report.py b/lib/ctt/test/test_report.py index 4a6e375..d6100bf 100755 --- a/lib/ctt/test/test_report.py +++ b/lib/ctt/test/test_report.py @@ -51,17 +51,17 @@ class ReportTestCase(ctt.test.CttTestCase): report_data = { '2016-04-07-0826': [ { - 'start_datetime': '2016-04-07-0826', - 'end_datetime': '2016-04-07-2359', - 'comment': 'foo1', - 'delta': '6', - 'delta_seconds': '6', - 'delta_minutes': '0', + 'start_datetime': '2016-04-07-0826', + 'end_datetime': '2016-04-07-2359', + 'comment': 'foo1', + 'delta': '6', + 'delta_seconds': '6', + 'delta_minutes': '0', }, ], } report.Report.print_report_time_entries(report_data, ctt.REPORTFORMAT, - False) + False) output = self._get_output() expected_output = "2016-04-07-0826 (6): foo1" self.assertEqual(output, expected_output) @@ -70,44 +70,46 @@ class ReportTestCase(ctt.test.CttTestCase): report_data = { '2016-04-07-0826': [ { - 'start_datetime': '2016-04-07-0826', - 'end_datetime': '2016-04-07-2359', - 'comment': 'foo1', - 'delta': '6', - 'delta_seconds': '6', - 'delta_minutes': '0', + 'start_datetime': '2016-04-07-0826', + 'end_datetime': '2016-04-07-2359', + 'comment': 'foo1', + 'delta': '6', + 'delta_seconds': '6', + 'delta_minutes': '0', }, ], '2016-04-07-0926': [ { - 'start_datetime': '2016-04-07-0926', - 'end_datetime': '2016-04-07-2359', - 'comment': 'foo12', - 'delta': '10', - 'delta_seconds': '10', - 'delta_minutes': '0', + 'start_datetime': '2016-04-07-0926', + 'end_datetime': '2016-04-07-2359', + 'comment': 'foo12', + 'delta': '10', + 'delta_seconds': '10', + 'delta_minutes': '0', }, ], } report.Report.print_report_time_entries(report_data, ctt.REPORTFORMAT, - True) + True) output = self._get_output() expected_output = ("2016-04-07-0826 (6): foo1\n" - "2016-04-07-0926 (10): foo12") + "2016-04-07-0926 (10): foo12") self.assertEqual(output, expected_output) def test_print_reports(self): reports = collections.OrderedDict() for project in ('foo1', 'foo2'): - rep = report.Report(project, ('2016-04-07',), ('2016-04-08',), - ctt.REPORTFORMAT, None, None) + rep = report.Report(project, ('2016-04-07', ), ('2016-04-08', ), + ctt.REPORTFORMAT, None, None) report_data = rep.report() reports[project] = (rep, report_data) expected_output = ( - "Report for foo1 between 2016-04-07 00:00:00 and 2016-04-08 23:59:59\n" + "Report for foo1 between 2016-04-07 00:00:00 and " + "2016-04-08 23:59:59\n" "2016-04-07-0826 (0:00:06): foo1\n" "2016-04-08-1200 (1:23:20): foo1 12\n" - "Report for foo2 between 2016-04-07 00:00:00 and 2016-04-08 23:59:59\n" + "Report for foo2 between 2016-04-07 00:00:00 and " + "2016-04-08 23:59:59\n" "2016-04-07-0810 (0:00:10): foo2" ) rep.print_reports(reports, ctt.REPORTFORMAT, summary=False) @@ -132,8 +134,8 @@ class ReportTestCase(ctt.test.CttTestCase): # self.assertEqual(output, expected_output) def test__init_date(self): - rep = report.Report('foo1', ('2016-04-07',), ('2016-04-07',), - ctt.REPORTFORMAT, None, None) + rep = report.Report('foo1', ('2016-04-07', ), ('2016-04-07', ), + ctt.REPORTFORMAT, None, None) expected_start_date = datetime.datetime(2016, 4, 7) expected_end_date = datetime.datetime(2016, 4, 7, 23, 59, 59) self.assertEqual(rep.start_date, expected_start_date) @@ -141,44 +143,46 @@ class ReportTestCase(ctt.test.CttTestCase): @unittest.expectedFailure def test__init_date_fail(self): - rep = report.Report('foo1', ('2016-04-08',), ('2016-04-07',), - ctt.REPORTFORMAT, None, None) + report.Report('foo1', ('2016-04-08', ), ('2016-04-07', ), + ctt.REPORTFORMAT, None, None) def test__init_date_defaults(self): rep = report.Report('foo1', None, None, - ctt.REPORTFORMAT, None, None) + ctt.REPORTFORMAT, None, None) now = datetime.datetime.now() expected_start_date = now.replace(day=1, hour=0, minute=0, second=0, - microsecond=0) - next_month = expected_start_date.replace(day=28) + datetime.timedelta(days=4) + microsecond=0) + next_month = expected_start_date.replace(day=28) + datetime.timedelta( + days=4) first_day_next_month = next_month.replace(day=1) - expected_end_date = first_day_next_month - datetime.timedelta(seconds=1) + expected_end_date = first_day_next_month - datetime.timedelta( + seconds=1) self.assertEqual(rep.start_date, expected_start_date) self.assertEqual(rep.end_date, expected_end_date) @unittest.expectedFailure def test__init_report_db_fail(self): - rep = report.Report('unexisting', ('2016-04-07',), ('2016-04-07',), - ctt.REPORTFORMAT, None, None) + report.Report('unexisting', ('2016-04-07',), ('2016-04-07',), + ctt.REPORTFORMAT, None, None) def test__init_report_db(self): rep = report.Report('foo1', ('2016-04-07',), ('2016-04-07',), - ctt.REPORTFORMAT, None, None) - expected_db = { - '2016-04-07-0826': { - 'comment': 'foo1', - 'delta': '6.248274' - }, + ctt.REPORTFORMAT, None, None) + expected_db = { + '2016-04-07-0826': { + 'comment': 'foo1', + 'delta': '6.248274' + }, } self.assertEqual(rep._report_db, expected_db) def test_header(self): rep = report.Report('foo1', ('2016-04-07',), ('2016-04-07',), - ctt.REPORTFORMAT, None, None) + ctt.REPORTFORMAT, None, None) rep.header() output = self._get_output() self.assertEqual(output, ("Report for foo1 between 2016-04-07 00:00:00" - " and 2016-04-07 23:59:59")) + " and 2016-04-07 23:59:59")) def test_summary(self): report.Report.summary(10) @@ -187,35 +191,35 @@ class ReportTestCase(ctt.test.CttTestCase): def test_total_time(self): rep = report.Report('foo1', ('2016-04-07',), ('2016-04-07',), - ctt.REPORTFORMAT, None, None) + ctt.REPORTFORMAT, None, None) total_time = rep.total_time - expected_total_time = 6.248274 + expected_total_time = 6.248274 self.assertEqual(total_time, expected_total_time) def test_report(self): rep = report.Report('foo1', ('2016-04-07',), ('2016-04-08',), - ctt.REPORTFORMAT, None, None) + ctt.REPORTFORMAT, None, None) expected_entries = { - '2016-04-07-0826': [ - { + '2016-04-07-0826': [ + { 'start_datetime': '2016-04-07-0826', 'end_datetime': '2016-04-07-0826', 'comment': 'foo1', 'delta': datetime.timedelta(seconds=6), 'delta_seconds': 6, 'delta_minutes': 0, - }, - ], - '2016-04-08-1200': [ - { + }, + ], + '2016-04-08-1200': [ + { 'start_datetime': '2016-04-08-1200', 'end_datetime': '2016-04-08-1323', 'comment': 'foo1 12', 'delta': datetime.timedelta(seconds=5000), 'delta_seconds': 5000, 'delta_minutes': 83, - }, - ], + }, + ], } entries = rep.report() self.assertEqual(entries, expected_entries) diff --git a/lib/ctt/test/test_tracker.py b/lib/ctt/test/test_tracker.py index c7c6caf..166c2b2 100755 --- a/lib/ctt/test/test_tracker.py +++ b/lib/ctt/test/test_tracker.py @@ -28,6 +28,7 @@ import os import datetime import shutil + class TrackerTestCase(ctt.test.CttTestCase): def setUp(self): @@ -43,7 +44,7 @@ class TrackerTestCase(ctt.test.CttTestCase): def test___init__(self): project = 'foo1' expected_project_dir = os.path.join(ctt.test.fixtures_dir, - os.path.join('.ctt', project)) + os.path.join('.ctt', project)) tracker = tr.Tracker(project) self.assertEqual(tracker.project, project) self.assertEqual(tracker.project_dir, expected_project_dir) @@ -52,31 +53,31 @@ class TrackerTestCase(ctt.test.CttTestCase): self.assertIsNone(tracker.comment) self.assertFalse(tracker._tracked_time) - tracker = tr.Tracker(project, start_datetime=('2016-04-09-0900',)) + tracker = tr.Tracker(project, start_datetime=('2016-04-09-0900', )) self.assertEqual(tracker.start_datetime, - datetime.datetime(2016, 4, 9, 9, 0)) + datetime.datetime(2016, 4, 9, 9, 0)) self.assertIsNone(tracker.end_datetime) self.assertFalse(tracker._tracked_time) - tracker = tr.Tracker(project, start_datetime=('2016-04-04-0900',), - end_datetime=('2016-04-09-2000',)) + tracker = tr.Tracker(project, start_datetime=('2016-04-04-0900', ), + end_datetime=('2016-04-09-2000',)) self.assertEqual(tracker.start_datetime, - datetime.datetime(2016, 4, 4, 9, 0)) + datetime.datetime(2016, 4, 4, 9, 0)) self.assertEqual(tracker.end_datetime, - datetime.datetime(2016, 4, 9, 20, 0)) + datetime.datetime(2016, 4, 9, 20, 0)) self.assertTrue(tracker._tracked_time) @unittest.expectedFailure def test__init__fail(self): project = 'foo1' - tracker = tr.Tracker(project, start_datetime=('2016-04-090900',)) + tr.Tracker(project, start_datetime=('2016-04-090900', )) def test_delta(self): project = 'foo1' start_dt = datetime.datetime(2016, 4, 4, 9, 0) end_dt = datetime.datetime(2016, 4, 9, 20, 0) - tracker = tr.Tracker(project, start_datetime=('2016-04-04-0900',), - end_datetime=('2016-04-09-2000',)) + tracker = tr.Tracker(project, start_datetime=('2016-04-04-0900', ), + end_datetime=('2016-04-09-2000', )) expected_delta = end_dt - start_dt tracker._tracked_time = True delta = tracker.delta(True) @@ -93,7 +94,7 @@ class TrackerTestCase(ctt.test.CttTestCase): project = 'foo1' start_dt = '2016-04-09-1730' tracker = tr.Tracker(project, start_datetime=(start_dt,), - comment=True) + comment=True) end_dt = datetime.datetime(2016, 4, 9, hour=17, minute=45) expected_delta = str(15 * 60) + '.0\n' # seconds tracker.end_datetime = end_dt @@ -102,7 +103,7 @@ class TrackerTestCase(ctt.test.CttTestCase): tracker.comment = expected_comment expected_comment += "\n" timedir = os.path.join(ctt.test.fixtures_dir, '.ctt', project, - '2016-04-09-1730') + '2016-04-09-1730') self.rm_dirs.append(timedir) if os.path.exists(timedir): shutil.rmtree(timedir) @@ -124,15 +125,15 @@ class TrackerTestCase(ctt.test.CttTestCase): project = 'foo1' start_dt = '2016-04-09-1730' tracker = tr.Tracker(project, start_datetime=(start_dt,), - comment=True) + comment=True) end_dt = datetime.datetime(2016, 4, 9, hour=17, minute=45) - expected_delta = 15 * 60 # seconds + # expected_delta = 15 * 60 # seconds tracker.end_datetime = end_dt tracker._tracked_time = True expected_comment = "test" tracker.comment = expected_comment timedir = os.path.join(ctt.test.fixtures_dir, '.ctt', project, - '2016-04-09-1730') + '2016-04-09-1730') self.rm_dirs.append(timedir) if os.path.exists(timedir): shutil.rmtree(timedir) diff --git a/lib/ctt/tracker.py b/lib/ctt/tracker.py index 389a725..994acc9 100755 --- a/lib/ctt/tracker.py +++ b/lib/ctt/tracker.py @@ -22,17 +22,17 @@ import datetime import logging -import time import os import os.path -import sys import ctt log = logging.getLogger(__name__) + class Tracker: - def __init__(self, project, start_datetime = None, end_datetime = None, comment = True): + def __init__(self, project, start_datetime=None, end_datetime=None, + comment=True): self.project = project self.project_dir = ctt.project_dir(project) @@ -42,12 +42,14 @@ class Tracker: # Setup default values try: if start_datetime: - self.start_datetime = datetime.datetime.strptime(start_datetime[0], ctt.DATETIMEFORMAT) + self.start_datetime = datetime.datetime.strptime( + start_datetime[0], ctt.DATETIMEFORMAT) else: self.start_datetime = None if end_datetime: - self.end_datetime = datetime.datetime.strptime(end_datetime[0], ctt.DATETIMEFORMAT) + self.end_datetime = datetime.datetime.strptime( + end_datetime[0], ctt.DATETIMEFORMAT) else: self.end_datetime = None except ValueError as e: @@ -56,7 +58,6 @@ class Tracker: if self.start_datetime and self.end_datetime: self._tracked_time = True - @classmethod def commandline(cls, args): tracker = cls(args.project[0], args.start, args.end, args.comment) @@ -100,13 +101,14 @@ class Tracker: if self.start_datetime >= self.end_datetime: raise ctt.Error("End date must be after start date! (%s > %s)!" % - (self.start_datetime, self.end_datetime)) + (self.start_datetime, self.end_datetime)) subdirname = self.start_datetime.strftime(ctt.DISKFORMAT) time_dir = os.path.join(self.project_dir, subdirname) if os.path.exists(time_dir): - raise ctt.Error("Already tracked time at this beginning for this project") + raise ctt.Error( + "Already tracked time at this beginning for this project") os.makedirs(time_dir, mode=0o700) diff --git a/scripts/ctt b/scripts/ctt index e9ad42b..86a5c12 100755 --- a/scripts/ctt +++ b/scripts/ctt @@ -23,65 +23,89 @@ import argparse import logging -import os.path import sys log = logging.getLogger(__name__) # Setup locale for calendar printing # Setup locale to get Timezone information? -#print(locale.getlocale()) +# print(locale.getlocale()) # Record tags + def parse_argv(argv, version): parser = {} parser['loglevel'] = argparse.ArgumentParser(add_help=False) - parser['loglevel'].add_argument('-d', '--debug', - help='set log level to debug', action='store_true', + parser['loglevel'].add_argument( + '-d', '--debug', help='set log level to debug', action='store_true', default=False) - parser['loglevel'].add_argument('-v', '--verbose', + parser['loglevel'].add_argument( + '-v', '--verbose', help='set log level to info, be more verbose', action='store_true', default=False) parser['main'] = argparse.ArgumentParser(description='ctt ' + version, - parents=[parser['loglevel']]) + parents=[parser['loglevel']]) parser['sub'] = parser['main'].add_subparsers(title="Commands") - - parser['listprojects'] = parser['sub'].add_parser('listprojects', - parents=[parser['loglevel']]) + parser['listprojects'] = parser['sub'].add_parser( + 'listprojects', parents=[parser['loglevel']]) parser['listprojects'].set_defaults(func=ListProjects.commandline) parser['track'] = parser['sub'].add_parser('track', - parents=[parser['loglevel']]) + parents=[parser['loglevel']]) parser['track'].set_defaults(func=Tracker.commandline) - parser['track'].add_argument("--sd", "--start", help="start date (default: first of this month, format: %s)" % ctt.DATEFORMAT_PLAIN, + parser['track'].add_argument( + "--sd", "--start", + help="start date (default: first of this month, format: %s)" + % ctt.DATEFORMAT_PLAIN, nargs=1, dest="start") - parser['track'].add_argument("--ed", "--end", help="end date (default: last of this month, format: %s)" % ctt.DATEFORMAT_PLAIN, + parser['track'].add_argument( + "--ed", "--end", + help="end date (default: last of this month, format: %s)" + % ctt.DATEFORMAT_PLAIN, nargs=1, default=None, dest="end") - parser['track'].add_argument("-n", "--no-comment", help="disable comment prompting after tracking", + parser['track'].add_argument( + "-n", "--no-comment", help="disable comment prompting after tracking", action='store_false', dest="comment") - parser['track'].add_argument("project", help="project to track time for", nargs=1) + parser['track'].add_argument( + "project", help="project to track time for", nargs=1) parser['report'] = parser['sub'].add_parser('report', - parents=[parser['loglevel']]) + parents=[parser['loglevel']]) parser['report'].set_defaults(func=Report.commandline) - parser['report'].add_argument("project", help="project to report time for", nargs='*') - parser['report'].add_argument("--sd", "--start", help="start date (default: first of this month, format: %s)" % ctt.DATEFORMAT_PLAIN, + parser['report'].add_argument( + "project", help="project to report time for", nargs='*') + parser['report'].add_argument( + "--sd", "--start", + help="start date (default: first of this month, format: %s)" + % ctt.DATEFORMAT_PLAIN, nargs=1, dest="start") - parser['report'].add_argument("--ed", "--end", help="end date (default: last of this month, format: %s)" % ctt.DATEFORMAT_PLAIN, + parser['report'].add_argument( + "--ed", "--end", + help="end date (default: last of this month, format: %s)" + % ctt.DATEFORMAT_PLAIN, nargs=1, default=None, dest="end") - parser['report'].add_argument("-a", "--all", help="List entries for all projects", action='store_true') - parser['report'].add_argument("-e", "--regexp", help="regular expression to match", - default=None) - 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( + "-a", "--all", help="List entries for all projects", + action='store_true') + parser['report'].add_argument( + "-e", "--regexp", help="regular expression to match", default=None) + 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, default=ctt.REPORTFORMAT, dest="output_format") - parser['report'].add_argument("-s", "--summary", help="hide project names and list time entries in chronological order", action="store_true") + parser['report'].add_argument( + "-s", "--summary", + help="hide 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") args = parser['main'].parse_args() @@ -114,6 +138,5 @@ if __name__ == "__main__": from ctt.report import Report from ctt.listprojects import ListProjects - parse_argv(sys.argv[1:], ctt.VERSION) sys.exit(0) diff --git a/setup.py b/setup.py index 38f1edf..0e707b1 100644 --- a/setup.py +++ b/setup.py @@ -4,9 +4,10 @@ script to install ctt """ import sys from setuptools import setup -sys.path.insert(0, 'lib/') import ctt +sys.path.insert(0, 'lib/') + setup(name='ctt', version=ctt.VERSION, author=ctt.AUTHOR, @@ -28,5 +29,5 @@ setup(name='ctt', 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', 'Operating System :: POSIX', 'Programming Language :: Python', - 'Requires-Python:: 3.x'] - ) + 'Requires-Python:: 3.x' + ])