Google Apps Platform

Google Calendar API v2 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
except ImportError:
  from elementtree import ElementTree
import gdata.calendar.data
import gdata.calendar.client
import gdata.acl.data
import atom.data
import time

Authenticating to the Calendar service

The Python client library can be used to work with either public or private feeds. However the Calendar Data API only provides access to private feeds. That means your client application must send authenticated requests to the API. This can be done via ClientLogin username/password authentication, AuthSub, or OAuth.

Please see the Google Data APIs Authentication Overview for more information on AuthSub, OAuth, and ClientLogin.

Tip: The API supports SSL (HTTPS). If you're using AuthSub/OAuth, make sure to specify a scope of https://www.google.com/calendar/feeds/ in order to request feeds over SSL.

AuthSub for web applications

AuthSub Authentication for Web Applications should be used by client applications which need to authenticate their users to Google or Google Apps accounts. The operator does not need access to the username and password for the Google Calendar user—only an AuthSub token is required.

Request a single-use token

When the user first visits your application, they need to authenticate. Typically, developers print some text and a link directing the user to the AuthSub approval page to authenticate the user and request access to their documents. The Google Data Python client library provides a function, generate_auth_sub_url() to generate this URL. The code below sets up a link to the AuthSubRequest page.

import gdata.gauth

def GetAuthSubUrl():
  next = 'http://www.example.com/myapp.py'
  scopes = ['https://www.google.com/calendar/feeds/']
  secure = False  # set secure=True to request a secure AuthSub token
  session = True
  return gdata.gauth.generate_auth_sub_url(next, scopes, secure=secure, session=session)

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

If you want to authenticate users on a Google Apps hosted domain, pass the domain name to generate_auth_sub_url():

def GetAuthSubUrl():
  domain = 'example.com'
  next = 'http://www.example.com/myapp.py'
  scopes = ['https://www.google.com/calendar/feeds/']
  secure = False  # set secure=True to request a secure AuthSub token
  session = True
  return gdata.gauth.generate_auth_sub_url(next, scopes, secure=secure, session=session, domain=domain)

The generate_auth_sub_url() method takes the following parameters that each correspond to a query parameter used by the AuthSubRequest handler:

  • The next URL — URL that Google will redirect to after the user logs into their account and grants access; http://www.example.com/myapp.py in the example above.
  • The scopehttps://www.google.com/calendar/feeds/ in the example above. Note, both are used as a convenience to your app. Later, if you decide to initiate API requests over SSL, your existing AuthSub tokens will be valid.
  • The secure flag — a boolean to indicate whether the token will be used in secure and registered mode or not; False in the example above.
  • The session flag — a second boolean to indicate whether the single-use token will later be exchanged for a session token or not; True in the example above.

Upgrading to a session token

See Using AuthSub with the Google Data API Client Libraries.

Retrieving information about a session token

See Using AuthSub with the Google Data API Client Libraries.

Revoking a session token

See Using AuthSub with the Google Data API Client Libraries.

Tip: Once your application has successfully acquired a long lived sessions token, store that token in your database to recall for later use. There's no need to send the user back to AuthSub on every run of your application. Use client.auth_token = gdata.gauth.AuthSubToken(TOKEN_STR) to set an existing token on the client.

OAuth for web or installed/mobile applications

OAuth can be used as an alternative to AuthSub, and is intended for web applications. OAuth is similar to using the secure and registered mode of AuthSub in that all data requests must be digitally signed and you must register your domain.

Fetching a request token

See Using OAuth with the Google Data API Client Libraries.

Authorizing a request token

See Using OAuth with the Google Data API Client Libraries.

Upgrading to an access token

See Using OAuth with the Google Data API Client Libraries.

Tip: Once your application has successfully acquired an OAuth access token, store that token in your database to recall for later use. There's no need to send the user back through OAuth on every run of your application. Use client.auth_token = gdata.gauth.OAuthHmacToken(consumer_key, consumer_secret, oauth_token, oauth_secret, gdata.gauth.ACCESS_TOKEN) to set an existing token on the client.

ClientLogin for installed/mobile applications

ClientLogin should be used by installed or mobile applications which need to authenticate their users to Google accounts. On first run, your application prompts the user for their username/password. On subsequent requests, an authentication token is referenced.

To use ClientLogin, invoke the ClientLogin() method of CalendarClient object, which is inherited from GDClient. Specify the email address and password of the user on whose behalf your client is making requests. For example:

client = gdata.calendar.client.CalendarClient(source='yourCo-yourAppName-v1')
client.ClientLogin('user@gmail.com', 'pa$$word', client.source)

Tip: Once your application has successfully authenticated the user for the first time, store the auth token in your database to recall for later use. There's no need to prompt the user for his/her password on every run of your application. See Recalling an auth token for more information.

For more information on using ClientLogin in your Python applications, see the Using ClientLogin with the Google Data API Client Libraries.

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 CalendarClient object, then displays the title of each event.

calendar_client = gdata.calendar.client.CalendarClient()
username = 'username@gmail.com'
visibility = 'private-abcdefg'
projection = 'full'
feed_uri = calendar_client.GetCalendarEventFeedUri(calendar=username, visibility=visibility, projection=projection)

feed = calendar_client.GetCalendarEventFeed(uri=feed_uri)
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:

  • The username — indicating the username (in e-mail address form) of the calendar which you are accessing.
  • The visibility — specifying the private visibility feed along with the magic cookie value.
  • The 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 CalendarClient 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 CalendarClient object which has credentials specified via AuthSub or ClientLogin.

def PrintUserCalendars(calendar_client):
  feed = calendar_client.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 CalendarEntry 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_client):
  feed = calendar_client.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 CalendarEntry 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 CalendarEntry object and set the appropriate values. Then call the CalendarClient.InsertCalendar method, specifying the CalendarEntry. The following example uses an authenticated CalendarClient object called calendar_client:

# Create the calendar
calendar = gdata.calendar.data.CalendarEntry()
calendar.title = atom.data.Title(text='Little League Schedule')
calendar.summary = atom.data.Summary(text='This calendar contains practice and game times')
calendar.where.append(gdata.calendar.data.CalendarWhere(value='Oakland'))
calendar.color = gdata.calendar.data.ColorProperty(value='#2952A3')
calendar.timezone = gdata.calendar.data.TimeZoneProperty(value='America/Los_Angeles')
calendar.hidden = gdata.calendar.data.HiddenProperty(value='false')

new_calendar = calendar_client.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 CalendarEntry.

# calendar represents a previously retrieved CalendarEntry
calendar.title = atom.data.Title(text='New Title')
calendar.color = gdata.calendar.data.ColorProperty(value='#A32929')
updated_calendar = calendar_client.Update(calendar)

Deleting calendars

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

feed = calendar_client.GetOwnCalendarsFeed()
for entry in feed.entry:
  print 'Deleting calendar: %s' % entry.title.text
  calendar_client.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 CalendarEntry object and set the id property to specify the calendar to subscribe to. Then call the CalendarClient.InsertCalendarSubscription method, specifying the allcalendars feed. The following example uses an authenticated CalendarClient object called calendar_client to subscribe to the Google Doodles calendar:

calendar = gdata.calendar.data.CalendarEntry()
calendar.id = atom.data.Id(text='c4o4i7m2lbamc4k26sc2vokh5g%40group.calendar.google.com')
returned_calendar = calendar_client.InsertCalendarSubscription(calendar)

This invocation of InsertCalendarSubscription 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_client.GetAllCalendarsFeed()
for i, a_calendar in enumerate(feed.entry):
  a_calendar.color = gdata.calendar.data.ColorProperty(value='#0D7813')
  a_calendar.hidden = gdata.calendar.data.HiddenProperty(value='false')
  a_calendar.selected = gdata.calendar.data.SelectedProperty(value='false')
  updated_calendar = calendar_client.Update(a_calendar)

Deleting subscriptions

To remove an imported calendar, retrieve the calendar from the allcalendars feed and call the CalendarClient.Delete 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_client.GetCalendarEntry(calendar_url)
calendar_client.Delete(calendar_entry.GetEditLink().href)

Retrieving events

Retrieving events without query parameters

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

def PrintAllEventsOnDefaultCalendar(calendar_client):
  feed = calendar_client.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.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 CalendarClient. 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 CalendarClient object which has credentials specified via AuthSub or ClientLogin.

def DateRangeQuery(calendar_client, 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.client.CalendarEventQuery()
  query.start_min = start_date
  query.start_max = end_date
  feed = calendar_client.GetCalendarEventFeed(q=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,)
      print '\t\tEnd time:   %s' % (a_when.end,)

Retrieving events matching a full text query

The CalendarClient 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 CalendarClient object which has credentials specified via AuthSub or ClientLogin.

def FullTextQuery(calendar_client, text_query='Tennis'):
  print 'Full text query for events on Primary Calendar: \'%s\'' % ( text_query,)
  query = gdata.calendar.client.CalendarEventQuery(text_query=text_query)
  feed = calendar_client.GetCalendarEventFeed(q=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,)
      print '\t\tEnd time:   %s' % (a_when.end,)

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_client, 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.data.CalendarEventEntry()
    event.title = atom.data.Title(text=title)
    event.content = atom.data.Content(text=content)
    event.where.append(gdata.calendar.data.CalendarWhere(value=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.data.When(start=start_time, end=end_time))

    new_event = calendar_client.InsertEvent(event)

    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.data.CalendarEventEntry()
event.content = atom.data.Content(text='Tennis with John July 30 3pm-3:30pm')
event.quick_add = gdata.calendar.data.QuickAddProperty(value='true')

# Send the request and receive the response:
new_event = calendar_client.InsertEvent(event)

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.data.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.data.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.data.WebContent(url=url, width='300', height='136')
web_content.web_content_gadget_pref.append(
    gdata.calendar.data.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.data.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.data.CalendarEventEntry()
event.link.append(web_content_link)

new_event = calendar_client.InsertEvent(event)

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(calendar_client, 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.data.CalendarEventEntry()
    event.title = atom.data.Title(text=title)
    event.content = atom.data.Content(text=content)
    event.where.append(gdata.calendar.data.CalendarWhere(value=where))

    # Set a recurring event
    event.recurrence = gdata.data.Recurrence(text=recurrence_data)
    new_event = calendar_client.InsertEvent(event)

    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_client, 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_client.Update(event)

Note that the Update method (like InsertEvent) returns a CalendarEventEntry object created from the data returned by the server after the event is inserted. This represents the 'official' state of the event on the server.

Deleting events

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

def DeleteEvent(calendar_client, event):
  calendar_client.Delete(event)

Improving performance

Some special features are available to help you optimize your Calendar Data API requests.

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_client object is an authenticated instance of the CalendarClient class.

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

  # creating an event entry to insert
  insertEntry = gdata.calendar.data.CalendarEventEntry()
  insertEntry.title = atom.data.Title(text='Python: batch insert')
  insertEntry.content = atom.data.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.data.When(start=start_time,
    end=end_time))
  insertEntry.batch_id = gdata.data.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.data.BatchId(text='update-request')
    updateEntry.title = atom.data.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.data.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.data.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_client.ExecuteBatch(request_feed,
    gdata.calendar.client.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):
  query = gdata.calendar.client.CalendarEventQuery(text_query=text, max_results=1)

  feed = calendar_client.GetCalendarEventFeed(q=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_client is an authenticated CalendarClient object.

feed = calendar_client.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.data.CalendarAclEntry()
rule.scope = gdata.acl.data.AclScope(value='viewer@gmail.com', type='user')
roleValue = 'http://schemas.google.com/gCal/2005#%s' % ('freebusy')
rule.role = gdata.acl.data.AclRole(value=roleValue)
aclUrl = 'https://www.google.com/calendar/feeds/creator@gmail.com/acl/full'
returned_rule = calendar_client.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.acl.data.AclRole(value=roleValue)
updated_rule = calendar_client.Update(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_client.Delete(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_client, event,
                        name='http://www.example.com/schemas/2005#mycal.id',
                        value='1234'):
  event.extended_property.append(gdata.calendar.data.CalendarExtendedProperty(name=name, value=value))
  print 'Adding extended property to event: \'%s\'=\'%s\'' % (name, value,)
  return calendar_client.Update(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_client, 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.data.Reminder(minutes=minutes))

  print 'Adding %d minute reminder to event' % (minutes,)
  return calendar_client.Update(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.