| | |
Integrating python and Google calendar?
Please support our Python advertiser: Programming Forums - DaniWeb Sister Site
![]() |
•
•
Join Date: Apr 2009
Posts: 29
Reputation:
Solved Threads: 0
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:
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):
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
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
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:
Python Syntax (Toggle Plain Text)
"-14","Update calendar","12:00" "-2","Send out email","12:00" "2","Send out thank you email to attendees","12:00" "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):
Python Syntax (Toggle Plain Text)
# Two helper classes to parse CSV files. class CalendarEvent: def __init__(self): self.interval_from_start = 0 self.description = "" self.hour = 0 self.minute = 0 def __str__(self): s = "" for k,v in self.__dict__.iteritems(): s = s + "%s:\t%s\n" % (k,v) return s + "\n" class CalendarEventFactory: def __init__(self, csv_file): self.csv_file = csv_file def loadEvents(self): # List to hold events. event_list = [] # Open the file try: f = open(self.csv_file, 'r') except: raise Exception, "Unable to open file %s" % self.csv_file # Stuff it into the csv reader class input_csv = csv.reader(f) # 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_list.append(event) # Close the file f.close() # Return the list return event_list # Helper function to list CSV files in a directory, without full path information def list_csv_files(dirname): files = [] csv_files = [] try: files = os.listdir(dirname) except: raise Exception, "Unable to open directoy %s" % dirname r = re.compile(".+\.csv") for file in files: if r.match(file): csv_files.append(file) 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.
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
I haven't fully confirmed this, but it would involve a change to this section:
You could add other headers by writing something like the following into that block of code, after
and change the CSV file to have an extra value at the end of the line, so it looks like this:
In the above case, I used index 3 (indices start on zero) as the location header of the event. This is why I used
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
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!
python Syntax (Toggle Plain Text)
# 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_list.append(event)
event.minute = int(minute) . Like this: python Syntax (Toggle Plain Text)
event.location = item[3]
Python Syntax (Toggle Plain Text)
"-2","Send out email","12:00","home"
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
- Hunter S. Thompson
my photography
•
•
Join Date: Apr 2009
Posts: 29
Reputation:
Solved Threads: 0
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!)
Thank you for all your help!
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!)
Python Syntax (Toggle Plain Text)
#!/usr/bin/python try: from xml.etree import ElementTree except ImportError: from elementtree import ElementTree import gdata.calendar.service import gdata.service import atom.service import gdata.calendar import atom import getopt import os import csv import re import sys import time import datetime from datetime import timedelta from exceptions import Exception # This is where the zipfile gets unpacked to. Put your CSV files in here. global install_root install_root = "C:/" # This is the name of your Google Calendar. Please note that case must match, and you need to have created the calendar # in Google Calendar already. global calendar_name calendar_name = "Test" # Set this to your gmail account global gmail_account gmail_account = 'xxxxxxxxxxxxxxxxx' # Set this to your gmail password global gmail_password gmail_password = 'xxxxxxxxxxxxxxxxx' # Two helper classes to parse CSV files. class CalendarEvent: def __init__(self): self.interval_from_start = 0 self.description = "" self.hour = 0 self.minute = 0 def __str__(self): s = "" for k,v in self.__dict__.iteritems(): s = s + "%s:\t%s\n" % (k,v) return s + "\n" class CalendarEventFactory: def __init__(self, csv_file): self.csv_file = csv_file def loadEvents(self): # List to hold events. event_list = [] # Open the file try: f = open(self.csv_file, 'r') except: raise Exception, "Unable to open file %s" % self.csv_file # Stuff it into the csv reader class input_csv = csv.reader(f) # 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_list.append(event) # Close the file f.close() # Return the list return event_list # Helper function to list CSV files in a directory, without full path information def list_csv_files(dirname): files = [] csv_files = [] try: files = os.listdir(dirname) except: raise Exception, "Unable to open directoy %s" % dirname r = re.compile(".+\.csv") for file in files: if r.match(file): csv_files.append(file) return csv_files # 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. def display_menu(menu_items): def print_menu(): os.system('cls') print "Magical Mbira Event Calculator Version 1.0" print "" print " Please select your desired event template" # Menu index i = 1 for item in menu_items: print "\t%d - %s" % (i, item) i += 1 print "\tQ - Exit program" print "" # Loop until they pick something comprehensible. picked = False while not picked: print_menu() resp = raw_input("\tPlease selecct an event template, or press Q to quit: ") resp = resp.strip() try: index = int(resp) except: if resp in ('Q', 'q'): sys.exit() else: print "\n\tInvalid choice!!" time.sleep(1) continue if index>len(menu_items): print "\n\tInvalid choice!!" time.sleep(1) else: picked = True return index-1 # And really, isn't being a musician really just about getting dates anyway? def get_gig_date(): # Loop until they enter something comprehensible. Comprehensible means a date of the format MM/DD/YYYY picked = False 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})') while not picked: os.system('cls') resp = raw_input("Date/time of the gig in the format MM/DD/YYYY HH:MM (military time): ") resp = resp.strip() mo = r.match(resp) if mo is None: print "Incorrect date format!" time.sleep(1) continue else: picked = True return datetime.datetime(int(mo.group('year')), int(mo.group('month')), int(mo.group('day')), int(mo.group('hour')), int(mo.group('minute'))) # Helper function to get a reference to a calendar object by name. Really, this should be in the library... def find_calendar_by_name(calendar_service, name): # Get a reference to the specified calendar feed = calendar_service.GetOwnCalendarsFeed() for i, a_calendar in enumerate(feed.entry): if a_calendar.title.text==calendar_name: return a_calendar return None # First, get a list of all the CSV files in the install root directory sorted alphabetically. Make an event factory for each. csv_files = list_csv_files(install_root) # Next, print a menu and get the index of the option they want. index = display_menu(csv_files) # Prompt for the gig date gig_date = get_gig_date() # Get a description of the gig gig_description = raw_input("Short description of the gig: ") # Load it up via the event factory evf = CalendarEventFactory(os.path.join(install_root, csv_files[index])) # Authenticate to Google Calendar try: calendar_service = gdata.calendar.service.CalendarService() calendar_service.email = gmail_account calendar_service.password = gmail_password calendar_service.source = 'Google-Calendar_Python_Sample-1.0' calendar_service.ProgrammaticLogin() except: print "Error logging into Google Calendar service. Please check your account settings at the top of the script." sys.exit(1) # Find the named calendar cal = find_calendar_by_name(calendar_service, calendar_name) # ****, Google, could you have made getting the feed ID any more obscure? You know, like putting it in the field marked ID???!?!? # Smart people my ass. If Google employees are so damn smart, why do so many of them live in IRVINE??? cal_id = cal.content.src.replace('http://www.google.com', '') # Loop through the events, and insert them relative to the specified day for ev in evf.loadEvents(): event_dt = datetime.datetime(gig_date.year, gig_date.month, gig_date.day, ev.hour, ev.minute, 0) + timedelta(days=ev.interval_from_start) end_event_dt = event_dt + timedelta(hours=1) start_time = event_dt.strftime('%Y-%m-%dT%H:%M:%S.000Z') end_time = end_event_dt.strftime('%Y-%m-%dT%H:%M:%S.000Z') print "Start: %s" % str(event_dt) print "End: %s" % str(end_event_dt) print start_time print end_time event = gdata.calendar.CalendarEventEntry() event.title = atom.Title(text=ev.description) event.when.append(gdata.calendar.When(start_time=start_time, end_time=end_time)) new_event = calendar_service.InsertEvent(event, cal_id) # Finally, add the gig itself event = gdata.calendar.CalendarEventEntry() event.title = atom.Title(text=gig_description) end_gig_date = gig_date + timedelta(hours=1) start_time = gig_date.strftime('%Y-%m-%dT%H:%M:%S.000Z') end_time = end_gig_date.strftime('%Y-%m-%dT%H:%M:%S.000Z') event.when.append(gdata.calendar.When(start_time=start_time, end_time=end_time)) new_event = calendar_service.InsertEvent(event, cal_id)
Thank you for all your help!
I don't have the time to look at that massive section of code you posted, but in my above example, try changing that
to
and tell me if that makes a difference in Google Calender!
python Syntax (Toggle Plain Text)
event.location = item[3]
python Syntax (Toggle Plain Text)
if len(item) >= 3: event.where = item[3] else: event.where = "undefined location"
"Two good old boys in a fire-apple red convertible. Stoned. Ripped. Twisted. Good people."
- Hunter S. Thompson
my photography
- Hunter S. Thompson
my photography
•
•
Join Date: Mar 2009
Posts: 181
Reputation:
Solved Threads: 28
Try this:
You could try this for testing purposes so you don't have to edit your CVS structure:
python Syntax (Toggle Plain Text)
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:
python Syntax (Toggle Plain Text)
event.where.append(gdata.calendar.Where(value_string="Home"))
Last edited by adam1122; Apr 2nd, 2009 at 3:18 am.
•
•
Join Date: Mar 2009
Posts: 181
Reputation:
Solved Threads: 28
The description part should be handled by:
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.
Python Syntax (Toggle Plain Text)
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.
•
•
Join Date: Apr 2009
Posts: 29
Reputation:
Solved Threads: 0
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:
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
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:
Python Syntax (Toggle Plain Text)
Traceback (most recent call last): File "calendarUpdate.py", line 226, in <module> for ev in evf.loadEvents(): File "calendarUpdate.py", line 83, in loadEvents event.where.append(gdata.calendar.Where(value_string=item[3])) 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.
•
•
Join Date: Mar 2009
Posts: 181
Reputation:
Solved Threads: 28
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:
python Syntax (Toggle Plain Text)
event = gdata.calendar.CalendarEventEntry()
•
•
Join Date: Apr 2009
Posts: 29
Reputation:
Solved Threads: 0
Hi Adam1122,
I'm very new to this but trying hard to keep up. Here is where I put it:
old code:
New code:
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!!
I'm very new to this but trying hard to keep up. Here is where I put it:
old code:
Python Syntax (Toggle Plain Text)
# 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_list.append(event) # Close the file f.close() # Return the list 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_listI 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!!
![]() |
Other Threads in the Python Forum
- Previous Thread: can wxpython can become a web base program?
- Next Thread: Writing binary data to a file, so it can be recognised and opened as a jpeg?
| Thread Tools | Search this Thread |
Tag cloud for Python
abrupt ansi anti apache approximation array backend beginner binary book builtin calculator chmod code converter countpasswordentry curved dan08 dictionaries dictionary drive dynamic examples excel file filename float format function gui heads homework import inches input java launcher library line lines linux list lists loop mouse mysql mysqlquery number numbers numeric output parsing path phonebook plugin pointer port prime programming progressbar projects py2exe pygame pyqt pysimplewizard python random recursion redirect refresh scrolledtext software statictext statistics string strings sum table terminal text textarea thread threading time tkinter tlapse trick tricks tuple tutorial twoup ubuntu unicode urllib urllib2 variable windows wordgame write wxpython





