Renamed and added default config file.
1 #!/usr/local/bin/python
2 # -*- coding: utf-8 -*-
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
13 from datetime import datetime
22 CURRENCIES = {("EUR", "EURO", "€"): "EUR",
23 ("US DOLLAR", "USD", "$"): "USD"}
25 RATE_TYPES = {("h", "hourly"): "hourly"}
29 # Try to get the user's home directory path
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("~")
36 CONFIG_FILE = "%s/.timrc" % HOMEDIR
38 DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
42 with open(CONFIG_FILE, "r") as config_stream:
43 config_lines = [l.split(CONFIG_SEP) for l in config_stream.readlines()
45 for key, value in config_lines:
46 key = key.strip().lower()
49 config[key] = CONFIG[key](value)
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]))
60 print "Working directory path is not configured. \
61 Please use the init command."
63 return config[WD] + "/" + DB_FILE
70 config[WD] = args.working_path
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])
78 print "Working directory remains at %s." % config[WD]
80 print "Warning: working directory %s does not exist." % config[WD]
81 os.makedirs(config[WD])
82 print "Working directory %s created." % config[WD]
84 print "Database file %s already exists, please delete it before \
85 initiating a new database at this location." % db_file()
89 def parse_label(label):
92 project, activity = label.split(":")
94 project, activity = (label, None)
95 return project, activity
98 project, activity = parse_label(args.label)
100 db.resume(db_file(), None, None, time)
101 db.begin(db_file(), project, activity, time)
104 project, activity = parse_label(args.label)
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)
111 db.pause(db_file(), datetime.now())
114 db.resume(db_file(), None, datetime.now(), args.m)
117 project, activity = parse_label(args.label)
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)
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)
131 def set_customer(args):
132 db.update_where(db_file(), "projects", "name", args.project, "customer",
135 def map_name(map_base, name):
137 if name not in map_base.itervalues():
138 for v in map_base.iterkeys():
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)
153 task = db.status(db_file())
155 print "Currently active task"
156 print "Project: %s Activity: %s" % task
158 print "There is no active task."
162 config = read_config()
163 parser = argparse.ArgumentParser(description="Records time.")
164 subs = parser.add_subparsers()
166 sub_init = subs.add_parser("init")
167 sub_init.add_argument("working_path")
168 sub_init.set_defaults(func=init)
170 sub_begin = subs.add_parser("begin")
171 sub_begin.add_argument("label")
172 sub_begin.set_defaults(func=begin)
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)
179 sub_pause = subs.add_parser("pause")
180 sub_pause.set_defaults(func=pause)
182 sub_resume = subs.add_parser("resume")
183 sub_resume.add_argument("-m")
184 sub_resume.set_defaults(func=resume)
186 sub_add = subs.add_parser("add")
187 sub_add_subs = sub_add.add_subparsers()
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)
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)
202 sub_set = subs.add_parser("set")
203 sub_set_subs = sub_set.add_subparsers()
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)
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)
217 sub_status = subs.add_parser("status")
218 sub_status.set_defaults(func=status)
220 args = parser.parse_args()
223 if __name__ == "__main__":