cronrec.py
author Eugen Sawin <sawine@me73.com>
Wed, 06 Oct 2010 16:07:36 +0200
changeset 13 4ef9c2142059
parent 12 28c80ae695dc
permissions -rwxr-xr-x
Added set rate command.
     1 #!/usr/local/bin/python
     2 # -*- coding: utf-8 -*-
     3 
     4 """
     5 tim - A time recording tool, because time is money.
     6 Author: Eugen Sawin (sawine@me73.com)
     7 Dependencies: Python 2.7 and libsqlite3-dev
     8 """
     9 
    10 import os
    11 import sys
    12 import argparse
    13 from datetime import datetime
    14 
    15 import db
    16 
    17 WD = "working_path"
    18 CONFIG = {WD: str}
    19 CONFIG_SEP = "="
    20 DB_FILE = "tim.db"
    21 
    22 CURRENCIES = {("EUR", "EURO", "€"): "EUR",
    23 ("US DOLLAR", "USD", "$"): "USD"}
    24 
    25 RATE_TYPES = {("h", "hourly"): "hourly"}
    26 
    27 config = {}
    28 
    29 # Try to get the user's home directory path
    30 try: # Windows
    31 	from win32com.shell import shellcon, shell
    32 	HOMEDIR	= shell.SHGetFolderPath(0, shellcon.CSIDL_LOCAL_APPDATA, 0, 0)
    33 except ImportError: # Linux (hopefully)
    34 	HOMEDIR = os.path.expanduser("~")
    35 
    36 CONFIG_FILE = "%s/.timrc" % HOMEDIR
    37 
    38 DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
    39 
    40 def read_config():
    41 	config = {}
    42 	with open(CONFIG_FILE, "r") as config_stream:
    43 		config_lines = [l.split(CONFIG_SEP) for l in config_stream.readlines() 
    44 						if CONFIG_SEP in l]
    45 		for key, value in config_lines:
    46 			key = key.strip().lower()
    47 			value = value.strip()
    48 			if key in CONFIG:
    49 				config[key] = CONFIG[key](value)
    50 	return config
    51 
    52 def write_config(config):
    53 	with open(CONFIG_FILE, "w") as config_input:
    54 		config_input.write("\n".join([CONFIG_SEP.join((k, v)) 
    55 							for k, v in config.iteritems() if k in CONFIG]))
    56 
    57 def db_file():
    58 	global config
    59 	if WD not in config:
    60 		print "Working directory path is not configured. \
    61 Please use the init command."
    62 		return None
    63 	return config[WD] + "/" + DB_FILE
    64 	
    65 def init(args):
    66 	global config
    67 	last_wd = None
    68 	if WD in config:
    69 		last_wd = config[WD]
    70 	config[WD] = args.working_path
    71 	write_config(config)
    72 	path_exists = os.path.exists(config[WD]) and os.path.isdir(config[WD])
    73 	db_exists = path_exists and os.path.exists(db_file())\
    74 				and os.path.isfile(db_file())
    75 	if last_wd != config[WD]:		
    76 		print "Changed working directory from %s to %s." % (last_wd, config[WD])
    77 	else:
    78 		print "Working directory remains at %s." % config[WD]
    79 	if not path_exists:
    80 		print "Warning: working directory %s does not exist." % config[WD]
    81 		os.makedirs(config[WD])
    82 		print "Working directory %s created." % config[WD]
    83 	elif db_exists:
    84 		print "Database file %s already exists, please delete it before \
    85 initiating a new database at this location." % db_file()
    86 	if not db_exists:
    87 		db.init(db_file())	
    88 
    89 def parse_label(label):
    90 	label = label.strip()
    91 	if ":" in label:
    92 		project, activity = label.split(":")
    93 	else:
    94 		project, activity = (label, None)
    95 	return project, activity
    96 
    97 def begin(args):
    98 	project, activity = parse_label(args.label)
    99 	time = datetime.now()
   100 	db.resume(db_file(), None, None, time)
   101 	db.begin(db_file(), project, activity, time)	
   102     
   103 def end(args):
   104 	project, activity = parse_label(args.label)
   105 	log = args.m	
   106 	time = datetime.now()
   107 	db.resume(db_file(), db.find_active_task(db_file()), time, log)
   108 	db.end(db_file(), project, activity, time, log)	
   109 
   110 def pause(args):
   111 	db.pause(db_file(), datetime.now())	 
   112 
   113 def resume(args):
   114 	db.resume(db_file(), None, datetime.now(), args.m)	
   115 
   116 def add_task(args):
   117 	project, activity = parse_label(args.label)
   118 	log = args.m
   119 	begin = datetime.strptime(args.begin, DATETIME_FORMAT)
   120 	end = datetime.strptime(args.end, DATETIME_FORMAT)
   121 	db.begin(db_file(), project, activity, begin)
   122 	db.end(db_file(), project, activity, end, log)
   123 
   124 def add_break(args):
   125 	log = args.m
   126 	begin = datetime.strptime(args.begin, DATETIME_FORMAT)
   127 	end = datetime.strptime(args.end, DATETIME_FORMAT)
   128 	db.pause(db_file(), begin)
   129 	db.resume(db_file(), db.find_active_task(db_file(), begin), end, log)
   130 
   131 def set_customer(args):
   132 	db.update_where(db_file(), "projects", "name", args.project, "customer", 
   133 				args.customer)
   134 
   135 def map_name(map_base, name):
   136 	mapped = None
   137 	if name not in map_base.itervalues():
   138 		for v in map_base.iterkeys():
   139 			if name in v:
   140 				mapped = map_base[v]
   141 	else:
   142 		mapped = name
   143 	return mapped
   144 
   145 def set_rate(args):
   146 	project, activity = parse_label(args.label)
   147 	currency = map_name(CURRENCIES, args.currency)
   148 	type = map_name(RATE_TYPES, args.type)
   149 	print "setting rate for %s at %f %s %s" % (project, args.rate, currency, type)
   150 	db.set_rate(db_file(), project, activity, args.rate, currency, type)
   151 
   152 def status(args):
   153 	task = db.status(db_file())
   154 	if task:
   155 		print "Currently active task"
   156 		print "Project: %s Activity: %s" % task
   157 	else:
   158 		print "There is no active task."
   159 
   160 def main():
   161 	global config
   162 	config = read_config()
   163 	parser = argparse.ArgumentParser(description="Records time.")
   164 	subs = parser.add_subparsers()
   165 
   166 	sub_init = subs.add_parser("init")
   167 	sub_init.add_argument("working_path")
   168 	sub_init.set_defaults(func=init)
   169 
   170 	sub_begin = subs.add_parser("begin")
   171 	sub_begin.add_argument("label")
   172 	sub_begin.set_defaults(func=begin)
   173 
   174 	sub_end = subs.add_parser("end")
   175 	sub_end.add_argument("label", nargs="?", default="all:all")
   176 	sub_end.add_argument("-m")
   177 	sub_end.set_defaults(func=end)
   178 
   179 	sub_pause = subs.add_parser("pause")
   180 	sub_pause.set_defaults(func=pause)
   181 
   182 	sub_resume = subs.add_parser("resume")
   183 	sub_resume.add_argument("-m")
   184 	sub_resume.set_defaults(func=resume)
   185 
   186 	sub_add = subs.add_parser("add")
   187 	sub_add_subs = sub_add.add_subparsers()
   188 
   189 	sub_add_task = sub_add_subs.add_parser("task")
   190 	sub_add_task.add_argument("label")
   191 	sub_add_task.add_argument("begin")
   192 	sub_add_task.add_argument("end")
   193 	sub_add_task.add_argument("-m")
   194 	sub_add_task.set_defaults(func=add_task)
   195 	
   196 	sub_add_break = sub_add_subs.add_parser("break")
   197 	sub_add_break.add_argument("begin")
   198 	sub_add_break.add_argument("end")
   199 	sub_add_break.add_argument("-m")
   200 	sub_add_break.set_defaults(func=add_break)
   201 
   202 	sub_set = subs.add_parser("set")
   203 	sub_set_subs = sub_set.add_subparsers()
   204 
   205 	sub_set_customer = sub_set_subs.add_parser("customer")
   206 	sub_set_customer.add_argument("project")
   207 	sub_set_customer.add_argument("customer")
   208 	sub_set_customer.set_defaults(func=set_customer)
   209 
   210 	sub_set_rate = sub_set_subs.add_parser("rate")
   211 	sub_set_rate.add_argument("label")
   212 	sub_set_rate.add_argument("rate", type=float)
   213 	sub_set_rate.add_argument("currency")
   214 	sub_set_rate.add_argument("type")
   215 	sub_set_rate.set_defaults(func=set_rate)
   216 
   217 	sub_status = subs.add_parser("status")
   218 	sub_status.set_defaults(func=status)
   219 
   220 	args = parser.parse_args()
   221 	args.func(args)
   222     
   223 if __name__ == "__main__":
   224 	main()