From 48fa0864aaa9c9f79e90b3db4a85081b0c1bce58 Mon Sep 17 00:00:00 2001 From: Alasdair Colley Date: Tue, 1 Nov 2011 11:23:23 +0000 Subject: New admin/user options allowing addition of custom events from command line --- perc | 248 ++++++++++++++++++++++----------------------------------------- perc.cfg | 73 +++++++++---------- 2 files changed, 121 insertions(+), 200 deletions(-) diff --git a/perc b/perc index 7419476..366043c 100644 --- a/perc +++ b/perc @@ -40,10 +40,10 @@ import re import string import sys -from datetime import datetime, date +from datetime import datetime, date, timedelta, time PROG = "perc" -VERSION = "3.23" +VERSION = "3.3" CONFIG_FILE = "perc.cfg" @@ -52,7 +52,6 @@ NOW = datetime.now() MODES = ["user", "admin"] USER = None -NICK = "default" CONFIG = {} CONFIG_IS_DIRTY = False @@ -199,20 +198,17 @@ def isTime(timestr): return False def getDayOfWeek(day): - return (NOW - day_of_week() * datetime.timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0) + day * datetime.timedelta(days=1) + return (NOW - day_of_week() * timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0) + day * timedelta(days=1) -def parseTemporalEvent(event): +def parseTemporalEvent(event, user): start, finish = None, None - - work_start = datetime.combine(NOW.date(), datetime.strptime(CONFIG["DEFAULTS"][NICK]["start"], "%H:%M").time()) - work_finish = datetime.combine(NOW.date(), datetime.strptime(CONFIG["DEFAULTS"][NICK]["finish"], "%H:%M").time()) if event == "tomorrow": start = NOW.replace(hour=0, minute=0, second=0, microsecond=0) finish = NOW.replace(day=NOW.day + 1, hour=0, minute=0, second=0, microsecond=0) start_formatted = WEEK_DAY_NAMES[day_of_week()] - finish_formatted = WEEK_DAY_NAMES[day_of_week(date.today() + datetime.timedelta(days=1))] + finish_formatted = WEEK_DAY_NAMES[day_of_week(date.today() + timedelta(days=1))] elif event in ["christmas", "xmas"]: start = NOW.replace(year=NOW.year - 1, month=12, day=25, hour=0, minute=0, second=0, microsecond=0) finish = NOW.replace(year=NOW.year, month=12, day=25, hour=0, minute=0, second=0, microsecond=0) @@ -229,8 +225,8 @@ def parseTemporalEvent(event): start = getDayOfWeek(MONDAY) finish = getDayOfWeek(FRIDAY) - start = datetime.combine(start.date(), work_start.time()) - finish = datetime.combine(finish.date(), work_finish.time()) + start = datetime.combine(start.date(), user.start.time()) + finish = datetime.combine(finish.date(), user.finish.time()) start_formatted = "Monday" finish_formatted = "Weekend" @@ -238,7 +234,7 @@ def parseTemporalEvent(event): start = getDayOfWeek(MONDAY) finish = getDayOfWeek(FRIDAY) - start = datetime.combine(start.date(), work_start.time()) + start = datetime.combine(start.date(), user.start.time()) start_formatted = "Monday" finish_formatted = "Friday" @@ -255,21 +251,16 @@ def parseTemporalEvent(event): start_formatted = "Halloween %d" % start.year finish_formatted = "Halloween %d" % finish.year elif event == "lunch": - - lunch_start = datetime.combine(NOW.date(), datetime.strptime(CONFIG["DEFAULTS"][NICK]["lunch"]["start"]).time()) - lunch_finish = datetime.combine(NOW.date(), datetime.strptime(CONFIG["DEFAULTS"][NICK]["lunch"]["finish"]).time()) - format = CONFIG["DEFAULTS"][NICK]["format"] - if NOW < lunch_start: start = work_start - finish = lunch_start + finish = user.lunch.start - finish_formatted = "Lunch (%s)" % finish.strftime(format) + finish_formatted = "Lunch (%s)" % finish.strftime(user.format) else: - start = lunch_start - finish = lunch_finish + start = user.lunch.start + finish = user.lunch.finish - finish_formatted = finish.strftime(format) + finish_formatted = finish.strftime(user.format) start_formatted = start.strftime(format) elif event in CONFIG["CUSTOM_EVENTS"]: @@ -318,44 +309,6 @@ def parseDatetime(datetimestring): print "Not a recognised date/time '%s'" % datetimestring sys.exit(1) -def setUser(name, start=None, finish=None, format=None, output=None): - user = {} - - if name in CONFIG["DEFAULTS"]: - if NICK != name: - print "Cannot edit someone else's perc settings!" - sys.exit(1) - - user = CONFIG["DEFAULTS"][name] - - if start: - user["start"] = start.strftime("%H:%M") - if finish: - user["finish"] = finish.strftime("%H:%M") - if format: - user["format"] = format - if output: - user["output"] = output - - CONFIG["DEFAULTS"][name] = user - -def setUserLunch(name, start=None, finish=None): - if name not in CONFIG["DEFAULTS"]: - print "User must be added to the config first using -u command" - sys.exit(1) - - if NICK != name: - print "Cannot edit someone else's perc settings!" - sys.exit(1) - - lunch = CONFIG["DEFAULTS"][name]["lunch"] - if start: - lunch["start"] = start - if finish: - lunch["finish"] = finish - - CONFIG["DEFAULTS"][name]["lunch"] = lunch - def addEvent(name, start, finish, format="{name} %Y"): if start > finish: print "Event cannot have a start time later than the finish" @@ -386,7 +339,7 @@ def parseUserArgs(args, user): start, finish, start_formatted, finish_formatted = user.start, user.finish, user.start.strftime(user.format), user.finish.strftime(user.format) if args and isImportantTemporalEvent(args[0].lower()): - start, finish, start_formatted, finish_formatted = parseTemporalEvent(args[0].lower()) + start, finish, start_formatted, finish_formatted = parseTemporalEvent(args[0].lower(), user) else: format = None times = args[0:1] @@ -461,6 +414,31 @@ class Output(object): func(ratio, start, finish) +class TimeRange(object): + + def __init__(self, start, finish, formatter): + self._start = start + self._finish = finish + self.formatter = formatter + + def __datetimeGetter(self, name): + return datetime.combine(NOW.date(), datetime.strptime(getattr(self, name), "%H:%M").time()) + + @property + def start(self): + return self.__datetimeGetter("_start") + + @property + def finish(self): + return self.__datetimeGetter("_finish") + + @property + def format(self): + return self.formatter.format + + def toDict(self): + return { "start": self._start, "finish": self._finish } + class User(object): PROPERTIES = ["start", "finish", "format", "output", "lunch"] @@ -470,10 +448,28 @@ class User(object): def __init__(self, name, data=None): self._name = name if data: - self.data = copy.deepcopy(data) + self.data = self.__parseData(data) else: self.data = {} + def __parseData(self, data): + data = copy.deepcopy(data) + + for key, value in data.items(): + if isinstance(value, dict) and set(["start", "finish"]).issubset(set(value.keys())): + data[key] = TimeRange(value["start"], value["finish"], self) + + return data + + def __convertToDict(self): + data = copy.deepcopy(self.data) + + for key, value in data.items(): + if isinstance(value, TimeRange): + data[key] = value.toDict() + + return data + def commit(self): if self.Name in CONFIG["DEFAULTS"] and USER.Name != self.Name: print "Cannot edit someone else's perc settings!" @@ -483,7 +479,7 @@ class User(object): print "Cannot edit default user" sys.exit(1) - CONFIG["DEFAULTS"][self.Name] = self.data + CONFIG["DEFAULTS"][self.Name] = self.__convertToDict(self.data) CONFIG_IS_DIRTY = True @@ -497,7 +493,10 @@ class User(object): self._data[name] = value def __defaultDeleter(self, name): - del self._data[name] + try: + del self._data[name] + except KeyError: + pass def __defaultGetter(self, name): try: @@ -506,97 +505,28 @@ class User(object): return CONFIG["DEFAULTS"]["default"][name] def __getattr__(self, name): - if name not in User.PROPERTIES: - raise NameError() - - if name in ["start", "finish"]: - return self.__datetimeGetter(name) - elif name in ["format", "output"]: - return self.__defaultGetter(name) - elif name == "lunch": - pass + if name in User.PROPERTIES: + if name in ["start", "finish"]: + return self.__datetimeGetter(name) + else: + return self.__defaultGetter(name) + else: + return self.__getattribute__(name) def __setattr__(self, name, value): - if name not in User.PROPERTIES: - raise NameError() - - @property - def start(self): - try: - return datetime.combine(NOW.date(), datetime.strptime(self.data["start"], "%H:%M").time()) - except KeyError: - return CONFIG["DEFAULTS"]["default"]["start"] - - @start.setter - def start(self, value): - self.data["start"] = value - - @start.deleter - def start(self): - del self.data["start"] - - @property - def finish(self): - try: - return datetime.combine(NOW.date(), datetime.strptime(self.data["finish"], "%H:%M").time()) - except KeyError: - return CONFIG["DEFAULTS"]["default"]["finish"] - - @finish.setter - def finish(self, value): - self.data["finish"] = value - - @finish.deleter - def finish(self): - del self.data["finish"] - - @property - def format(self): - try: - return self.data["format"] - except KeyError: - return CONFIG["DEFAULTS"]["default"]["format"] - - @format.setter - def format(self, value): - self.data["format"] = value - - @format.deleter - def format(self): - del self.data["format"] - - @property - def output(self): - try: - return self.data["output"] - except KeyError: - return CONFIG["DEFAULTS"]["default"]["output"] - - @output.setter - def output(self, value): - self.data["output"] = value - - @output.deleter - def output(self): - del self.data["output"] - - @property - def lunch(self): - try: - return self.data["lunch"] - except KeyError: - return CONFIG["DEFAULTS"]["default"]["lunch"] - - @lunch.setter - def lunch(self, value): - self.data["lunch"] = value + if name in User.PROPERTIES: + self.__defaultSetter(name, value) + else: + super(User, self).__setattr__(name, value) - @lunch.deleter - def lunch(self): - del self.data["lunch"] + def __delattr__(self, name): + if name in User.PROPERTIES: + self.__defaultDeleter(name) + else: + super(User, self).__delattr__(name) def admin(args): - if NICK not in CONFIG["ADMINS"]: + if USER.Name not in CONFIG["ADMINS"]: print "You do not have admin permissions" sys.exit(1) @@ -620,8 +550,8 @@ def admin(args): sys.exit(0) if options.user: - - else + pass + else: if options.add_event: if not options.start or not options.finish: print "--add-event option requires --start and --finish date/time options to be set" @@ -658,6 +588,7 @@ def user(args): print "v%s" % VERSION sys.exit(0) + # Choose which user to display percentages for user = USER if options.nick: nick = options.nick.lower() @@ -665,6 +596,7 @@ def user(args): start, finish, ratio, output_type = parseUserArgs(args, user) + # Finally output the percentage in the specified way output = Output() output.output(output_type, ratio, start, finish) @@ -678,21 +610,15 @@ def main(): args = sys.argv[1:] if "perc" in args: args.remove("perc") - -# global NICK -# if args: -# NICK = args.pop(0).lower() -# else: -# NICK = "default" -# -# if NICK not in CONFIG["DEFAULTS"]: -# NICK = "default" + + # Set the user variable to the user who ran the script global USER USER = User("default") if args: nick = args.pop(0).lower() USER = User(nick, CONFIG["DEFAULTS"].get(nick)) + # Obtain the mode if set, otherwise default to 'user' mode = "user" if args: if args[0] in MODES: diff --git a/perc.cfg b/perc.cfg index 018f379..454a9a8 100644 --- a/perc.cfg +++ b/perc.cfg @@ -6,9 +6,9 @@ }, "time": { "12hour": "%I:%M%p", - "civilian": "%H:%M", + "military": "%H%M", "12houronly": "%I%p", - "military": "%H%M" + "civilian": "%H:%M" } }, "RATIO_SIGFIGS": 3, @@ -17,8 +17,8 @@ "bondroid", "bottlecap", "carpnet", - "daveg", - "dhm", + "daveg", + "dhm", "dsk", "fbeans", "sbeans", @@ -32,121 +32,121 @@ "DEFAULTS": { "daveg": { "start": "07:30", - "format": "%H:%M", "finish": "18:00", + "output": "bar", "lunch": { "start": "12:30", "finish": "13:00" }, - "output": "bar" + "format": "%H:%M" }, "bikeman": { "start": "09:00", - "format": "%I%p", "finish": "17:00", + "output": "bar", "lunch": { "start": "13:00", "finish": "14:00" }, - "output": "bar" + "format": "%I%p" }, "wjoe": { "start": "09:00", - "format": "%I%p", "finish": "17:00", + "output": "bar", "lunch": { "start": "12:00", "finish": "13:00" }, - "output": "bar" + "format": "%I%p" }, "default": { "start": "09:00", - "format": "%H:%M", "finish": "17:00", + "output": "bar", "lunch": { "start": "13:00", "finish": "14:00" }, - "output": "bar" + "format": "%H:%M" }, - "l_bratch": { - "start": "08:30", - "format": "%H:%M", - "finish": "17:00", + "jagw": { + "start": "09:00", + "finish": "18:00", + "output": "bar", "lunch": { "start": "13:00", "finish": "14:00" }, - "output": "bar" + "format": "%I%p" }, "bottlecap": { "start": "09:00", - "format": "%H:%M", "finish": "17:30", + "output": "bar", "lunch": { "start": "13:00", "finish": "14:00" }, - "output": "bar" + "format": "%H:%M" }, "carpnet": { "start": "10:00", - "format": "%H:%M", "finish": "19:00", + "output": "bar", "lunch": { "start": "13:00", "finish": "14:00" }, - "output": "bar" + "format": "%H:%M" }, "miniwork": { "start": "09:00", - "format": "%H:%M", "finish": "17:30", + "output": "bar", "lunch": { "start": "13:00", "finish": "14:00" }, - "output": "bar" + "format": "%H:%M" }, "otherlw": { "start": "10:00", - "format": "%H:%M", "finish": "19:00", + "output": "bar", "lunch": { "start": "13:00", "finish": "14:00" }, - "output": "bar" + "format": "%H:%M" }, - "jagw": { - "start": "09:00", - "format": "%I%p", - "finish": "18:00", + "l_bratch": { + "start": "08:30", + "finish": "17:00", + "output": "bar", "lunch": { "start": "13:00", "finish": "14:00" }, - "output": "bar" + "format": "%H:%M" }, "sbeans": { "start": "09:00", - "format": "%H:%M", "finish": "17:30", + "output": "bar", "lunch": { "start": "13:00", "finish": "14:00" }, - "output": "bar" + "format": "%H:%M" } }, "OUTPUT": { "PERCENTAGE": "{ratio:.2%} {finish} ({start} start)", "BAR": { - "character": "-", + "length_mobile": 30, "length": 40, - "length_mobile": 30 + "character": "-" } }, "CUSTOM_EVENTS": { @@ -159,11 +159,6 @@ "start": "2011-09-04 18:00", "finish": "2011-11-11 20:00", "format": "{name} (%y-%m-%d %H:%M)" - }, - "birth": { - "start": "2011-03-28 10:00", - "finish": "2012-03-28 00:00", - "format": "{name} %Y" } } } -- cgit v1.2.3