sawine@0
|
1 |
#!/usr/bin/python
|
sawine@0
|
2 |
|
sawine@0
|
3 |
"""
|
sawine@0
|
4 |
A time recording tool.
|
sawine@0
|
5 |
Author: Eugen Sawin (sawine@me73.com)
|
sawine@2
|
6 |
Dependencies: libsqlite3-dev
|
sawine@0
|
7 |
"""
|
sawine@0
|
8 |
|
sawine@1
|
9 |
import os
|
sawine@2
|
10 |
import sys
|
sawine@0
|
11 |
import argparse
|
sawine@2
|
12 |
from datetime import datetime
|
sawine@3
|
13 |
|
sawine@3
|
14 |
import db
|
sawine@0
|
15 |
|
sawine@1
|
16 |
WD = "working_path"
|
sawine@1
|
17 |
CONFIG = {WD: str}
|
sawine@1
|
18 |
CONFIG_SEP = "="
|
sawine@2
|
19 |
DB_FILE = "cronrec.db"
|
sawine@1
|
20 |
|
sawine@1
|
21 |
config = {}
|
sawine@1
|
22 |
|
sawine@2
|
23 |
# Trying to get the user's home directory path
|
sawine@1
|
24 |
try: # Windows
|
sawine@1
|
25 |
from win32com.shell import shellcon, shell
|
sawine@1
|
26 |
HOMEDIR = shell.SHGetFolderPath(0, shellcon.CSIDL_LOCAL_APPDATA, 0, 0)
|
sawine@2
|
27 |
except ImportError: # Linux (hopefully)
|
sawine@1
|
28 |
HOMEDIR = os.path.expanduser("~")
|
sawine@1
|
29 |
|
sawine@1
|
30 |
CONFIG_FILE = "%s/.cronrecrc" % HOMEDIR
|
sawine@1
|
31 |
|
sawine@1
|
32 |
def read_config():
|
sawine@1
|
33 |
config = {}
|
sawine@1
|
34 |
with open(CONFIG_FILE, "r") as config_stream:
|
sawine@1
|
35 |
config_lines = [l.split(CONFIG_SEP) for l in config_stream.readlines()
|
sawine@1
|
36 |
if CONFIG_SEP in l]
|
sawine@1
|
37 |
for key, value in config_lines:
|
sawine@1
|
38 |
key = key.strip().lower()
|
sawine@1
|
39 |
value = value.strip()
|
sawine@1
|
40 |
if key in CONFIG:
|
sawine@1
|
41 |
config[key] = CONFIG[key](value)
|
sawine@1
|
42 |
return config
|
sawine@1
|
43 |
|
sawine@1
|
44 |
def write_config(config):
|
sawine@1
|
45 |
with open(CONFIG_FILE, "w") as config_input:
|
sawine@1
|
46 |
config_input.write("\n".join([CONFIG_SEP.join((k, v))
|
sawine@1
|
47 |
for k, v in config.iteritems() if k in CONFIG]))
|
sawine@1
|
48 |
|
sawine@3
|
49 |
def db_file():
|
sawine@3
|
50 |
global config
|
sawine@3
|
51 |
if WD not in config:
|
sawine@3
|
52 |
print "Working directory path is not configured. \
|
sawine@3
|
53 |
Please use the init command."
|
sawine@3
|
54 |
return None
|
sawine@3
|
55 |
return config[WD] + "/" + DB_FILE
|
sawine@3
|
56 |
|
sawine@1
|
57 |
def init(args):
|
sawine@2
|
58 |
global config
|
sawine@1
|
59 |
last_wd = None
|
sawine@1
|
60 |
if WD in config:
|
sawine@1
|
61 |
last_wd = config[WD]
|
sawine@2
|
62 |
config[WD] = args.working_path
|
sawine@1
|
63 |
write_config(config)
|
sawine@2
|
64 |
path_exists = os.path.exists(config[WD]) and os.path.isdir(config[WD])
|
sawine@3
|
65 |
db_exists = path_exists and os.path.exists(db_file())\
|
sawine@3
|
66 |
and os.path.isfile(db_file())
|
sawine@2
|
67 |
if last_wd != config[WD]:
|
sawine@2
|
68 |
print "Changed working directory from %s to %s." % (last_wd, config[WD])
|
sawine@1
|
69 |
else:
|
sawine@2
|
70 |
print "Working directory remains at %s." % config[WD]
|
sawine@2
|
71 |
if not path_exists:
|
sawine@2
|
72 |
print "Warning: working directory %s does not exist." % config[WD]
|
sawine@2
|
73 |
os.makedirs(config[WD])
|
sawine@2
|
74 |
print "Working directory %s created." % config[WD]
|
sawine@2
|
75 |
elif db_exists:
|
sawine@3
|
76 |
print "Database file %s already exists, please delete it before \
|
sawine@3
|
77 |
initiating a new database at this location." % db_file()
|
sawine@2
|
78 |
if not db_exists:
|
sawine@3
|
79 |
db.init(db_file())
|
sawine@1
|
80 |
|
sawine@0
|
81 |
def begin(args):
|
sawine@2
|
82 |
project = None
|
sawine@2
|
83 |
activity = None
|
sawine@2
|
84 |
label = args.label.strip()
|
sawine@2
|
85 |
if ":" in label:
|
sawine@2
|
86 |
project, activity = label.split(":")
|
sawine@2
|
87 |
else:
|
sawine@2
|
88 |
project = label
|
sawine@3
|
89 |
db.begin(db_file(), project, activity, datetime.now())
|
sawine@2
|
90 |
print "begins %s:%s" % (project, activity)
|
sawine@0
|
91 |
|
sawine@0
|
92 |
def end(args):
|
sawine@5
|
93 |
project = None
|
sawine@5
|
94 |
activity = None
|
sawine@5
|
95 |
label = args.label.strip()
|
sawine@5
|
96 |
if ":" in label:
|
sawine@5
|
97 |
project, activity = label.split(":")
|
sawine@5
|
98 |
else:
|
sawine@5
|
99 |
project = label
|
sawine@5
|
100 |
db.end(db_file(), project, activity, datetime.now())
|
sawine@5
|
101 |
print "ends %s:%s" % (project, activity)
|
sawine@2
|
102 |
|
sawine@2
|
103 |
def main():
|
sawine@2
|
104 |
global config
|
sawine@1
|
105 |
config = read_config()
|
sawine@1
|
106 |
parser = argparse.ArgumentParser(description="Records time.")
|
sawine@1
|
107 |
subs = parser.add_subparsers()
|
sawine@1
|
108 |
sub_begin = subs.add_parser("init")
|
sawine@2
|
109 |
sub_begin.add_argument("working_path", type=str)
|
sawine@1
|
110 |
sub_begin.set_defaults(func=init)
|
sawine@0
|
111 |
|
sawine@1
|
112 |
sub_begin = subs.add_parser("begin")
|
sawine@2
|
113 |
sub_begin.add_argument("label", type=str)
|
sawine@1
|
114 |
sub_begin.set_defaults(func=begin)
|
sawine@0
|
115 |
|
sawine@1
|
116 |
sub_end = subs.add_parser("end")
|
sawine@2
|
117 |
sub_end.add_argument("label", type=str)
|
sawine@1
|
118 |
sub_end.set_defaults(func=end)
|
sawine@0
|
119 |
|
sawine@1
|
120 |
args = parser.parse_args()
|
sawine@1
|
121 |
args.func(args)
|
sawine@2
|
122 |
|
sawine@2
|
123 |
if __name__ == "__main__":
|
sawine@2
|
124 |
main()
|