Integrating python and Google calendar?

Please support our Python advertiser: Programming Forums - DaniWeb Sister Site
Reply

Join Date: Apr 2009
Posts: 29
Reputation: mbirame is an unknown quantity at this point 
Solved Threads: 0
mbirame mbirame is offline Offline
Light Poster

Integrating python and Google calendar?

 
0
  #1
Apr 2nd, 2009
Hi friends,
This is my first post here. Please forgive me as I am a complete novice with Python. I have experience with HTML and CSS, but my main gig is electronics...So, please excuse me if I am out of line asking this question here!

A friend was helping me build a script using Python to integrate with my Google Calendar. I have a band, and I was wanting an app that could input one date (gig) and then several other events would auto-populate into the calendar (IE: 14 days before send out fliers, 2 days after send out thank you emails, etc).

I got Python installed and the code does the basic job. He has the Python code link to a CSV file and I open up a DOS command prompt and enter the fields and everything populates fine.

Here is the basic CSV code:
  1. "-14","Update calendar","12:00"
  2. "-2","Send out email","12:00"
  3. "2","Send out thank you email to attendees","12:00"
  4. "4","Upload drunken pictures to MySpace","1:00"

Here is the Python code that I am pretty sure relats to the above CSV (again my apologies if I am missing important bits-I'd be happy to post more if needed):

  1. # Two helper classes to parse CSV files.
  2. class CalendarEvent:
  3. def __init__(self):
  4. self.interval_from_start = 0
  5. self.description = ""
  6. self.hour = 0
  7. self.minute = 0
  8.  
  9. def __str__(self):
  10. s = ""
  11. for k,v in self.__dict__.iteritems():
  12. s = s + "%s:\t%s\n" % (k,v)
  13. return s + "\n"
  14.  
  15.  
  16. class CalendarEventFactory:
  17. def __init__(self, csv_file):
  18. self.csv_file = csv_file
  19.  
  20. def loadEvents(self):
  21. # List to hold events.
  22. event_list = []
  23.  
  24. # Open the file
  25. try:
  26. f = open(self.csv_file, 'r')
  27. except:
  28. raise Exception, "Unable to open file %s" % self.csv_file
  29.  
  30. # Stuff it into the csv reader class
  31. input_csv = csv.reader(f)
  32.  
  33. # For each item, create a CalendarEvent object
  34. for item in input_csv:
  35. hour, minute = item[2].split(':')
  36.  
  37. event = CalendarEvent()
  38.  
  39. event.interval_from_start = int(item[0])
  40. event.description = item[1]
  41. event.hour = int(hour)
  42. event.minute = int(minute)
  43.  
  44. event_list.append(event)
  45.  
  46. # Close the file
  47. f.close()
  48.  
  49. # Return the list
  50. return event_list
  51.  
  52.  
  53. # Helper function to list CSV files in a directory, without full path information
  54. def list_csv_files(dirname):
  55. files = []
  56. csv_files = []
  57.  
  58. try:
  59. files = os.listdir(dirname)
  60. except:
  61. raise Exception, "Unable to open directoy %s" % dirname
  62.  
  63. r = re.compile(".+\.csv")
  64.  
  65. for file in files:
  66. if r.match(file):
  67. csv_files.append(file)
  68.  
  69. return csv_files

Now the above code works fine, but it only allows me to input the description, date, and time of the event. I know that Google calendar is able to read more CSV information on an import:
From http://www.google.com/support/calend...n&answer=45656

To add more information to your events, simply add more headers. Possible headers include: Subject, Start Date, Start Time, End Date, End Time, All Day Event, Description, Location, and Private.
So this was my long winded way of asking my question:
How can I add all these other headers into the above python code? I have read a lot on the google pages, but I just don't know enough about this stuff to understand most of what is being talked about. I'm sure the answer is somewhere HERE, but I don't know where!

Thank you for your time and your patience!

Sincerely,
Joel
Reply With Quote Quick reply to this message  
Join Date: Jul 2007
Posts: 489
Reputation: shadwickman will become famous soon enough shadwickman will become famous soon enough 
Solved Threads: 76
shadwickman's Avatar
shadwickman shadwickman is offline Offline
Posting Pro in Training

Re: Integrating python and Google calendar?

 
0
  #2
Apr 2nd, 2009
I haven't fully confirmed this, but it would involve a change to this section:
  1. # For each item, create a CalendarEvent object
  2. for item in input_csv:
  3. hour, minute = item[2].split(':')
  4.  
  5. event = CalendarEvent()
  6.  
  7. event.interval_from_start = int(item[0])
  8. event.description = item[1]
  9. event.hour = int(hour)
  10. event.minute = int(minute)
  11.  
  12. event_list.append(event)
You could add other headers by writing something like the following into that block of code, after event.minute = int(minute) . Like this:
  1. event.location = item[3]
and change the CSV file to have an extra value at the end of the line, so it looks like this:
  1. "-2","Send out email","12:00","home"
In the above case, I used index 3 (indices start on zero) as the location header of the event. This is why I used item[3] in the above Python. So now this event has the location set to 'home'. I'm not sure about all the Python variables used for the various headers, but I'm guessing they follow the format of the header with spaces turned to underscores, and in all lower-case letters. I'm guessing here, but the header 'All Day Event' probably is 'all_day_event' in python.
The CSV file seems to be organized at your own whim (as far as I could find), so keep track of the order of the headers on the line, so in Python, you can call event.HEADER = item[INDEX] for in this same code block as above, where HEADER is the Python variable for a header, and INDEX is the location of it on the CSV file's line.

I've never used Google Calender, but I just glanced through those links you provided and the sample with the location header I provided seems to be logical. Tell me if it works, or if you need any other help!
Last edited by shadwickman; Apr 2nd, 2009 at 2:27 am.
"Two good old boys in a fire-apple red convertible. Stoned. Ripped. Twisted. Good people."
- Hunter S. Thompson

my photography
Reply With Quote Quick reply to this message  
Join Date: Apr 2009
Posts: 29
Reputation: mbirame is an unknown quantity at this point 
Solved Threads: 0
mbirame mbirame is offline Offline
Light Poster

Re: Integrating python and Google calendar?

 
0
  #3
Apr 2nd, 2009
Thanks for the reply shadwickman. Those changes didn't break the code, but it didn't give any results. The location did not import into the "Where" field on google calendar. I did find this-again sadly I don't really know if this info helps...Elements: "Kinds".

One thing I'm confused about though from your post is that I need to be able to edit the variables like location. If I just put "home" in the CSV, then the location would always be "home"...

So to be clear, what I need to be able to do is edit more of the fields of the "primary date", but all the secondary 'auto-populated' dates will have built in values that would be predetermined (I guess with the CSV)

Forgive me if it's too much, but I'll include all the python code to give a better description of what is happening with the DOS input. (forgive the humor that my friend included in the coding!)

  1. #!/usr/bin/python
  2.  
  3. try:
  4. from xml.etree import ElementTree
  5. except ImportError:
  6. from elementtree import ElementTree
  7. import gdata.calendar.service
  8. import gdata.service
  9. import atom.service
  10. import gdata.calendar
  11. import atom
  12. import getopt
  13. import os
  14. import csv
  15. import re
  16. import sys
  17. import time
  18. import datetime
  19. from datetime import timedelta
  20.  
  21. from exceptions import Exception
  22.  
  23.  
  24. # This is where the zipfile gets unpacked to. Put your CSV files in here.
  25. global install_root
  26. install_root = "C:/"
  27.  
  28. # This is the name of your Google Calendar. Please note that case must match, and you need to have created the calendar
  29. # in Google Calendar already.
  30. global calendar_name
  31. calendar_name = "Test"
  32.  
  33. # Set this to your gmail account
  34. global gmail_account
  35. gmail_account = 'xxxxxxxxxxxxxxxxx'
  36.  
  37. # Set this to your gmail password
  38. global gmail_password
  39. gmail_password = 'xxxxxxxxxxxxxxxxx'
  40.  
  41. # Two helper classes to parse CSV files.
  42. class CalendarEvent:
  43. def __init__(self):
  44. self.interval_from_start = 0
  45. self.description = ""
  46. self.hour = 0
  47. self.minute = 0
  48.  
  49. def __str__(self):
  50. s = ""
  51. for k,v in self.__dict__.iteritems():
  52. s = s + "%s:\t%s\n" % (k,v)
  53. return s + "\n"
  54.  
  55.  
  56. class CalendarEventFactory:
  57. def __init__(self, csv_file):
  58. self.csv_file = csv_file
  59.  
  60. def loadEvents(self):
  61. # List to hold events.
  62. event_list = []
  63.  
  64. # Open the file
  65. try:
  66. f = open(self.csv_file, 'r')
  67. except:
  68. raise Exception, "Unable to open file %s" % self.csv_file
  69.  
  70. # Stuff it into the csv reader class
  71. input_csv = csv.reader(f)
  72.  
  73. # For each item, create a CalendarEvent object
  74. for item in input_csv:
  75. hour, minute = item[2].split(':')
  76.  
  77. event = CalendarEvent()
  78.  
  79. event.interval_from_start = int(item[0])
  80. event.description = item[1]
  81. event.hour = int(hour)
  82. event.minute = int(minute)
  83.  
  84. event_list.append(event)
  85.  
  86. # Close the file
  87. f.close()
  88.  
  89. # Return the list
  90. return event_list
  91.  
  92.  
  93. # Helper function to list CSV files in a directory, without full path information
  94. def list_csv_files(dirname):
  95. files = []
  96. csv_files = []
  97.  
  98. try:
  99. files = os.listdir(dirname)
  100. except:
  101. raise Exception, "Unable to open directoy %s" % dirname
  102.  
  103. r = re.compile(".+\.csv")
  104.  
  105. for file in files:
  106. if r.match(file):
  107. csv_files.append(file)
  108.  
  109. return csv_files
  110.  
  111. # Helper function to show a quick and dirty menu of list items. Returns the index of the list item picked, or exits if the user so desires.
  112. def display_menu(menu_items):
  113. def print_menu():
  114. os.system('cls')
  115. print "Magical Mbira Event Calculator Version 1.0"
  116. print ""
  117. print " Please select your desired event template"
  118.  
  119. # Menu index
  120. i = 1
  121.  
  122. for item in menu_items:
  123. print "\t%d - %s" % (i, item)
  124. i += 1
  125.  
  126. print "\tQ - Exit program"
  127. print ""
  128.  
  129. # Loop until they pick something comprehensible.
  130. picked = False
  131.  
  132. while not picked:
  133. print_menu()
  134. resp = raw_input("\tPlease selecct an event template, or press Q to quit: ")
  135. resp = resp.strip()
  136.  
  137. try:
  138. index = int(resp)
  139. except:
  140. if resp in ('Q', 'q'):
  141. sys.exit()
  142. else:
  143. print "\n\tInvalid choice!!"
  144. time.sleep(1)
  145. continue
  146.  
  147. if index>len(menu_items):
  148. print "\n\tInvalid choice!!"
  149. time.sleep(1)
  150. else:
  151. picked = True
  152.  
  153. return index-1
  154.  
  155. # And really, isn't being a musician really just about getting dates anyway?
  156. def get_gig_date():
  157. # Loop until they enter something comprehensible. Comprehensible means a date of the format MM/DD/YYYY
  158. picked = False
  159.  
  160. r = re.compile('(?P<month>\d{1,2})(/)(?P<day>\d{1,2})(/)(?P<year>\d{4,4}) (?P<hour>\d{1,2})(:)(?P<minute>\d{2,2})')
  161.  
  162. while not picked:
  163. os.system('cls')
  164. resp = raw_input("Date/time of the gig in the format MM/DD/YYYY HH:MM (military time): ")
  165. resp = resp.strip()
  166.  
  167. mo = r.match(resp)
  168.  
  169. if mo is None:
  170. print "Incorrect date format!"
  171. time.sleep(1)
  172. continue
  173. else:
  174. picked = True
  175.  
  176. return datetime.datetime(int(mo.group('year')), int(mo.group('month')), int(mo.group('day')), int(mo.group('hour')), int(mo.group('minute')))
  177.  
  178. # Helper function to get a reference to a calendar object by name. Really, this should be in the library...
  179. def find_calendar_by_name(calendar_service, name):
  180. # Get a reference to the specified calendar
  181. feed = calendar_service.GetOwnCalendarsFeed()
  182. for i, a_calendar in enumerate(feed.entry):
  183. if a_calendar.title.text==calendar_name:
  184. return a_calendar
  185.  
  186. return None
  187.  
  188.  
  189.  
  190. # First, get a list of all the CSV files in the install root directory sorted alphabetically. Make an event factory for each.
  191. csv_files = list_csv_files(install_root)
  192.  
  193. # Next, print a menu and get the index of the option they want.
  194. index = display_menu(csv_files)
  195.  
  196. # Prompt for the gig date
  197. gig_date = get_gig_date()
  198.  
  199. # Get a description of the gig
  200. gig_description = raw_input("Short description of the gig: ")
  201.  
  202.  
  203.  
  204. # Load it up via the event factory
  205. evf = CalendarEventFactory(os.path.join(install_root, csv_files[index]))
  206.  
  207. # Authenticate to Google Calendar
  208. try:
  209. calendar_service = gdata.calendar.service.CalendarService()
  210. calendar_service.email = gmail_account
  211. calendar_service.password = gmail_password
  212. calendar_service.source = 'Google-Calendar_Python_Sample-1.0'
  213. calendar_service.ProgrammaticLogin()
  214. except:
  215. print "Error logging into Google Calendar service. Please check your account settings at the top of the script."
  216. sys.exit(1)
  217.  
  218. # Find the named calendar
  219. cal = find_calendar_by_name(calendar_service, calendar_name)
  220.  
  221. # ****, Google, could you have made getting the feed ID any more obscure? You know, like putting it in the field marked ID???!?!?
  222. # Smart people my ass. If Google employees are so damn smart, why do so many of them live in IRVINE???
  223. cal_id = cal.content.src.replace('http://www.google.com', '')
  224.  
  225. # Loop through the events, and insert them relative to the specified day
  226. for ev in evf.loadEvents():
  227. event_dt = datetime.datetime(gig_date.year,
  228. gig_date.month,
  229. gig_date.day,
  230. ev.hour,
  231. ev.minute,
  232. 0) + timedelta(days=ev.interval_from_start)
  233.  
  234. end_event_dt = event_dt + timedelta(hours=1)
  235.  
  236. start_time = event_dt.strftime('%Y-%m-%dT%H:%M:%S.000Z')
  237. end_time = end_event_dt.strftime('%Y-%m-%dT%H:%M:%S.000Z')
  238.  
  239. print "Start: %s" % str(event_dt)
  240. print "End: %s" % str(end_event_dt)
  241. print start_time
  242. print end_time
  243.  
  244. event = gdata.calendar.CalendarEventEntry()
  245. event.title = atom.Title(text=ev.description)
  246. event.when.append(gdata.calendar.When(start_time=start_time, end_time=end_time))
  247.  
  248. new_event = calendar_service.InsertEvent(event, cal_id)
  249.  
  250.  
  251.  
  252.  
  253. # Finally, add the gig itself
  254. event = gdata.calendar.CalendarEventEntry()
  255. event.title = atom.Title(text=gig_description)
  256.  
  257. end_gig_date = gig_date + timedelta(hours=1)
  258. start_time = gig_date.strftime('%Y-%m-%dT%H:%M:%S.000Z')
  259. end_time = end_gig_date.strftime('%Y-%m-%dT%H:%M:%S.000Z')
  260. event.when.append(gdata.calendar.When(start_time=start_time, end_time=end_time))
  261.  
  262. new_event = calendar_service.InsertEvent(event, cal_id)

Thank you for all your help!
Reply With Quote Quick reply to this message  
Join Date: Jul 2007
Posts: 489
Reputation: shadwickman will become famous soon enough shadwickman will become famous soon enough 
Solved Threads: 76
shadwickman's Avatar
shadwickman shadwickman is offline Offline
Posting Pro in Training

Re: Integrating python and Google calendar?

 
0
  #4
Apr 2nd, 2009
I don't have the time to look at that massive section of code you posted, but in my above example, try changing that
  1. event.location = item[3]
to
  1. if len(item) >= 3:
  2. event.where = item[3]
  3. else:
  4. event.where = "undefined location"
and tell me if that makes a difference in Google Calender!
"Two good old boys in a fire-apple red convertible. Stoned. Ripped. Twisted. Good people."
- Hunter S. Thompson

my photography
Reply With Quote Quick reply to this message  
Join Date: Mar 2009
Posts: 181
Reputation: adam1122 is an unknown quantity at this point 
Solved Threads: 28
adam1122 adam1122 is offline Offline
Junior Poster

Re: Integrating python and Google calendar?

 
0
  #5
Apr 2nd, 2009
Try this:
  1. event.where.append(gdata.calendar.Where(value_string=item[3]))

You could try this for testing purposes so you don't have to edit your CVS structure:
  1. event.where.append(gdata.calendar.Where(value_string="Home"))
Last edited by adam1122; Apr 2nd, 2009 at 3:18 am.
Reply With Quote Quick reply to this message  
Join Date: Mar 2009
Posts: 181
Reputation: adam1122 is an unknown quantity at this point 
Solved Threads: 28
adam1122 adam1122 is offline Offline
Junior Poster

Re: Integrating python and Google calendar?

 
0
  #6
Apr 2nd, 2009
The description part should be handled by:
  1. event.content = atom.Content(text=description)

Other than that, the only other settings that you listed that your program doesn't do is "All Day Event", which I believe will be set if you leave off a time and date, and the visibility of the event.
Reply With Quote Quick reply to this message  
Join Date: Apr 2009
Posts: 29
Reputation: mbirame is an unknown quantity at this point 
Solved Threads: 0
mbirame mbirame is offline Offline
Light Poster

Re: Integrating python and Google calendar?

 
0
  #7
Apr 2nd, 2009
Thank you Adam1122 and shadwickman for your time. I will work on these ideas this evening and report back.

Best regards,
Joel
Reply With Quote Quick reply to this message  
Join Date: Apr 2009
Posts: 29
Reputation: mbirame is an unknown quantity at this point 
Solved Threads: 0
mbirame mbirame is offline Offline
Light Poster

Re: Integrating python and Google calendar?

 
0
  #8
Apr 2nd, 2009
Hi again. No luck so far:

shadwickman, when I tried that new code, the DOS stopped at that point of the code and didn't seem to like the way it was written...didn't let me get past that.

adam1122, when I put in your code, I got:

  1. Traceback (most recent call last):
  2. File "calendarUpdate.py", line 226, in <module>
  3. for ev in evf.loadEvents():
  4. File "calendarUpdate.py", line 83, in loadEvents
  5. event.where.append(gdata.calendar.Where(value_string=item[3]))
  6. AttributeError: CalendarEvent instance has no attribute 'where'

After sleeping on this I'm realizing that there are two different things that are needing to happen, and I don't think I was clear about the differences:

1) I enter a gig by going to the DOS run prompt and run the cualendarUpdate.py file.

The DOS asks me which CSV file I am wanting to read.

The DOS then asks me for the date of the gig and the time of the gig. If I don't answer these values, it doesn't let me go further.

Then the DOS asks me for a short description of the gig.

2) THen Python adds the gig whose Info I put in onto Google calendar and then populates the other dates based on the CSV file.

So the added functionality I am needing is twofold:

1) I need to have other fields (like location, etc, etc) that can be read from the CSV,

and 2) I need other prompts requested of me from the DOS (also things like location, start and end time, etc, etc).

Thoug these two tasks seem similar, I believe they are two different areas of the above code that need to be addresse (one for the DOS and one for the CSV)

I hope this makes sense?

To be more clear: When I put a gig into the calendar, I am wanting to choose a predetermined CSV file that will have a "promotion timeline" that will be based on what type of gig it is (IE I will have a "local" and a "regional" CSV list because my promotion timeline will be different for both) These CSV lists won't need to change from gig to gig-I can edit them over time as my needs change.

But the fields that the DOS is asking me for for each specific gig need to give me more options than just the date, time, and short description...


Best regards,
Joel
Last edited by mbirame; Apr 2nd, 2009 at 8:26 pm.
Reply With Quote Quick reply to this message  
Join Date: Mar 2009
Posts: 181
Reputation: adam1122 is an unknown quantity at this point 
Solved Threads: 28
adam1122 adam1122 is offline Offline
Junior Poster

Re: Integrating python and Google calendar?

 
0
  #9
Apr 2nd, 2009
You get those errors because that's your custom class and it doesn't have those fields. The code I gave you has to be done on the event object created like this:
  1. event = gdata.calendar.CalendarEventEntry()
Reply With Quote Quick reply to this message  
Join Date: Apr 2009
Posts: 29
Reputation: mbirame is an unknown quantity at this point 
Solved Threads: 0
mbirame mbirame is offline Offline
Light Poster

Re: Integrating python and Google calendar?

 
0
  #10
Apr 2nd, 2009
Hi Adam1122,

I'm very new to this but trying hard to keep up. Here is where I put it:

old code:
  1. # For each item, create a CalendarEvent object
  2. for item in input_csv:
  3. hour, minute = item[2].split(':')
  4.  
  5. event = CalendarEvent()
  6.  
  7. event.interval_from_start = int(item[0])
  8. event.description = item[1]
  9. event.hour = int(hour)
  10. event.minute = int(minute)
  11.  
  12. event_list.append(event)
  13.  
  14. # Close the file
  15. f.close()
  16.  
  17. # Return the list
  18. return event_list

New code:

 # For each item, create a CalendarEvent object
        for item in input_csv:
            hour, minute = item[2].split(':')

            event = CalendarEvent()

            event.interval_from_start = int(item[0])
            event.description = item[1]
            event.hour = int(hour)
            event.minute = int(minute)
            event.where.append(gdata.calendar.Where(value_string=item[3]))
            event_list.append(event)

        # Close the file
        f.close()

        # Return the list
        return event_list

I still had put the extra "home" attribute on the CSV files thinking that the above new code would relate to it...

If there is somewhere else or something different I should put the code, I'm not understanding where-sorry!!
Reply With Quote Quick reply to this message  
Reply

This thread is more than three months old.
Perhaps start a new thread instead?
Message:


Thread Tools Search this Thread



Tag cloud for Python
About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC