Google Apps Platform

Google Calendar API v1 Developer's Guide: Python

This API is a subject to the Deprecation Policy and will be deprecated on November 17, 2014. Please use APIv3 instead.

Google Calendar allows client applications to view and update calendar events in the form of Google Data API feeds. Your client application can use the Google Calendar Data API to create new events, edit or delete existing events, and query for events that match particular criteria.

There are many possible uses for the Calendar Data API. For example, you can create a web front end for your group's calendar that uses Google Calendar as a back end. Or you can generate a public calendar for Google Calendar to display, based on your organization's event database. Or you can search relevant calendars to display a list of upcoming events on those calendars.

This document provides detailed examples for using the Python Client Library to work with the Google Calendar service. For help setting up the client library, see the Getting Started Guide. You will find examples of adding events, updating events, deleting events and querying events. If you're interested in understanding more about the underlying protocol used by the Python Client Library to interact with the Calendar Data API, please see the protocol tab.

Contents

Audience

This document is intended for programmers who want to write client applications using the Google Data API Python client library that can interact with Google Calendar.

Getting started

For help setting up the client library, see the Getting Started Guide. The Python client library is available for download from the project page or from the Subversion repository. You will also need to download and install the ElementTree package. Also note that to use the Python client library, you must be running Python 2.2 or newer.

A full working copy of this sample is available in the CalendarExample.py file, under the directory gdata-python-client/samples/calendar/. You can run the sample with the following arguments:

python calendarExample.py --user [[]username] --pw [[]password] --delete [[]true|false]

The sample performs a number of operations on the provided user's calendar to demonstrate the use of the Calendar Data API. Please see the Run method of the code for more details as to which operations are performed, but you'll want to be sure to use a test account so you don't modify or delete your real data.

To run the examples in this document in your own code, you'll need to use the following import statements:

try:
  from xml.etree import ElementTree # for Python 2.5 users
except ImportError:
  from elementtree import ElementTree
import gdata.calendar.service
import gdata.service
import atom.service
import gdata.calendar
import atom
import getopt
import sys
import string
import time

Authenticating to the Calendar service

The Python client library can be used to work with either public or private feeds. Public feeds are read-only, but do not require any authentication. Private feeds require that you authenticate to the calendar servers. This can be done via ClientLogin username/password authentication or AuthSub proxy authentication. The calendar service also allows authentication to a read-only private feed using magic cookie authentication.

For an overview of authentication with the calendar API, see the relevant entry in the FAQ. For more information about authentication with Google Data APIs in general, please see the authentication documentation.

AuthSub proxy authentication

AuthSub proxy authentication is used by web applications which need to authenticate their users to Google accounts. The website operator does not need access to the username and password for the calendar user - only special AuthSub tokens are required. Please see the AuthSub documentation for more detailed information.

When a user first visits your application, they have not yet been authenticated. In this case, you need to print some text and a link directing the user to Google to authenticate your request for access to their calendar. The Python Google Data API client library provides a function to generate this URL from the CalendarService class. The code below sets up a link to the AuthSubRequest page.

def GetAuthSubUrl():
  next = 'http://www.coolcalendarsite.com/welcome.pyc'
  scope = 'https://www.google.com/calendar/feeds/'
  secure = False
  session = True
  calendar_service = gdata.calendar.service.CalendarService()
  return calendar_service.GenerateAuthSubURL(next, scope, secure, session);

authSubUrl = GetAuthSubUrl();
print '<a href="%s">Login to your Google account</a>' % authSubUrl

Notice the parameters sent to the GenerateAuthSubURL method:

  • next, the URL of the page that Google should redirect the user to after authentication.
  • scope, indicating that the application will only access Google Calendar feeds.
  • secure, indicating that the token returned will not be a secure token.
  • session, indicating this token can be exchanged for a multi-use (session) token.

The URL will look something like this:

https://www.google.com/accounts/AuthSubRequest?scope=http%3A%2F%2Fwww.google.com%2Fcalendar%2Ffeeds%2F&session=1&secure=0&next=http%3A%2F%2Fwww.coolcalendarsite.com%2Fwelcome.pyc%2F

The user will then follow the link to Google's site and authenticate to their Google account.

After the user authenticates, they will be redirected back to the next URL. The URL will have a single-use token value appended to it as a query parameter. The URL the user will be redirected to will look something like this:

http://www.coolcalendarsite.com/welcome.pyc?token=14a87fe98219731acd516

The calendar service only supports session tokens, so we need to exchange this single-use token for a session token. The following code snippet shows how to upgrade the single-use token to a session token, and then retrieve the user's calendar list.

calendar_service = gdata.calendar.service.CalendarService()
calendar_service.auth_token = authsub_token
calendar_service.UpgradeToSessionToken()
feed = calendar_service.GetCalendarListFeed()
for i, a_calendar in enumerate(feed.entry):
  print '\t%s. %s' % (i, a_calendar.title.text,)

In this snippet, the authsub_token variable contains the value from the token query parameter in the URL. There are several ways to retrieve this value, for example:

import cgi

parameters = cgi.FieldStorage()
authsub_token = parameters[[]'token']

This token value represents a single-use AuthSub token. Since we specified session = True above, this token can be exchanged for an AuthSub session token using the CalendarService.UpgradeToSessionToken method, which calls the AuthSubSessionToken service.

ClientLogin username/password authentication

To use ClientLogin (also called "Authentication for Installed Applications"), first create a instance of CalendarService and set the credentials, then invoke the ProgrammaticLogin method. For example:

calendar_service = gdata.calendar.service.CalendarService()
calendar_service.email = 'username@domain.com'
calendar_service.password = 'mypassword'
calendar_service.source = 'Google-Calendar_Python_Sample-1.0'
calendar_service.ProgrammaticLogin()

Calling calendar_service.ProgrammaticLogin() will send the email and password defined above to Google's ClientLogin authentication service. This service responds with a token which is then added as part of the Authorization header to the CalendarService object. All future requests using this CalendarService object will include this Authorization header. For more information about authentication systems, see the Google Account Authentication documentation.

Magic cookie authentication

Magic cookie authentication can be used in cases where you want to retrieve a read-only feed containing private calendar events. A magic cookie can be specified in the URL of the feed. In the following example feed URL, 'abcdefg' is the magic cookie:

https://www.google.com/calendar/feeds/username@gmail.com/private-abcdefg/full/

The appropriate value for a magic cookie can be obtained through the 'Calendar details' page in the UI for each of your calendars. It is labeled as a 'Private Address'.

The following code creates a CalendarEventQuery object with the magic cookie information, retrieves the feed using the CalendarService object, then displays the title of each event.

username = 'username@gmail.com'
visibility = 'private-abcdefg'
projection = 'full'
query = gdata.calendar.service.CalendarEventQuery(username, visibility, projection)

calendar_service = gdata.calendar.service.CalendarService()
feed = calendar_service.CalendarQuery(query)
for i, an_event in enumerate(feed.entry):
  print '\t%s. %s' % (i, an_event.title.text,)

Notice the options used to create the CalendarEventQuery:

  • username, indicating the username (in e-mail address form) of the calendar which you are accessing
  • visibility specifying the private visibility feed along with the magic cookie value
  • projection, indicating the use of the full projection (as opposed to the basic projection, composite projection or others)

Please see the Reference Guide for more information about the Calendar feed types.

Retrieving a list of calendars

The Calendar Data API provides several ways to access the list of calendars that appear in the Google Calendar web application. There are three types of calendars in this list: primary, secondary, and imported calendars. A primary calendar is created for a user when they sign up for a Google Calendar account. All other calendars created by that user are called secondary calendars. Imported calendars are calendars that a user subscribes to that someone else has created.

Retrieving all calendars

You can get a list of a the authenticated user's calendars by sending a GET request to the allcalendars feed URL:

https://www.google.com/calendar/feeds/default/allcalendars/full

The CalendarService object supports retrieving this list of calendars for the authenticated user. This is the same list of calendars that is presented in the UI -- including primary, secondary, and imported calendars. While calendars marked as 'hidden' do not appear in the UI, they are included in the feed. You cannot retrieve a list of another user's calendars. The following example presumes that you already have a CalendarService object which has credentials specified via AuthSub or ClientLogin.

def PrintUserCalendars(calendar_service):
  feed = calendar_service.GetAllCalendarsFeed()
  print feed.title.text
  for i, a_calendar in enumerate(feed.entry):
    print '\t%s. %s' % (i, a_calendar.title.text,)

Although we are only printing the title of the calendar in this case, we can also access other information, including the color of the calendar, the timezone, and more. See CalendarListEntry for more details on available attributes.

Note: This feed is accessible only using an authentication token, so you cannot use a magic cookie URL to access the feed. For information on authentication, see the earlier Authenticating to the Calendar service section.

Retrieving only calendars that a user owns

There is also an owncalendars feed that you can query to retrieve the list of calendars that the authenticated user has owner access to. The owncalendars feed is located at:

https://www.google.com/calendar/feeds/default/owncalendars/full

Querying this feed will return a list of calendars that includes the user's primary and secondary calendars, as well as any imported calendars for which the user has the "Make changes AND manage sharing" permission. The feed can be accessed by replacing the URL in the previous example:

def PrintOwnCalendars(calendar_service):
  feed = calendar_service.GetOwnCalendarsFeed()
  print feed.title.text
  for i, a_calendar in enumerate(feed.entry):
    print '\t%s. %s' % (i, a_calendar.title.text,)

Although we are only printing the title of the calendar in this case, we can also access other information, including the color of the calendar, the timezone, and more. See CalendarListEntry for more details on available attributes.

Managing Calendars

The owncalendars feed can also be used to create, update, and delete calendars. Calendars created through the owncalendars feed will be secondary calendars.

Creating new calendars

To create a new calendar, first instantiate a CalendarListEntry object and set the appropriate values. Then call the CalendarService.InsertCalendar method, specifying the CalendarListEntry. The following example uses an authenticated CalendarService object called calendar_service:

# Create the calendar
calendar = gdata.calendar.CalendarListEntry()
calendar.title = atom.Title(text='Little League Schedule')
calendar.summary = atom.Summary(text='This calendar contains practice and game times')
calendar.where = gdata.calendar.Where(value_string='Oakland')
calendar.color = gdata.calendar.Color(value='#2952A3')
calendar.timezone = gdata.calendar.Timezone(value='America/Los_Angeles')
calendar.hidden = gdata.calendar.Hidden(value='false')

new_calendar = calendar_service.InsertCalendar(new_calendar=calendar)

Note: The <atom:id> field of the calendar entry should be null because the Google Calendar server will create an id for the entry when it process the request.

Updating existing calendars

You can update most information about the authenticated user's calendars via the owncalendars feed. The following example updates the title and color of a CalendarListEntry.

# calendar represents a previously retrieved CalendarListEntry
calendar.title = atom.Title(text='New Title')
calendar.color = gdata.calendar.Color(value='#A32929')
updated_calendar = calendar_service.UpdateCalendar(calendar=calendar)

Deleting calendars

To delete a calendar, call the Delete method on the CalendarService object, passing the appropriate edit link. The following example attempts to delete all the calendars that are returned in the feed:

feed = calendar_service.GetOwnCalendarsFeed()
for entry in feed.entry:
  print 'Deleting calendar: %s' % entry.title.text
  calendar_service.Delete(entry.GetEditLink().href)

Note: You can't delete a user's primary calendar, i.e. the calendar with the user's email address in the ID. If you try to delete a primary calendar, a gdata.Service.RequestError will be thrown.

Managing subscriptions to calendars

The allcalendars feed can be used to modify the list of imported calendars that a user has subscribed to. Calendars inserted via the allcalendars feed will be added as imported calendars.

Adding new subscriptions

To subscribe to an existing calendar, you first need to find the calendar's ID. The calendar ID is available on the calendar settings page, next to the Calendar Address buttons. If you're subscribing to a user's primary calendar, the id will just be the user's email address.

Once you have the calendar's ID, you can instantiate a CalendarListEntry object and set the id property to specify the calendar to subscribe to. Then call the CalendarService.InsertCalendarSubscription method, specifying the allcalendars feed. The following example uses an authenticated CalendarService object called calendar_service to subscribe to the Google Doodles calendar:

calendar = gdata.calendar.CalendarListEntry()
calendar.id = atom.Id(text='c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com')
returned_calendar = calendar_service.InsertCalendarSubscription(calendar)

This invocation of InsertSubscription will have different results based on the current state of the calendar. If the subscription doesn't exist, then the calendar is added to the user's list of imported calendars. If the user has already subscribed to the calendar, then the server will return a 409 Conflict. If the calendar inserted is currently hidden, it will become visible.

Updating calendar subscriptions

You can update the following personalization settings of a calendar using the allcalendars feed:

  • color - the color of the calendar in the UI.
  • hidden - whether or not the calendar is shown in the UI.
  • selected - whether or not the calendar is selected in the UI.

The personalization settings can be modified with the allcalendars feed even if the user doesn't own the calendar. However, the title and summary of the calendar can only be updated by an owner of the calendar using the owncalendars feed. The following example makes all the calendars in the feed visible but not selected and turns them green:

feed = calendar_service.GetAllCalendarsFeed()
for i, a_calendar in enumerate(feed.entry):
  a_calendar.color = gdata.calendar.Color(value='#0D7813')
  a_calendar.hidden = gdata.calendar.Hidden(value='false')
  a_calendar.selected = gdata.calendar.Selected(value='false')
  updated_calendar = calendar_service.UpdateCalendar(calendar=a_calendar)

Deleting subscriptions

To remove an imported calendar, retrieve the calendar from the allcalendars feed and call the CalendarService.DeleteCalendarEntry method, passing the edit URL. The following example removes the subscription to the Google Doodles calendar that was added in a previous example:

calendar_url = 'https://www.google.com/calendar/feeds/default/allcalendars/full/c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com'
calendar_entry = calendar_service.GetCalendarListEntry(calendar_url)
calendar_service.DeleteCalendarEntry(calendar_entry.GetEditLink().href) 

Retrieving events

Retrieving events without query parameters

Like the list of calendars, events are also retrieved using the CalendarService class. This example specifies the use of the private visibility feed which requires that the CalendarService object was already authenticated using AuthSub or ClientLogin.

def PrintAllEventsOnDefaultCalendar(calendar_service):
  feed = calendar_service.GetCalendarEventFeed()
  print 'Events on Primary Calendar: %s' % (feed.title.text,)
  for i, an_event in enumerate(feed.entry):
    print '\t%s. %s' % (i, an_event.title.text,)
    for p, a_participant in enumerate(an_event.who):
      print '\t\t%s. %s' % (p, a_participant.email,)
      print '\t\t\t%s' % (a_participant.name,)
      print '\t\t\t%s' % (a_participant.attendee_status.value,)

When invoked with no parameters, the GetCalendarEventFeed method returns the user's primary calendar. By default, the server limits the result set initially returned, but you can use the max_results query parameter to ask the server to send additional results back. Additionally, you can page through the results returned by using the feed.GetNextLink().href value to get the location of the next set of results. We'll show you how to create detailed queries like this as we progress through this guide.

Retrieving events for a specified date range

To print out all events between January 1 2007 and July 1 2007, you can create a query and use it to retrieve information from the CalendarService. Note that while the start_min is inclusive, the start_max is exclusive, so specifying a start_max of '2007-07-01' will include those events up until 2007-06-30 11:59:59PM. Again, the following example presumes that you already have a CalendarService object which has credentials specified via AuthSub or ClientLogin.

def DateRangeQuery(calendar_service, start_date='2007-01-01', end_date='2007-07-01'):
  print 'Date range query for events on Primary Calendar: %s to %s' % (start_date, end_date,)
  query = gdata.calendar.service.CalendarEventQuery('default', 'private', 'full')
  query.start_min = start_date
  query.start_max = end_date
  feed = calendar_service.CalendarQuery(query)
  for i, an_event in enumerate(feed.entry):
    print '\t%s. %s' % (i, an_event.title.text,)
    for a_when in an_event.when:
      print '\t\tStart time: %s' % (a_when.start_time,)
      print '\t\tEnd time:   %s' % (a_when.end_time,)

Retrieving events matching a full text query

The CalendarService class also supports full-text queries. The full-text query searches the title and content of an event, but it does not search the value of extended properties at the time of this writing. It uses the default (primary) calendar of the authenticated user and uses the private visibility/full projection feed. Please see the Calendar feed types section of the reference guide for more information on the feed types. Again, the following example presumes that you already have a CalendarService object which has credentials specified via AuthSub or ClientLogin.

def FullTextQuery(calendar_service, text_query='Tennis'):
  print 'Full text query for events on Primary Calendar: \'%s\'' % ( text_query,)
  query = gdata.calendar.service.CalendarEventQuery('default', 'private', 'full', text_query)
  feed = calendar_service.CalendarQuery(query)
  for i, an_event in enumerate(feed.entry):
    print '\t%s. %s' % (i, an_event.title.text,)
    print '\t\t%s. %s' % (i, an_event.content.text,)
    for a_when in an_event.when:
      print '\t\tStart time: %s' % (a_when.start_time,)
      print '\t\tEnd time:   %s' % (a_when.end_time,)

Creating events

The Calendar Data API allows you to create two types of events: single-occurrence events and recurring events, which are set up to repeat on a predetermined schedule.

Creating single-occurrence events

To insert a single-occurrence event into a Calendar feed, we first create the CalendarEventEntry and then add it to the calendar using the InsertEvent method. The InsertEvent method returns a tuple that contains a boolean indicating success or failure. Upon success, the tuple will contain the calendar entry that was added. On failure, the tuple will contain the HTTP status code, reason for failure, and message body returned from the server.

def InsertSingleEvent(calendar_service, title='One-time Tennis with Beth',
                      content='Meet for a quick lesson', where='On the courts',
                      start_time=None, end_time=None):
    event = gdata.calendar.CalendarEventEntry()
    event.title = atom.Title(text=title)
    event.content = atom.Content(text=content)
    event.where.append(gdata.calendar.Where(value_string=where))

    if start_time is None:
      # Use current time for the start_time and have the event last 1 hour
      start_time = time.strftime('%Y-%m-%dT%H:%M:%S.000Z', time.gmtime())
      end_time = time.strftime('%Y-%m-%dT%H:%M:%S.000Z', time.gmtime(time.time() + 3600))
    event.when.append(gdata.calendar.When(start_time=start_time, end_time=end_time))

    new_event = calendar_service.InsertEvent(event, '/calendar/feeds/default/private/full')

    print 'New single event inserted: %s' % (new_event.id.text,)
    print '\tEvent edit URL: %s' % (new_event.GetEditLink().href,)
    print '\tEvent HTML URL: %s' % (new_event.GetHtmlLink().href,)

    return new_event

Note that some members of the CalendarEventEntry class are stored as arrays and others are not. This is based on the Google Data API event "kind" specification. Members which are allowed to occur more than once, such as where and who, are stored as arrays. Even for these elements, Google Calendar may limit the length of the array to one element, such as in the case of the member. The general motto to use when working with the Calendar Data API is that functionality not available through the GUI will not be available through the API. Please see the Event kind section of the Data API common elements documentation for more information.

Creating quick add events

To create an event using Google Calendar's quick add feature, set the entry's content to the quick add string you'd like to use. Then set the quick_add property on the new entry, as follows:

event = gdata.calendar.CalendarEventEntry()
event.content = atom.Content(text='Tennis with John July 30 3pm-3:30pm')
event.quick_add = gdata.calendar.QuickAdd(value='true')

# Send the request and receive the response:
new_event = calendar_service.InsertEvent(event, '/calendar/feeds/default/private/full')

Notice that it's not necessary to set the title property when creating an event with quick add; the title is parsed automatically (in this case, "Tennis with John").

Creating Calendar Event Gadgets

You can also insert Calendar Event Gadgets events using the Python Client Library. Calendar Event Gadgets, formerly called web content, can contain images, HTML pages, or gadgets.

To create a simple Calendar Event Gadget that displays an image, first instantiate new gdata.calendar.WebContent and gdata.calendar.WebContentLink objects and set their properties, as follows:

# Create a WebContent object
url = 'http://www.google.com/logos/worldcup06.gif'
web_content = gdata.calendar.WebContent(url=url, width='276', height='120')

# Create a WebContentLink object that contains the WebContent object
title = 'World Cup'
href = 'http://www.google.com/calendar/images/google-holiday.gif'
type = 'image/gif'
web_content_link = gdata.calendar.WebContentLink(title=title, href=href,
    link_type=type, web_content=web_content)

This code sets up WebContent and WebContentLink objects to display the World Cup doodle (dimensions 276x120, and located at http://www.google.com/logos/worldcup06.gif). The icon at http://www.google.com/calendar/images/google-holiday.gif will be used to display the Calendar Event Gadget in the Calendar user interface before it is clicked.

The process is very similar to create a Calendar Event Gadget that displays a gadget, but this time the type should be application/x-google-gadgets+xml. You'll also need to get the gadget's URL from the iGoogle Directory. This example configures a Calendar Event Gadget to display the DateTime gadget and specifies the appropriate user preferences.

# Create a WebContent object
url = 'http://google.com/ig/modules/datetime.xml'
web_content = gdata.calendar.WebContent(url=url, width='300', height='136')
web_content.gadget_pref.append(
    gdata.calendar.WebContentGadgetPref(name='color', value='green'))

# Create a WebContentLink object that contains the WebContent object
title = 'Date and Time Gadget'
href = 'http://www.google.com/calendar/images/google-holiday.gif'
type = 'application/x-google-gadgets+xml'
web_content_link = gdata.calendar.WebContentLink(title=title, href=href,
    link_type=type, web_content=web_content)

Once you've created the WebContentLink object, append this object to the collection of links in the CalendarEventEntry object and insert the event:

# Create an event that contains this web content
event = gdata.calendar.CalendarEventEntry()
event.link.append(web_content_link)

new_event = calendar_service.InsertEvent(event,
    '/calendar/feeds/default/private/full')

This inserts the Calendar Event Gadget on the current date. Please see the section on Creating single-occurrence events for information on how to set the start_time property to choose the date when the Calendar Event Gadget should appear on the calendar.

Note: For more information on Calendar Event Gadgets, check out the documentation here.

Creating recurring events

Creating a recurring event is just like creating a single-occurrence event except that we have to specify the recurrence information in the CalendarEventEntry object that we're adding. Here's an example showing how to add a recurring event:

def InsertRecurringEvent(calender_service, title='Weekly Tennis with Beth',
                         content='Meet for a quick lesson', where='On the courts',
                         recurrence_data=None):
    if recurrence_data is None:
      recurrence_data = ('DTSTART;VALUE=DATE:20070501\r\n'
        + 'DTEND;VALUE=DATE:20070502\r\n'
        + 'RRULE:FREQ=WEEKLY;BYDAY=Tu;UNTIL=20070904\r\n')

    event = gdata.calendar.CalendarEventEntry()
    event.title = atom.Title(text=title)
    event.content = atom.Content(text=content)
    event.where.append(gdata.calendar.Where(value_string=where))

    # Set a recurring event
    event.recurrence = gdata.calendar.Recurrence(text=recurrence_data)
    new_event = calendar_service.InsertEvent(event, '/calendar/feeds/default/private/full')

    print 'New recurring event inserted: %s' % (new_event.id.text,)
    print '\tEvent edit URL: %s' % (new_event.GetEditLink().href,)
    print '\tEvent HTML URL: %s' % (new_event.GetHtmlLink().href,)

    return new_event

The recurrence string follows the iCalendar standard (RFC 2445). Please see the gd:recurrence section of the Data API common elements documentation for more information on gd:recurrence syntax.

Updating events

The general methodology for updating an event is to retrieve the existing event from the server, update the properties you wish to change and save the changes. Here's some sample code to update the title of an event that we've already retrieved from the service.

def UpdateTitle(calendar_service, event, new_title='Updated event title'):
  previous_title = event.title.text
  event.title.text = new_title
  print 'Updating title of event from:\'%s\' to:\'%s\'' % (previous_title, event.title.text,)
  return calendar_service.UpdateEvent(event.GetEditLink().href, event)

Note that the UpdateEvent method (like InsertEvent) returns the CalendarEventEntry object based upon the data returned from the server after the event is inserted. This represents the 'official' state of the event on the server. The 'edit' link returned in this event can be used for future updates. Due to the use of the 'optimistic concurrency' method of version control, most services do not allow you to send multiple update requests using the same edit URL. Please see the Optimistic Concurrency section of the Google Data API Reference Guide for more information

Deleting events

To delete an existing event, just call the DeleteEvent method and pass in the edit link from the CalendarEventEntry, like this:

def DeleteEvent(calendar_service, event):
  calendar_service.DeleteEvent(event.GetEditLink().href)

Performing multiple operations with a batch request

If you're performing a lot of operations, the time it takes to send and and receive all those HTTP messages can really add up, making your app slow and unresponsive. With batch requests you can have the server perform multiple operations with a single HTTP request. The basic idea is that you create a CalendarEventFeed object and add an entry for each operation you want to perform. The following code snippet builds and submits a batch request that contains four operations, one each for creating, querying, updating, and deleting an event, but you can use any combination of operations that you want. The snippet also shows how to check the batch response to make sure the operations were successful. Note that the calendar_service object is an authenticated instance of the CalendarService class.

def batchRequest():
  # feed that holds all the batch rquest entries
  request_feed = gdata.calendar.CalendarEventFeed()

  # creating an event entry to insert
  insertEntry = gdata.calendar.CalendarEventEntry()
  insertEntry.title = atom.Title(text='Python: batch insert')
  insertEntry.content = atom.Content(text='my content')
  start_time = '2008-06-01T09:00:00.000-07:00'
  end_time = '2008-06-01T10:00:00.000-07:00'
  insertEntry.when.append(gdata.calendar.When(start_time=start_time,
    end_time=end_time))
  insertEntry.batch_id = gdata.BatchId(text='insert-request')

  # add the insert entry to the batch feed
  request_feed.AddInsert(entry=insertEntry)

  updateEntry = getOneEvent('Python')
  if updateEntry:
    updateEntry.batch_id = gdata.BatchId(text='update-request')
    updateEntry.title = atom.Title(text='Python: batch update')
    # add the update entry to the batch feed
    request_feed.AddUpdate(entry=updateEntry)

  queryEntry = getOneEvent('Python')
  if queryEntry:
    queryEntry.batch_id = gdata.BatchId(text='query-request')
    # add the query entry to the batch feed
    request_feed.AddQuery(entry=queryEntry)

  deleteEntry = getOneEvent('Python')
  if deleteEntry:
    deleteEntry.batch_id = gdata.BatchId(text='delete-request')
    # add the delete entry to the batch feed
    request_feed.AddDelete(entry=deleteEntry)

  # submit the batch request to the server
  response_feed = calendar_service.ExecuteBatch(request_feed,
    gdata.calendar.service.DEFAULT_BATCH_URL)

  # iterate the response feed to get the operation status
  for entry in response_feed.entry:
    print 'batch id: %s' % (entry.batch_id.text,)
    print 'status: %s' % (entry.batch_status.code,)
    print 'reason: %s' % (entry.batch_status.reason,)

def getOneEvent(text):
  username = 'default'
  visibility = 'private'
  projection = 'full'
  query = gdata.calendar.service.CalendarEventQuery(username, visibility, projection)
  query[[]'q'] = text
  query[[]'max-results'] = '1'

  feed = calendar_service.CalendarQuery(query)

  if len(feed.entry) > 0:
    return feed.entry[[]0]
  else:
    return None

When working with batch requests, the size of the request must be under a megabyte and it's best to limit batches to 50-100 operations at a time. You can find more information about batch operations in the Google Data API Batch Processing documentation.

Sharing calendars

This section describes how to retrieve and modify Calendar access control lists (ACLs) with the Python client library for Google Data APIs. An access control list identifies the set of users with whom a calendar is shared, and the access permissions of each user (read-only access, full access, etc.) For more information, see the ACL topic of the Protocol section.

Retrieving access control lists

To retrieve and print an access control lists of your default calendar, use the following code. Here calendar_service is an authenticated CalendarService object.

feed = calendar_service.GetCalendarAclFeed()
print feed.title.text
for i, a_rule in enumerate(feed.entry):
  print '\t%s. %s' % (i, a_rule.title.text,)
  print '\t\t Role: %s' % (a_rule.role.value,)
  print '\t\t Scope %s - %s' % (a_rule.scope.type, a_rule.scope.value)

To access an ACL feed for a secondary calendar, you need to get the ACL feed URI from the calendar metafeed (see Retrieving a list of calendars). For each calendar in the metafeed, the ACL feed URI is contained in a link element where rel="http://schemas.google.com/acl/2007#accessControlList". These links have the form https://www.google.com/calendar/feeds/<calendarId>/acl/full.

An CalendarAclEntry consists of a scope, which defines a user with access to this calendar, and a role, which defines how much access he or she has. Valid roles are:

  • "freebusy" - this user can only see free/busy information.
  • "read" - this user can see all event details.
  • "editor" - this user can make changes to events.
  • "owner" - this user can make changes and manage sharing.

Note: Google Data ACLs define scopes that encompass more than one user, though the examples here only use the scope of type "user" for simplicity. Specifically, "domain" (available only in Google Apps) indicates that an access rule applies to all users with email addresses in the domain, while "default" specifies an access rule that applies to all users. For more information, see the GAcl namespace element reference.

Adding a user to an access control list

To add a user to a calendar's access control list you might do the following:

rule = gdata.calendar.CalendarAclEntry()
rule.scope = gdata.calendar.Scope(value='viewer@gmail.com', type='user')
roleValue = 'http://schemas.google.com/gCal/2005#%s' % ('freebusy')
rule.role = gdata.calendar.Role(value=roleValue)
aclUrl = '/calendar/feeds/creator@gmail.com/acl/full'
returned_rule = calendar_service.InsertAclEntry(rule, aclUrl)

This code allows viewer@gmail.com to have "freebusy" access to creator@gmail.com's calendar. Note that if an attempt is made to add an entry with a scope whose type and value match another entry already in the access control list, the operation will fail with error code 409 (Conflict).

Updating a user's role in an ACL

In order to change a user's access level to a calendar, update the CalendarAclEntry with the following code. Here returned_rule is the ACL entry returned from the call to the Insert method in the previous example:

roleValue = 'http://schemas.google.com/gCal/2005#%s' % ('read')
returned_rule.role = gdata.calendar.Role(value=roleValue)
updated_rule = calendar_service.UpdateAclEntry(returned_rule.GetEditLink().href, returned_rule)

This code changes the role of the existing ACL entry from "freebusy" to "read" access privileges for the user jdoe@gmail.com.

Note: It is not possible to modify the scope of an CalendarAclEntry when updating it; only the role can be modified. An attempt to update the scope will result in a 403 (Forbidden) error.

Removing a user from an access control list

To remove a user from a calendar's access control list, do the following:

calendar_service.DeleteAclEntry(entry.GetEditLink().href)

Here entry is a CalendarAclEntry that was already defined as a variable or retrieved from a CalendarAclFeed. Executing this code will cause the user defined in entry's scope to lose access to this calendar.

Additional operations

This section describes other Calendar operations you can perform with the Google Data API Python client library.

Extended properties

You can add extended properties (arbitrary name-value pairs) to Calendar events. These can be used to store application-specific IDs or other small amounts of information your application needs when interacting with a Google Calendar. Extended properties are only accessible through the API – they do not appear in the Calendar user interface.

In this example, we are adding an extended property id with value 1234 to the Calendar entry myEntry. It is recommended that you specify the complete schema URL to avoid namespace collisions with other applications that use the same property name.

def AddExtendedProperty(calendar_service, event,
                        name='http://www.example.com/schemas/2005#mycal.id',
                        value='1234'):
  event.extended_property.append(gdata.calendar.ExtendedProperty(name=name, value=value))
  print 'Adding extended property to event: \'%s\'=\'%s\'' % (name, value,)
  return calendar_service.UpdateEvent(event.GetEditLink().href, event)

Reminders and Notifications

The following example shows how to add a reminder to an event. The example uses the default reminder settings for the user to determine what type of notifications are sent (email, sms, popup, etc.) and sets the reminder for 'minutes' number of minutes before the event. Currently you can only use values for minutes as specified in the Calendar GUI. Also, reminders are only available on a user's primary calendar.

def AddReminder(calendar_service, event, minutes=10):
  for a_when in event.when:
    if len(a_when.reminder) > 0:
      a_when.reminder[[]0].minutes = minutes
    else:
      a_when.reminder.append(gdata.calendar.Reminder(minutes=minutes))

  print 'Adding %d minute reminder to event' % (minutes,)
  return calendar_service.UpdateEvent(event.GetEditLink().href, event)

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.