trying on production (my real dir :-))
[pauldeden-misc.git] / googledocs_timesheet.py
blobf100320c47591d715d4afee1384b9a4f32cf8c6e
1 # python program to automate the process of
2 # checking in and checking out of my timesheet
3 # Future features may include reports
4 # or even replacing this script with a
5 # web interface.
7 try:
8 from xml.etree import ElementTree
9 except ImportError:
10 from elementtree import ElementTree
11 import atom
12 import atom.service
13 import gdata.service
14 import gdata.spreadsheet
15 import gdata.spreadsheet.service
16 import string
17 import time
18 import sys
19 import datetime
20 import googledocs_timesheet_conf as c
22 class GoogleDocsTimesheet():
24 def __init__(self):
25 self.gd_client = self._login();
26 self.wbid = self._get_workbook()
27 self.wsid = self._get_worksheet()
28 self.cur_date = self._get_current_date()
29 self.cur_time = self._get_current_time()
31 def _spreadsheet_query(self, sq):
32 """
33 not currently returning as I expect
34 so I'm currently not using it
35 """
36 q = gdata.spreadsheet.service.ListQuery()
37 q.reverse = 'true'
38 q.sq = sq
39 feed = self.gd_client.GetListFeed(self.wbid, self.wsid, query=q)
40 return feed
42 def _PrintFeed(self, feed):
43 for i, entry in enumerate(feed.entry):
44 if isinstance(feed, gdata.spreadsheet.SpreadsheetsCellsFeed):
45 print '%s %s\n' % (entry.title.text, entry.content.text)
46 elif isinstance(feed, gdata.spreadsheet.SpreadsheetsListFeed):
47 print '%s %s %s\n' % (i, entry.title.text, entry.content.text)
48 else:
49 print '%s %s\n' % (i, entry.title.text)
51 def _get_workbook(self):
52 """
53 This can be enhanced to query directly for the
54 spreadsheet we need by passing in the query parameter
55 to the GetSpreadsheetsFeed call, but it is
56 currently not necessary as the number of spreadsheets
57 is small.
58 """
59 feed = self.gd_client.GetSpreadsheetsFeed()
60 for wb in feed.entry:
61 if wb.title.text == c.spreadsheet_name:
62 timesheetid = wb.id.text.rsplit('/', 1)[1]
63 break
64 return timesheetid
66 def _get_worksheet(self):
67 feed = self.gd_client.GetWorksheetsFeed(self.wbid)
68 worksheetid = feed.entry[string.atoi('0')].id.text.rsplit('/', 1)[1]
69 return worksheetid
71 def _login(self):
72 gd_client = gdata.spreadsheet.service.SpreadsheetsService()
73 gd_client.email = c.login
74 gd_client.password = c.password
75 gd_client.source = c.source
76 try:
77 gd_client.ProgrammaticLogin()
78 except socket.sslerror:
79 pass # this is a known error, but not a problem
80 # see http://mail.python.org/pipermail/python-list/2005-August/338280.html
81 return gd_client
83 def _make_google_date(self, datestr):
84 """
85 mm/dd/yyyy to m/d/yyyy
86 """
87 month, day, year = datestr.split("/")
88 if month[0] == '0':
89 month = month[1]
90 if day[0] == '0':
91 day = day[1]
92 return "/".join([month, day, year])
94 def _get_current_date(self):
95 d = time.strftime("%m/%d/%Y")
96 gdate = self._make_google_date(d)
97 return gdate
99 def _get_current_time(self):
100 return time.strftime("%H:%M:%S")
102 def _timestr_to_timedelta(self, timestr):
103 hours, minutes, seconds = [int(item) for item in timestr.split(":")]
104 rdt = datetime.timedelta(hours=hours, minutes=minutes, seconds=seconds)
105 return rdt
107 def _calc_hours_worked_today(self):
108 hwt = datetime.timedelta()
109 for row in self.feed.entry:
110 clockin = row.custom['clockin'].text
111 clockout = row.custom['clockout'].text
112 if clockout is None:
113 clockout = self._get_current_time()
114 clockin = self._timestr_to_timedelta(clockin)
115 clockout = self._timestr_to_timedelta(clockout)
116 hwt += clockout - clockin
117 return hwt
119 def _print_hours_worked_today(self):
120 hwt = self._calc_hours_worked_today()
121 seconds = hwt.seconds
122 minutes = seconds/60
123 hours = minutes/60
124 minutes_left_over = minutes%60
125 print "%s hours and %s minutes worked today." % (hours, minutes_left_over)
127 def clock_in(self, punch_time):
129 clocks in
131 print "Clocking in..."
132 # add a row
133 row = {}
134 row['date'] = self.cur_date
135 row['clockin'] = punch_time
136 result = self.gd_client.InsertRow(row, self.wbid, self.wsid)
137 if isinstance(result, gdata.spreadsheet.SpreadsheetsList):
138 print "Clocked in at %s %s" % (self.cur_date, punch_time)
139 self._print_hours_worked_today()
140 else:
141 print "Problem clocking in"
143 def clock_out(self, punch_time):
145 clocks out
147 print "Clocking out..."
148 row = {}
149 row['date'] = self.feed.entry[0].custom['date'].text
150 row['clockin'] = self.feed.entry[0].custom['clockin'].text
151 row['clockout'] = punch_time
152 result = self.gd_client.UpdateRow(self.feed.entry[0], row)
153 if isinstance(result, gdata.spreadsheet.SpreadsheetsList):
154 print "Clocked out at %s %s" % (self.cur_date, punch_time)
155 self._print_hours_worked_today()
156 else:
157 print "Problem clocking out"
159 def _is_clocked_in(self):
160 "returns true if clocked in"
161 query = 'date=%s' % self.cur_date
162 self.feed = self._spreadsheet_query(query)
163 clocked_in = False
164 for row in self.feed.entry:
165 if row.custom['clockout'].text is None:
166 clocked_in = True
167 break
168 return clocked_in
170 def toggle_login(self, punch_time=False):
171 if not punch_time:
172 punch_time = self.cur_time
173 if (self._is_clocked_in()):
174 self.clock_out(punch_time)
175 else:
176 self.clock_in(punch_time)
178 def main(self, args):
179 if len(args) > 1 and args[1] == "hours":
180 if self._is_clocked_in():
181 print "Clocked in"
182 else:
183 print "Clocked out"
184 self._print_hours_worked_today()
185 elif len(args) > 1 and args[1].find(":") != -1: # a time
186 self.toggle_login(args[1])
187 else:
188 self.toggle_login()
189 # stop the windows command prompt from going away immediately
190 time.sleep(3)
192 if __name__ == "__main__":
193 a = GoogleDocsTimesheet()
194 a.main(sys.argv)