cronrec.py
author Eugen Sawin <sawine@me73.com>
Tue, 05 Oct 2010 15:38:38 +0200
changeset 11 8a99ccb99361
parent 10 37ab6d0ddb30
child 12 28c80ae695dc
permissions -rwxr-xr-x
Added add break command.
sawine@6
     1
#!/usr/local/bin/python
sawine@0
     2
sawine@0
     3
"""
sawine@7
     4
tim - A time recording tool, because time is money.
sawine@0
     5
Author: Eugen Sawin (sawine@me73.com)
sawine@7
     6
Dependencies: Python 2.7 and 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@7
    23
# Try 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@10
    32
DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
sawine@10
    33
sawine@1
    34
def read_config():
sawine@1
    35
	config = {}
sawine@1
    36
	with open(CONFIG_FILE, "r") as config_stream:
sawine@1
    37
		config_lines = [l.split(CONFIG_SEP) for l in config_stream.readlines() 
sawine@1
    38
						if CONFIG_SEP in l]
sawine@1
    39
		for key, value in config_lines:
sawine@1
    40
			key = key.strip().lower()
sawine@1
    41
			value = value.strip()
sawine@1
    42
			if key in CONFIG:
sawine@1
    43
				config[key] = CONFIG[key](value)
sawine@1
    44
	return config
sawine@1
    45
sawine@1
    46
def write_config(config):
sawine@1
    47
	with open(CONFIG_FILE, "w") as config_input:
sawine@1
    48
		config_input.write("\n".join([CONFIG_SEP.join((k, v)) 
sawine@1
    49
							for k, v in config.iteritems() if k in CONFIG]))
sawine@1
    50
sawine@3
    51
def db_file():
sawine@3
    52
	global config
sawine@3
    53
	if WD not in config:
sawine@3
    54
		print "Working directory path is not configured. \
sawine@3
    55
Please use the init command."
sawine@3
    56
		return None
sawine@3
    57
	return config[WD] + "/" + DB_FILE
sawine@3
    58
	
sawine@1
    59
def init(args):
sawine@2
    60
	global config
sawine@1
    61
	last_wd = None
sawine@1
    62
	if WD in config:
sawine@1
    63
		last_wd = config[WD]
sawine@2
    64
	config[WD] = args.working_path
sawine@1
    65
	write_config(config)
sawine@2
    66
	path_exists = os.path.exists(config[WD]) and os.path.isdir(config[WD])
sawine@3
    67
	db_exists = path_exists and os.path.exists(db_file())\
sawine@3
    68
				and os.path.isfile(db_file())
sawine@2
    69
	if last_wd != config[WD]:		
sawine@2
    70
		print "Changed working directory from %s to %s." % (last_wd, config[WD])
sawine@1
    71
	else:
sawine@2
    72
		print "Working directory remains at %s." % config[WD]
sawine@2
    73
	if not path_exists:
sawine@2
    74
		print "Warning: working directory %s does not exist." % config[WD]
sawine@2
    75
		os.makedirs(config[WD])
sawine@2
    76
		print "Working directory %s created." % config[WD]
sawine@2
    77
	elif db_exists:
sawine@3
    78
		print "Database file %s already exists, please delete it before \
sawine@3
    79
initiating a new database at this location." % db_file()
sawine@2
    80
	if not db_exists:
sawine@3
    81
		db.init(db_file())	
sawine@1
    82
sawine@10
    83
def parse_label(label):
sawine@10
    84
	label = label.strip()
sawine@2
    85
	if ":" in label:
sawine@2
    86
		project, activity = label.split(":")
sawine@2
    87
	else:
sawine@10
    88
		project, activity = (label, None)
sawine@10
    89
	return project, activity
sawine@10
    90
sawine@10
    91
def begin(args):
sawine@10
    92
	project, activity = parse_label(args.label)
sawine@8
    93
	time = datetime.now()
sawine@8
    94
	db.resume(db_file(), None, None, time)
sawine@8
    95
	db.begin(db_file(), project, activity, time)	
sawine@0
    96
    
sawine@0
    97
def end(args):
sawine@10
    98
	project, activity = parse_label(args.label)
sawine@10
    99
	log = args.m	
sawine@8
   100
	time = datetime.now()
sawine@9
   101
	db.resume(db_file(), db.find_active_task(db_file()), time, log)
sawine@9
   102
	db.end(db_file(), project, activity, time, log)	
sawine@8
   103
sawine@8
   104
def pause(args):
sawine@11
   105
	db.pause(db_file(), datetime.now())	 
sawine@8
   106
sawine@8
   107
def resume(args):
sawine@11
   108
	db.resume(db_file(), None, datetime.now(), args.m)	
sawine@2
   109
sawine@10
   110
def add_task(args):
sawine@10
   111
	project, activity = parse_label(args.label)
sawine@10
   112
	log = args.m
sawine@10
   113
	begin = datetime.strptime(args.begin, DATETIME_FORMAT)
sawine@10
   114
	end = datetime.strptime(args.end, DATETIME_FORMAT)
sawine@10
   115
	db.begin(db_file(), project, activity, begin)
sawine@10
   116
	db.end(db_file(), project, activity, end, log)
sawine@10
   117
sawine@11
   118
def add_break(args):
sawine@11
   119
	log = args.m
sawine@11
   120
	begin = datetime.strptime(args.begin, DATETIME_FORMAT)
sawine@11
   121
	end = datetime.strptime(args.end, DATETIME_FORMAT)
sawine@11
   122
	db.pause(db_file(), begin)
sawine@11
   123
	db.resume(db_file(), db.find_active_task(db_file(), begin), end, log)
sawine@11
   124
sawine@7
   125
def status(args):
sawine@8
   126
	task = db.status(db_file())
sawine@8
   127
	if task:
sawine@8
   128
		print "Currently active task"
sawine@8
   129
		print "Project: %s Activity: %s" % task
sawine@7
   130
	else:
sawine@8
   131
		print "There is no active task."
sawine@7
   132
sawine@2
   133
def main():
sawine@2
   134
	global config
sawine@1
   135
	config = read_config()
sawine@1
   136
	parser = argparse.ArgumentParser(description="Records time.")
sawine@1
   137
	subs = parser.add_subparsers()
sawine@10
   138
sawine@10
   139
	sub_init = subs.add_parser("init")
sawine@10
   140
	sub_init.add_argument("working_path", type=str)
sawine@10
   141
	sub_init.set_defaults(func=init)
sawine@0
   142
sawine@1
   143
	sub_begin = subs.add_parser("begin")
sawine@2
   144
	sub_begin.add_argument("label", type=str)
sawine@1
   145
	sub_begin.set_defaults(func=begin)
sawine@0
   146
sawine@1
   147
	sub_end = subs.add_parser("end")
sawine@7
   148
	sub_end.add_argument("label", type=str, nargs="?", default="all:all")
sawine@9
   149
	sub_end.add_argument("-m", type=str)
sawine@1
   150
	sub_end.set_defaults(func=end)
sawine@0
   151
sawine@10
   152
	sub_pause = subs.add_parser("pause")
sawine@10
   153
	sub_pause.set_defaults(func=pause)
sawine@8
   154
sawine@10
   155
	sub_resume = subs.add_parser("resume")
sawine@10
   156
	sub_resume.add_argument("-m", type=str)
sawine@10
   157
	sub_resume.set_defaults(func=resume)
sawine@8
   158
sawine@10
   159
	sub_add = subs.add_parser("add")
sawine@10
   160
	sub_add_subs = sub_add.add_subparsers()
sawine@11
   161
sawine@10
   162
	sub_add_task = sub_add_subs.add_parser("task")
sawine@10
   163
	sub_add_task.add_argument("label", type=str)
sawine@10
   164
	sub_add_task.add_argument("begin", type=str)
sawine@10
   165
	sub_add_task.add_argument("end", type=str)
sawine@10
   166
	sub_add_task.add_argument("-m", type=str)
sawine@10
   167
	sub_add_task.set_defaults(func=add_task)
sawine@11
   168
	
sawine@11
   169
	sub_add_break = sub_add_subs.add_parser("break")
sawine@11
   170
	sub_add_break.add_argument("begin", type=str)
sawine@11
   171
	sub_add_break.add_argument("end", type=str)
sawine@11
   172
	sub_add_break.add_argument("-m", type=str)
sawine@11
   173
	sub_add_break.set_defaults(func=add_break)
sawine@10
   174
sawine@10
   175
	sub_status = subs.add_parser("status")
sawine@10
   176
	sub_status.set_defaults(func=status)
sawine@7
   177
sawine@1
   178
	args = parser.parse_args()
sawine@1
   179
	args.func(args)
sawine@2
   180
    
sawine@2
   181
if __name__ == "__main__":
sawine@2
   182
	main()