Renamed and added default config file.
1 #!/usr/local/bin/python
2 # -*- coding: utf-8 -*-
5 Name: 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
19 config = read_config()
20 parser = argparse.ArgumentParser(description="Records time.")
21 subs = parser.add_subparsers()
23 sub_init = subs.add_parser("init")
24 sub_init.add_argument("working_path")
25 sub_init.set_defaults(func=init)
27 sub_begin = subs.add_parser("begin")
28 sub_begin.add_argument("label")
29 sub_begin.set_defaults(func=begin)
31 sub_end = subs.add_parser("end")
32 sub_end.add_argument("label", nargs="?", default="all:all")
33 sub_end.add_argument("-m")
34 sub_end.set_defaults(func=end)
36 sub_pause = subs.add_parser("pause")
37 sub_pause.set_defaults(func=pause)
39 sub_resume = subs.add_parser("resume")
40 sub_resume.add_argument("-m")
41 sub_resume.set_defaults(func=resume)
43 sub_add = subs.add_parser("add")
44 sub_add_subs = sub_add.add_subparsers()
46 sub_add_task = sub_add_subs.add_parser("task")
47 sub_add_task.add_argument("label")
48 sub_add_task.add_argument("begin")
49 sub_add_task.add_argument("end")
50 sub_add_task.add_argument("-m")
51 sub_add_task.set_defaults(func=add_task)
53 sub_add_break = sub_add_subs.add_parser("break")
54 sub_add_break.add_argument("begin")
55 sub_add_break.add_argument("end")
56 sub_add_break.add_argument("-m")
57 sub_add_break.set_defaults(func=add_break)
59 sub_set = subs.add_parser("set")
60 sub_set_subs = sub_set.add_subparsers()
62 sub_set_customer = sub_set_subs.add_parser("customer")
63 sub_set_customer.add_argument("project")
64 sub_set_customer.add_argument("customer")
65 sub_set_customer.set_defaults(func=set_customer)
67 sub_set_rate = sub_set_subs.add_parser("rate")
68 sub_set_rate.add_argument("label")
69 sub_set_rate.add_argument("rate", type=float)
70 sub_set_rate.add_argument("currency")
71 sub_set_rate.add_argument("type")
72 sub_set_rate.set_defaults(func=set_rate)
74 sub_status = subs.add_parser("status")
75 sub_status.set_defaults(func=status)
77 args = parser.parse_args()
85 CURRENCIES = {("EUR", "EURO", "€"): "EUR",
86 ("US DOLLAR", "USD", "$"): "USD"}
88 RATE_TYPES = {("h", "hourly"): "hourly"}
92 # Try to get the user's home directory path
94 from win32com.shell import shellcon, shell
95 HOMEDIR = shell.SHGetFolderPath(0, shellcon.CSIDL_LOCAL_APPDATA, 0, 0)
96 except ImportError: # Linux (hopefully)
97 HOMEDIR = os.path.expanduser("~")
99 CONFIG_FILE = "%s/.timrc" % HOMEDIR
101 DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
105 if not os.path.isfile(CONFIG_FILE):
107 with open(CONFIG_FILE, "r") as config_stream:
108 config_lines = [l.split(CONFIG_SEP) for l in config_stream.readlines()
110 for key, value in config_lines:
111 key = key.strip().lower()
112 value = value.strip()
114 config[key] = CONFIG[key](value)
117 def write_config(config):
118 with open(CONFIG_FILE, "w") as config_input:
119 config_input.write("\n".join([CONFIG_SEP.join((k, v))
120 for k, v in config.iteritems() if k in CONFIG]))
125 print "Working directory path is not configured. \
126 Please use the init command."
128 return config[WD] + "/" + DB_FILE
135 config[WD] = args.working_path
137 path_exists = os.path.exists(config[WD]) and os.path.isdir(config[WD])
138 db_exists = path_exists and os.path.exists(db_file())\
139 and os.path.isfile(db_file())
140 if last_wd != config[WD]:
141 print "Changed working directory from %s to %s." % (last_wd, config[WD])
143 print "Working directory remains at %s." % config[WD]
145 print "Warning: working directory %s does not exist." % config[WD]
146 os.makedirs(config[WD])
147 print "Working directory %s created." % config[WD]
149 print "Database file %s already exists, please delete it before \
150 initiating a new database at this location." % db_file()
154 def parse_label(label):
155 label = label.strip()
157 project, activity = label.split(":")
159 project, activity = (label, None)
160 return project, activity
163 project, activity = parse_label(args.label)
164 time = datetime.now()
165 db.resume(db_file(), None, None, time)
166 db.begin(db_file(), project, activity, time)
169 project, activity = parse_label(args.label)
171 time = datetime.now()
172 db.resume(db_file(), db.find_active_task(db_file()), time, log)
173 db.end(db_file(), project, activity, time, log)
176 db.pause(db_file(), datetime.now())
179 db.resume(db_file(), None, datetime.now(), args.m)
182 project, activity = parse_label(args.label)
184 begin = datetime.strptime(args.begin, DATETIME_FORMAT)
185 end = datetime.strptime(args.end, DATETIME_FORMAT)
186 db.begin(db_file(), project, activity, begin)
187 db.end(db_file(), project, activity, end, log)
191 begin = datetime.strptime(args.begin, DATETIME_FORMAT)
192 end = datetime.strptime(args.end, DATETIME_FORMAT)
193 db.pause(db_file(), begin)
194 db.resume(db_file(), db.find_active_task(db_file(), begin), end, log)
196 def set_customer(args):
197 db.update_where(db_file(), "projects", "name", args.project, "customer",
200 def map_name(map_base, name):
202 if name not in map_base.itervalues():
203 for v in map_base.iterkeys():
211 project, activity = parse_label(args.label)
212 currency = map_name(CURRENCIES, args.currency)
213 type = map_name(RATE_TYPES, args.type)
214 print "setting rate for %s at %f %s %s" % (project, args.rate, currency, type)
215 db.set_rate(db_file(), project, activity, args.rate, currency, type)
218 task = db.status(db_file())
220 print "Currently active task"
221 print "Project: %s Activity: %s" % task
223 print "There is no active task."
225 if __name__ == "__main__":