def main(): parser = argparse.ArgumentParser() parser.add_argument('-l', '--logfile', nargs=1, metavar='LOGFILE', help='Path to the gtimelog logfile to be use') args = parser.parse_args() if args.logfile is not None: LogFile = set_logfile(args.logfile) else: LogFile = set_logfile() (week_first, week_last) = get_time() log_entries = TimeWindow(LogFile, week_first, week_last, virtual_midnight) total_work, _ = log_entries.totals() _, totals = log_entries.categorized_work_entries() ordered_by_time = [(time, cat) for cat, time in totals.items()] ordered_by_time.sort(reverse=True) max_cat_length = max([len(cat) for cat in totals.keys()]) line_format = ' %-' + str(max_cat_length + 4) + 's %+5s\t %.0f%%' print("\nTotal work done so far : %s\n" % format_duration_short(total_work)) print('Categories by time spent:') for time, cat in ordered_by_time: print(line_format % (cat, format_duration_short(time), time / total_work * 100))
class TestTagging (unittest.TestCase): TEST_TIMELOG = textwrap.dedent(""" 2014-05-27 10:03: arrived 2014-05-27 10:13: edx: introduce topic to new sysadmins -- edx 2014-05-27 10:30: email 2014-05-27 12:11: meeting: how to support new courses? -- edx meeting 2014-05-27 15:12: edx: write test procedure for EdX instances -- edx sysadmin 2014-05-27 17:03: cluster: set-up accounts, etc. -- sysadmin hpc 2014-05-27 17:14: support: how to run statistics on Hydra? -- support hydra 2014-05-27 17:36: off: pause ** 2014-05-27 17:38: email 2014-05-27 19:06: off: dinner & family ** 2014-05-27 22:19: cluster: fix shmmax-shmall issue -- sysadmin hpc """) def setUp(self): from gtimelog.timelog import TimeWindow self.tw = TimeWindow( filename=StringIO(self.TEST_TIMELOG), min_timestamp=datetime.datetime(2014, 5, 27, 9, 0), max_timestamp=datetime.datetime(2014, 5, 27, 23, 59), virtual_midnight=datetime.time(2, 0)) def test_TimeWindow_set_of_all_tags(self): tags = self.tw.set_of_all_tags() self.assertEqual(tags, set(['edx', 'hpc', 'hydra', 'meeting', 'support', 'sysadmin'])) def test_TimeWindow_totals_per_tag1(self): """Test aggregate time per tag, 1 entry only""" result = self.tw.totals('meeting') self.assertEqual(len(result), 2) work, slack = result self.assertEqual(work, ( # start/end times are manually extracted from the TEST_TIMELOG sample (datetime.timedelta(hours=12, minutes=11) - datetime.timedelta(hours=10, minutes=30)) )) self.assertEqual(slack, datetime.timedelta(0)) def test_TimeWindow_totals_per_tag2(self): """Test aggregate time per tag, several entries""" result = self.tw.totals('hpc') self.assertEqual(len(result), 2) work, slack = result self.assertEqual(work, ( # start/end times are manually extracted from the TEST_TIMELOG sample (datetime.timedelta(hours=17, minutes=3) - datetime.timedelta(hours=15, minutes=12)) + (datetime.timedelta(hours=22, minutes=19) - datetime.timedelta(hours=19, minutes=6)) )) self.assertEqual(slack, datetime.timedelta(0)) def test_TimeWindow__split_entry_and_tags1(self): """Test `TimeWindow._split_entry_and_tags` with simple entry""" result = self.tw._split_entry_and_tags('email') self.assertEqual(len(result), 2) self.assertEqual(result[0], 'email') self.assertEqual(result[1], set()) def test_TimeWindow__split_entry_and_tags2(self): """Test `TimeWindow._split_entry_and_tags` with simple entry and tags""" result = self.tw._split_entry_and_tags('restart CFEngine server -- sysadmin cfengine issue327') self.assertEqual(len(result), 2) self.assertEqual(result[0], 'restart CFEngine server') self.assertEqual(result[1], set(['sysadmin', 'cfengine', 'issue327'])) def test_TimeWindow__split_entry_and_tags3(self): """Test `TimeWindow._split_entry_and_tags` with category, entry, and tags""" result = self.tw._split_entry_and_tags('tooling: tagging support in gtimelog -- tooling gtimelog') self.assertEqual(len(result), 2) self.assertEqual(result[0], 'tooling: tagging support in gtimelog') self.assertEqual(result[1], set(['tooling', 'gtimelog'])) def test_TimeWindow__split_entry_and_tags4(self): """Test `TimeWindow._split_entry_and_tags` with slack-type entry""" result = self.tw._split_entry_and_tags('read news -- reading **') self.assertEqual(len(result), 2) self.assertEqual(result[0], 'read news **') self.assertEqual(result[1], set(['reading'])) def test_TimeWindow__split_entry_and_tags5(self): """Test `TimeWindow._split_entry_and_tags` with slack-type entry""" result = self.tw._split_entry_and_tags('read news -- reading ***') self.assertEqual(len(result), 2) self.assertEqual(result[0], 'read news ***') self.assertEqual(result[1], set(['reading'])) def test_Reports__report_tags(self): from gtimelog.timelog import Reports rp = Reports(self.tw) txt = StringIO() # use same tags as in tests above, so we know the totals rp._report_tags(txt, ['meeting', 'hpc']) self.assertEqual( txt.getvalue().strip(), textwrap.dedent(""" Time spent in each area: hpc 5:04 meeting 1:41 Note that area totals may not add up to the period totals, as each entry may be belong to multiple areas (or none at all). """).strip())
class TestTagging(unittest.TestCase): TEST_TIMELOG = textwrap.dedent(""" 2014-05-27 10:03: arrived 2014-05-27 10:13: edx: introduce topic to new sysadmins -- edx 2014-05-27 10:30: email 2014-05-27 12:11: meeting: how to support new courses? -- edx meeting 2014-05-27 15:12: edx: write test procedure for EdX instances -- edx sysadmin 2014-05-27 17:03: cluster: set-up accounts, etc. -- sysadmin hpc 2014-05-27 17:14: support: how to run statistics on Hydra? -- support hydra 2014-05-27 17:36: off: pause ** 2014-05-27 17:38: email 2014-05-27 19:06: off: dinner & family ** 2014-05-27 22:19: cluster: fix shmmax-shmall issue -- sysadmin hpc """) def setUp(self): from gtimelog.timelog import TimeWindow self.tw = TimeWindow( filename=StringIO(self.TEST_TIMELOG), min_timestamp=datetime.datetime(2014, 5, 27, 9, 0), max_timestamp=datetime.datetime(2014, 5, 27, 23, 59), virtual_midnight=datetime.time(2, 0)) def test_TimeWindow_set_of_all_tags(self): tags = self.tw.set_of_all_tags() self.assertEqual( tags, set(['edx', 'hpc', 'hydra', 'meeting', 'support', 'sysadmin'])) def test_TimeWindow_totals_per_tag1(self): """Test aggregate time per tag, 1 entry only""" result = self.tw.totals('meeting') self.assertEqual(len(result), 2) work, slack = result self.assertEqual( work, ( # start/end times are manually extracted from the TEST_TIMELOG sample (datetime.timedelta(hours=12, minutes=11) - datetime.timedelta(hours=10, minutes=30)))) self.assertEqual(slack, datetime.timedelta(0)) def test_TimeWindow_totals_per_tag2(self): """Test aggregate time per tag, several entries""" result = self.tw.totals('hpc') self.assertEqual(len(result), 2) work, slack = result self.assertEqual( work, ( # start/end times are manually extracted from the TEST_TIMELOG sample (datetime.timedelta(hours=17, minutes=3) - datetime.timedelta(hours=15, minutes=12)) + (datetime.timedelta(hours=22, minutes=19) - datetime.timedelta(hours=19, minutes=6)))) self.assertEqual(slack, datetime.timedelta(0)) def test_TimeWindow__split_entry_and_tags1(self): """Test `TimeWindow._split_entry_and_tags` with simple entry""" result = self.tw._split_entry_and_tags('email') self.assertEqual(len(result), 2) self.assertEqual(result[0], 'email') self.assertEqual(result[1], set()) def test_TimeWindow__split_entry_and_tags2(self): """Test `TimeWindow._split_entry_and_tags` with simple entry and tags""" result = self.tw._split_entry_and_tags( 'restart CFEngine server -- sysadmin cfengine issue327') self.assertEqual(len(result), 2) self.assertEqual(result[0], 'restart CFEngine server') self.assertEqual(result[1], set(['sysadmin', 'cfengine', 'issue327'])) def test_TimeWindow__split_entry_and_tags3(self): """Test `TimeWindow._split_entry_and_tags` with category, entry, and tags""" result = self.tw._split_entry_and_tags( 'tooling: tagging support in gtimelog -- tooling gtimelog') self.assertEqual(len(result), 2) self.assertEqual(result[0], 'tooling: tagging support in gtimelog') self.assertEqual(result[1], set(['tooling', 'gtimelog'])) def test_TimeWindow__split_entry_and_tags4(self): """Test `TimeWindow._split_entry_and_tags` with slack-type entry""" result = self.tw._split_entry_and_tags('read news -- reading **') self.assertEqual(len(result), 2) self.assertEqual(result[0], 'read news **') self.assertEqual(result[1], set(['reading'])) def test_Reports__report_tags(self): from gtimelog.timelog import Reports rp = Reports(self.tw) txt = StringIO() # use same tags as in tests above, so we know the totals rp._report_tags(txt, ['meeting', 'hpc']) self.assertEqual( txt.getvalue().strip(), textwrap.dedent(""" Time spent in each area: hpc 5:04 meeting 1:41 Note that area totals may not add up to the period totals, as each entry may be belong to multiple areas (or none at all). """).strip())
def main(): parser = argparse.ArgumentParser() parser.add_argument('-l', '--logfile', nargs=1, metavar='LOGFILE', help='Path to the gtimelog logfile to be use') parser.add_argument('-u', '--user', nargs=1, metavar='USER', help='User Identification to be used for report') parser.add_argument('-n', '--no-time', help='Print weekly report without spent time', action='store_true') parser.add_argument('-m', '--minutes', help='Print weekly report with spent time in minutes', action='store_true') args = parser.parse_args() if args.logfile is not None: LogFile = set_logfile(args.logfile) else: LogFile = set_logfile() if args.user is not None: UserId = set_userid(args.user) else: UserId = set_userid() (week_first, week_last) = get_time() log_entries = TimeWindow(LogFile, week_first, week_last, virtual_midnight) total_work, _ = log_entries.totals() entries, totals = log_entries.categorized_work_entries() print("[ACTIVITY] %s to %s (%s)" % (week_first.isoformat().split("T")[0], week_last.isoformat().split("T")[0], UserId)) if entries: if None in entries: categories = sorted(entries) categories.append('No category') entries['No category'] = e t = totals.pop(None) totals['No category'] = t else: categories = sorted(entries) for cat in categories: print('%s:' % cat) work = [(entry, duration) for start, entry, duration in entries[cat]] work.sort() for entry, duration in work: if not duration: continue # skip empty "arrival" entries entry = entry[:1].upper() + entry[1:] if args.no_time: print(u" %-61s " % entry) else: if args.minutes: print(u" %-61s %+5s %+4s" % (entry, format_duration_short(duration), as_minutes(duration))) else: print(u" %-61s %+5s" % (entry, format_duration_short(duration))) if args.no_time: print("") else: if args.minutes: print('-' * 75) print(u"%+70s %4s" % (format_duration_short( totals[cat]), as_minutes(totals[cat]))) else: print('-' * 70) print(u"%+70s" % (format_duration_short(totals[cat]))) print("Total work done : %s" % format_duration_short(total_work))