summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlasdair Colley <ac@brede.(none)>2011-11-01 11:23:23 +0000
committerAlasdair Colley <ac@brede.(none)>2011-11-01 11:23:23 +0000
commit48fa0864aaa9c9f79e90b3db4a85081b0c1bce58 (patch)
tree0f13ac5a77b7567a4299a95ee5ea2f5f75ece4a2
parente21b21808507c3deb6d828662d53d078921a335e (diff)
New admin/user options allowing addition of custom events from command line
-rw-r--r--perc248
-rw-r--r--perc.cfg73
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"
}
}
}