cleanup comments
diff --git a/Makefile b/Makefile
index 75d64b5..a1123b3 100644
--- a/Makefile
+++ b/Makefile
@@ -3,3 +3,7 @@
test:
python runtests.py tests
+
+.PHONY: docs
+docs:
+ cd docs; ./build.sh
diff --git a/apiclient/discovery.py b/apiclient/discovery.py
index 45a6ba0..6c4d76f 100644
--- a/apiclient/discovery.py
+++ b/apiclient/discovery.py
@@ -14,12 +14,10 @@
"""Client for discovery based APIs
-A client library for Google's discovery
-based APIs.
+A client library for Google's discovery based APIs.
"""
__author__ = 'jcgregorio@google.com (Joe Gregorio)'
-
__all__ = [
'build', 'build_from_document'
]
@@ -49,8 +47,9 @@
def key2param(key):
- """
- max-results -> max_results
+ """Converts key names into parameter names.
+
+ For example, converting "max-results" -> "max_results"
"""
result = []
key = list(key)
@@ -107,10 +106,10 @@
resp, content = http.request(requested_url)
service = simplejson.loads(content)
- fn = os.path.join(os.path.dirname(__file__), "contrib",
- serviceName, "future.json")
+ fn = os.path.join(os.path.dirname(__file__), 'contrib',
+ serviceName, 'future.json')
try:
- f = file(fn, "r")
+ f = file(fn, 'r')
future = f.read()
f.close()
except IOError:
diff --git a/apiclient/ext/file.py b/apiclient/ext/file.py
new file mode 100644
index 0000000..0a2c97c
--- /dev/null
+++ b/apiclient/ext/file.py
@@ -0,0 +1,45 @@
+# Copyright 2010 Google Inc. All Rights Reserved.
+
+"""Utilities for OAuth.
+
+Utilities for making it easier to work with OAuth 1.0 credentials.
+"""
+
+__author__ = 'jcgregorio@google.com (Joe Gregorio)'
+
+import pickle
+
+from apiclient.oauth import Storage as BaseStorage
+
+
+class Storage(BaseStorage):
+ """Store and retrieve a single credential to and from a file."""
+
+ def __init__(self, filename):
+ self._filename = filename
+
+ def get(self):
+ """Retrieve Credential from file.
+
+ Returns:
+ apiclient.oauth.Credentials
+ """
+ try:
+ f = open(self._filename, 'r')
+ credentials = pickle.loads(f.read())
+ f.close()
+ except:
+ credentials = None
+ credentials.set_store(self.put)
+
+ return credentials
+
+ def put(self, credentials):
+ """Write a pickled Credentials to file.
+
+ Args:
+ credentials: Credentials, the credentials to store.
+ """
+ f = open(self._filename, 'w')
+ f.write(pickle.dumps(credentials))
+ f.close()
diff --git a/apiclient/http.py b/apiclient/http.py
index 8f64baf..cecf3f2 100644
--- a/apiclient/http.py
+++ b/apiclient/http.py
@@ -23,7 +23,7 @@
"""
def __init__(self, http, postproc, uri,
- method="GET",
+ method='GET',
body=None,
headers=None,
methodId=None):
@@ -139,7 +139,7 @@
"""
self.responses = responses
- def __call__(self, http, postproc, uri, method="GET", body=None,
+ def __call__(self, http, postproc, uri, method='GET', body=None,
headers=None, methodId=None):
"""Implements the callable interface that discovery.build() expects
of requestBuilder, which is to build an object compatible with
@@ -157,19 +157,21 @@
class HttpMock(object):
"""Mock of httplib2.Http"""
- def __init__(self, filename, headers):
+ def __init__(self, filename, headers=None):
"""
Args:
filename: string, absolute filename to read response from
headers: dict, header to return with response
"""
+ if headers is None:
+ headers = {'status': '200 OK'}
f = file(filename, 'r')
self.data = f.read()
f.close()
self.headers = headers
def request(self, uri,
- method="GET",
+ method='GET',
body=None,
headers=None,
redirections=1,
diff --git a/apiclient/model.py b/apiclient/model.py
index 68da13e..58cd624 100644
--- a/apiclient/model.py
+++ b/apiclient/model.py
@@ -2,7 +2,7 @@
#
# Copyright 2010 Google Inc. All Rights Reserved.
-"""Model objects for requests and responses
+"""Model objects for requests and responses.
Each API may support one or more serializations, such
as JSON, Atom, etc. The model classes are responsible
diff --git a/apiclient/oauth.py b/apiclient/oauth.py
index 68e4300..b9fe7d3 100644
--- a/apiclient/oauth.py
+++ b/apiclient/oauth.py
@@ -7,20 +7,19 @@
__author__ = 'jcgregorio@google.com (Joe Gregorio)'
+
import copy
-import datetime
import httplib2
import logging
import oauth2 as oauth
import urllib
import urlparse
-
from anyjson import simplejson
try:
- from urlparse import parse_qs, parse_qsl
+ from urlparse import parse_qsl
except ImportError:
- from cgi import parse_qs, parse_qsl
+ from cgi import parse_qsl
class Error(Exception):
@@ -37,6 +36,10 @@
pass
+class CredentialsInvalidError(Error):
+ pass
+
+
def _abstract():
raise NotImplementedError('You need to override this function')
@@ -85,6 +88,29 @@
pass
+class Storage(object):
+ """Base class for all Storage objects.
+
+ Store and retrieve a single credential.
+ """
+
+ def get(self):
+ """Retrieve credential.
+
+ Returns:
+ apiclient.oauth.Credentials
+ """
+ _abstract()
+
+ def put(self, credentials):
+ """Write a credential.
+
+ Args:
+ credentials: Credentials, the credentials to store.
+ """
+ _abstract()
+
+
class OAuthCredentials(Credentials):
"""Credentials object for OAuth 1.0a
"""
@@ -99,6 +125,37 @@
self.consumer = consumer
self.token = token
self.user_agent = user_agent
+ self.store = None
+
+ # True if the credentials have been revoked
+ self._invalid = False
+
+ @property
+ def invalid(self):
+ """True if the credentials are invalid, such as being revoked."""
+ return getattr(self, "_invalid", False)
+
+ def set_store(self, store):
+ """Set the storage for the credential.
+
+ Args:
+ store: callable, a callable that when passed a Credential
+ will store the credential back to where it came from.
+ This is needed to store the latest access_token if it
+ has been revoked.
+ """
+ self.store = store
+
+ def __getstate__(self):
+ """Trim the state down to something that can be pickled."""
+ d = copy.copy(self.__dict__)
+ del d['store']
+ return d
+
+ def __setstate__(self, state):
+ """Reconstitute the state of the object from being pickled."""
+ self.__dict__.update(state)
+ self.store = None
def authorize(self, http):
"""
@@ -137,7 +194,7 @@
req = oauth.Request.from_consumer_and_token(
self.consumer, self.token, http_method=method, http_url=uri)
req.sign_request(signer, self.consumer, self.token)
- if headers == None:
+ if headers is None:
headers = {}
headers.update(req.to_header())
if 'user-agent' in headers:
@@ -149,6 +206,15 @@
response_code = resp.status
if response_code in [301, 302]:
uri = resp['location']
+
+ # Update the stored credential if it becomes invalid.
+ if response_code == 401:
+ logging.info('Access token no longer valid: %s' % content)
+ self._invalid = True
+ if self.store is not None:
+ self.store(self)
+ raise CredentialsInvalidError("Credentials are no longer valid.")
+
return resp, content
http.request = new_request
@@ -210,7 +276,7 @@
resp, content = client.request(uri, 'POST', headers=headers,
body=body)
if resp['status'] != '200':
- logging.error('Failed to retrieve temporary authorization: %s' % content)
+ logging.error('Failed to retrieve temporary authorization: %s', content)
raise RequestError('Invalid response %s.' % resp['status'])
self.request_token = dict(parse_qsl(content))
@@ -247,7 +313,7 @@
uri = _oauth_uri('access', self.discovery, self.params)
resp, content = client.request(uri, 'POST', headers=headers)
if resp['status'] != '200':
- logging.error('Failed to retrieve access token: %s' % content)
+ logging.error('Failed to retrieve access token: %s', content)
raise RequestError('Invalid response %s.' % resp['status'])
oauth_params = dict(parse_qsl(content))
diff --git a/docs/apiclient.anyjson.html b/docs/apiclient.anyjson.html
index 7471a08..df64fcd 100644
--- a/docs/apiclient.anyjson.html
+++ b/docs/apiclient.anyjson.html
@@ -8,7 +8,7 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="apiclient.html"><font color="#ffffff">apiclient</font></a>.anyjson</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/apiclient/anyjson.py">/home/jcgregorio/projects/apiary/apiclient/anyjson.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/anyjson.py">/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/anyjson.py</a></font></td></tr></table>
<p><tt>Utility module to import a JSON module<br>
<br>
Hides all the messy details of exactly where<br>
diff --git a/docs/apiclient.contrib.html b/docs/apiclient.contrib.html
index 7ac2858..488fdaa 100644
--- a/docs/apiclient.contrib.html
+++ b/docs/apiclient.contrib.html
@@ -8,7 +8,7 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="apiclient.html"><font color="#ffffff">apiclient</font></a>.contrib</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/apiclient/contrib/__init__.py">/home/jcgregorio/projects/apiary/apiclient/contrib/__init__.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/contrib/__init__.py">/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/contrib/__init__.py</a></font></td></tr></table>
<p></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
diff --git a/docs/apiclient.discovery.html b/docs/apiclient.discovery.html
index dd83c1b..a192d16 100644
--- a/docs/apiclient.discovery.html
+++ b/docs/apiclient.discovery.html
@@ -8,11 +8,10 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="apiclient.html"><font color="#ffffff">apiclient</font></a>.discovery</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/apiclient/discovery.py">/home/jcgregorio/projects/apiary/apiclient/discovery.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/discovery.py">/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/discovery.py</a></font></td></tr></table>
<p><tt>Client for discovery based APIs<br>
<br>
-A client library for Google's discovery<br>
-based APIs.</tt></p>
+A client library for Google's discovery based APIs.</tt></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#aa55cc">
@@ -49,9 +48,11 @@
parameters {api} and {apiVersion} that when filled in<br>
produce an absolute URI to the discovery document for<br>
that service.<br>
- developerKey: string, key obtained from https://code.google.com/apis/console<br>
+ developerKey: string, key obtained<br>
+ from https://code.google.com/apis/console<br>
model: apiclient.Model, converts to and from the wire format<br>
- requestBuilder: apiclient.http.HttpRequest, encapsulator for an HTTP request<br>
+ requestBuilder: apiclient.http.HttpRequest, encapsulator for<br>
+ an HTTP request<br>
<br>
Returns:<br>
A Resource object with methods for interacting with<br>
diff --git a/docs/apiclient.errors.html b/docs/apiclient.errors.html
index f439bc0..037040f 100644
--- a/docs/apiclient.errors.html
+++ b/docs/apiclient.errors.html
@@ -8,7 +8,7 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="apiclient.html"><font color="#ffffff">apiclient</font></a>.errors</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/apiclient/errors.py">/home/jcgregorio/projects/apiary/apiclient/errors.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/errors.py">/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/errors.py</a></font></td></tr></table>
<p><tt>Errors for the library.<br>
<br>
All exceptions defined by the library<br>
diff --git a/docs/apiclient.ext.appengine.html b/docs/apiclient.ext.appengine.html
index 6604c00..b5aafca 100644
--- a/docs/apiclient.ext.appengine.html
+++ b/docs/apiclient.ext.appengine.html
@@ -8,7 +8,7 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="apiclient.html"><font color="#ffffff">apiclient</font></a>.<a href="apiclient.ext.html"><font color="#ffffff">ext</font></a>.appengine</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/apiclient/ext/appengine.py">/home/jcgregorio/projects/apiary/apiclient/ext/appengine.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/ext/appengine.py">/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/ext/appengine.py</a></font></td></tr></table>
<p><tt>Utilities for Google App Engine<br>
<br>
Utilities for making it easier to use the<br>
diff --git a/docs/apiclient.ext.authtools.html b/docs/apiclient.ext.authtools.html
index 2b97fd4..df9e16d 100644
--- a/docs/apiclient.ext.authtools.html
+++ b/docs/apiclient.ext.authtools.html
@@ -8,7 +8,7 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="apiclient.html"><font color="#ffffff">apiclient</font></a>.<a href="apiclient.ext.html"><font color="#ffffff">ext</font></a>.authtools</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/apiclient/ext/authtools.py">/home/jcgregorio/projects/apiary/apiclient/ext/authtools.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/ext/authtools.py">/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/ext/authtools.py</a></font></td></tr></table>
<p><tt>Command-line tools for authenticating via OAuth 1.0<br>
<br>
Do the OAuth 1.0 Three Legged Dance for<br>
diff --git a/docs/apiclient.ext.django_orm.html b/docs/apiclient.ext.django_orm.html
index 73e8bea..163f80e 100644
--- a/docs/apiclient.ext.django_orm.html
+++ b/docs/apiclient.ext.django_orm.html
@@ -8,7 +8,7 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="apiclient.html"><font color="#ffffff">apiclient</font></a>.<a href="apiclient.ext.html"><font color="#ffffff">ext</font></a>.django_orm</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/apiclient/ext/django_orm.py">/home/jcgregorio/projects/apiary/apiclient/ext/django_orm.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/ext/django_orm.py">/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/ext/django_orm.py</a></font></td></tr></table>
<p></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
diff --git a/docs/apiclient.ext.html b/docs/apiclient.ext.html
index e4aa0c9..5a7cfbe 100644
--- a/docs/apiclient.ext.html
+++ b/docs/apiclient.ext.html
@@ -8,7 +8,7 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="apiclient.html"><font color="#ffffff">apiclient</font></a>.ext</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/apiclient/ext/__init__.py">/home/jcgregorio/projects/apiary/apiclient/ext/__init__.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/ext/__init__.py">/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/ext/__init__.py</a></font></td></tr></table>
<p></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
diff --git a/docs/apiclient.html b/docs/apiclient.html
index f046500..bf91ae5 100644
--- a/docs/apiclient.html
+++ b/docs/apiclient.html
@@ -8,7 +8,7 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong>apiclient</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/apiclient/__init__.py">/home/jcgregorio/projects/apiary/apiclient/__init__.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/__init__.py">/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/__init__.py</a></font></td></tr></table>
<p></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
diff --git a/docs/apiclient.http.html b/docs/apiclient.http.html
index b18e2de..5daef03 100644
--- a/docs/apiclient.http.html
+++ b/docs/apiclient.http.html
@@ -8,7 +8,7 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="apiclient.html"><font color="#ffffff">apiclient</font></a>.http</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/apiclient/http.py">/home/jcgregorio/projects/apiary/apiclient/http.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/http.py">/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/http.py</a></font></td></tr></table>
<p><tt>Classes to encapsulate a single HTTP request.<br>
<br>
The classes implement a command pattern, with every<br>
@@ -50,7 +50,7 @@
<td colspan=2><tt>Mock of httplib2.Http<br> </tt></td></tr>
<tr><td> </td>
<td width="100%">Methods defined here:<br>
-<dl><dt><a name="HttpMock-__init__"><strong>__init__</strong></a>(self, filename, headers)</dt><dd><tt>Args:<br>
+<dl><dt><a name="HttpMock-__init__"><strong>__init__</strong></a>(self, filename, headers<font color="#909090">=None</font>)</dt><dd><tt>Args:<br>
filename: string, absolute filename to read response from<br>
headers: dict, header to return with response</tt></dd></dl>
diff --git a/docs/apiclient.model.html b/docs/apiclient.model.html
index 0df4c8f..9a4ae1d 100644
--- a/docs/apiclient.model.html
+++ b/docs/apiclient.model.html
@@ -8,8 +8,8 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="apiclient.html"><font color="#ffffff">apiclient</font></a>.model</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/apiclient/model.py">/home/jcgregorio/projects/apiary/apiclient/model.py</a></font></td></tr></table>
- <p><tt><a href="#Model">Model</a> objects for requests and responses<br>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/model.py">/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/model.py</a></font></td></tr></table>
+ <p><tt><a href="#Model">Model</a> objects for requests and responses.<br>
<br>
Each API may support one or more serializations, such<br>
as JSON, Atom, etc. The model classes are responsible<br>
diff --git a/docs/apiclient.oauth.html b/docs/apiclient.oauth.html
index bdf3a4f..c99f722 100644
--- a/docs/apiclient.oauth.html
+++ b/docs/apiclient.oauth.html
@@ -8,7 +8,7 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="apiclient.html"><font color="#ffffff">apiclient</font></a>.oauth</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/apiclient/oauth.py">/home/jcgregorio/projects/apiary/apiclient/oauth.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/oauth.py">/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/oauth.py</a></font></td></tr></table>
<p><tt>Utilities for OAuth.<br>
<br>
Utilities for making it easier to work with OAuth.</tt></p>
@@ -20,13 +20,12 @@
<tr><td bgcolor="#aa55cc"><tt> </tt></td><td> </td>
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="copy.html">copy</a><br>
-<a href="datetime.html">datetime</a><br>
-</td><td width="25%" valign=top><a href="httplib2.html">httplib2</a><br>
-<a href="logging.html">logging</a><br>
-</td><td width="25%" valign=top><a href="oauth2.html">oauth2</a><br>
-<a href="simplejson.html">simplejson</a><br>
-</td><td width="25%" valign=top><a href="urllib.html">urllib</a><br>
-<a href="urlparse.html">urlparse</a><br>
+<a href="httplib2.html">httplib2</a><br>
+</td><td width="25%" valign=top><a href="logging.html">logging</a><br>
+<a href="oauth2.html">oauth2</a><br>
+</td><td width="25%" valign=top><a href="simplejson.html">simplejson</a><br>
+<a href="urllib.html">urllib</a><br>
+</td><td width="25%" valign=top><a href="urlparse.html">urlparse</a><br>
</td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ee77aa">
diff --git a/docs/oauth2client.appengine.html b/docs/oauth2client.appengine.html
index 89e1552..4a491ad 100644
--- a/docs/oauth2client.appengine.html
+++ b/docs/oauth2client.appengine.html
@@ -8,11 +8,10 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="oauth2client.html"><font color="#ffffff">oauth2client</font></a>.appengine</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/oauth2client/appengine.py">/home/jcgregorio/projects/apiary/oauth2client/appengine.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/oauth2client/appengine.py">/usr/local/google/home/jcgregorio/projects/apiclient/oauth2client/appengine.py</a></font></td></tr></table>
<p><tt>Utilities for Google App Engine<br>
<br>
-Utilities for making it easier to use OAuth 2.0<br>
-on Google App Engine.</tt></p>
+Utilities for making it easier to use OAuth 2.0 on Google App Engine.</tt></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#aa55cc">
@@ -30,12 +29,6 @@
<tr><td bgcolor="#ee77aa"><tt> </tt></td><td> </td>
<td width="100%"><dl>
-<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
-</font></dt><dd>
-<dl>
-<dt><font face="helvetica, arial"><a href="oauth2client.appengine.html#StorageByKeyName">StorageByKeyName</a>
-</font></dt></dl>
-</dd>
<dt><font face="helvetica, arial"><a href="google.appengine.ext.db.html#Property">google.appengine.ext.db.Property</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
</font></dt><dd>
<dl>
@@ -43,6 +36,12 @@
</font></dt><dt><font face="helvetica, arial"><a href="oauth2client.appengine.html#FlowProperty">FlowProperty</a>
</font></dt></dl>
</dd>
+<dt><font face="helvetica, arial"><a href="oauth2client.client.html#Storage">oauth2client.client.Storage</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="oauth2client.appengine.html#StorageByKeyName">StorageByKeyName</a>
+</font></dt></dl>
+</dd>
</dl>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
@@ -51,8 +50,9 @@
<font color="#000000" face="helvetica, arial"><a name="CredentialsProperty">class <strong>CredentialsProperty</strong></a>(<a href="google.appengine.ext.db.html#Property">google.appengine.ext.db.Property</a>)</font></td></tr>
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
-<td colspan=2><tt>Utility property that allows easy<br>
-storage and retrieval of<br>
+<td colspan=2><tt>App Engine datastore <a href="google.appengine.ext.db.html#Property">Property</a> for Credentials.<br>
+ <br>
+Utility property that allows easy storage and retrieval of<br>
oath2client.Credentials<br> </tt></td></tr>
<tr><td> </td>
<td width="100%"><dl><dt>Method resolution order:</dt>
@@ -88,7 +88,7 @@
<br>
Args:<br>
verbose_name: User friendly name of property.<br>
- name: Storage name for property. By default, uses attribute name<br>
+ name: <a href="oauth2client.client.html#Storage">Storage</a> name for property. By default, uses attribute name<br>
as it is assigned in the Model sub-class.<br>
default: Default value for property if none is assigned.<br>
required: Whether property is required.<br>
@@ -138,8 +138,9 @@
<font color="#000000" face="helvetica, arial"><a name="FlowProperty">class <strong>FlowProperty</strong></a>(<a href="google.appengine.ext.db.html#Property">google.appengine.ext.db.Property</a>)</font></td></tr>
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
-<td colspan=2><tt>Utility property that allows easy<br>
-storage and retreival of an<br>
+<td colspan=2><tt>App Engine datastore <a href="google.appengine.ext.db.html#Property">Property</a> for Flow.<br>
+ <br>
+Utility property that allows easy storage and retreival of an<br>
oauth2client.Flow<br> </tt></td></tr>
<tr><td> </td>
<td width="100%"><dl><dt>Method resolution order:</dt>
@@ -172,7 +173,7 @@
<br>
Args:<br>
verbose_name: User friendly name of property.<br>
- name: Storage name for property. By default, uses attribute name<br>
+ name: <a href="oauth2client.client.html#Storage">Storage</a> name for property. By default, uses attribute name<br>
as it is assigned in the Model sub-class.<br>
default: Default value for property if none is assigned.<br>
required: Whether property is required.<br>
@@ -219,19 +220,25 @@
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">
<td colspan=3 valign=bottom> <br>
-<font color="#000000" face="helvetica, arial"><a name="StorageByKeyName">class <strong>StorageByKeyName</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+<font color="#000000" face="helvetica, arial"><a name="StorageByKeyName">class <strong>StorageByKeyName</strong></a>(<a href="oauth2client.client.html#Storage">oauth2client.client.Storage</a>)</font></td></tr>
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
<td colspan=2><tt>Store and retrieve a single credential to and from<br>
the App Engine datastore.<br>
<br>
-This Storage helper presumes the Credentials<br>
+This <a href="oauth2client.client.html#Storage">Storage</a> helper presumes the Credentials<br>
have been stored as a CredenialsProperty<br>
on a datastore model class, and that entities<br>
are stored by key_name.<br> </tt></td></tr>
<tr><td> </td>
-<td width="100%">Methods defined here:<br>
-<dl><dt><a name="StorageByKeyName-__init__"><strong>__init__</strong></a>(self, model, key_name, property_name)</dt><dd><tt>Constructor for Storage.<br>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="oauth2client.appengine.html#StorageByKeyName">StorageByKeyName</a></dd>
+<dd><a href="oauth2client.client.html#Storage">oauth2client.client.Storage</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="StorageByKeyName-__init__"><strong>__init__</strong></a>(self, model, key_name, property_name)</dt><dd><tt>Constructor for <a href="oauth2client.client.html#Storage">Storage</a>.<br>
<br>
Args:<br>
model: db.Model, model class<br>
@@ -249,7 +256,7 @@
credentials: Credentials, the credentials to store.</tt></dd></dl>
<hr>
-Data descriptors defined here:<br>
+Data descriptors inherited from <a href="oauth2client.client.html#Storage">oauth2client.client.Storage</a>:<br>
<dl><dt><strong>__dict__</strong></dt>
<dd><tt>dictionary for instance variables (if defined)</tt></dd>
</dl>
diff --git a/docs/oauth2client.client.html b/docs/oauth2client.client.html
index e900249..36bc502 100644
--- a/docs/oauth2client.client.html
+++ b/docs/oauth2client.client.html
@@ -8,7 +8,7 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="oauth2client.html"><font color="#ffffff">oauth2client</font></a>.client</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/oauth2client/client.py">/home/jcgregorio/projects/apiary/oauth2client/client.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/oauth2client/client.py">/usr/local/google/home/jcgregorio/projects/apiclient/oauth2client/client.py</a></font></td></tr></table>
<p><tt>An OAuth 2.0 client<br>
<br>
Tools for interacting with OAuth 2.0 protected<br>
@@ -42,15 +42,21 @@
</font></dt><dd>
<dl>
<dt><font face="helvetica, arial"><a href="oauth2client.client.html#OAuth2Credentials">OAuth2Credentials</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="oauth2client.client.html#AccessTokenCredentials">AccessTokenCredentials</a>
</font></dt></dl>
</dd>
+</dl>
+</dd>
<dt><font face="helvetica, arial"><a href="oauth2client.client.html#Flow">Flow</a>
</font></dt><dd>
<dl>
<dt><font face="helvetica, arial"><a href="oauth2client.client.html#OAuth2WebServerFlow">OAuth2WebServerFlow</a>
</font></dt></dl>
</dd>
-</dl>
+<dt><font face="helvetica, arial"><a href="oauth2client.client.html#Storage">Storage</a>
+</font></dt></dl>
</dd>
<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
</font></dt><dd>
@@ -58,7 +64,7 @@
<dt><font face="helvetica, arial"><a href="oauth2client.client.html#Error">Error</a>
</font></dt><dd>
<dl>
-<dt><font face="helvetica, arial"><a href="oauth2client.client.html#MissingParameter">MissingParameter</a>
+<dt><font face="helvetica, arial"><a href="oauth2client.client.html#AccessTokenCredentialsError">AccessTokenCredentialsError</a>
</font></dt><dt><font face="helvetica, arial"><a href="oauth2client.client.html#RequestError">RequestError</a>
</font></dt></dl>
</dd>
@@ -69,6 +75,166 @@
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">
<td colspan=3 valign=bottom> <br>
+<font color="#000000" face="helvetica, arial"><a name="AccessTokenCredentials">class <strong>AccessTokenCredentials</strong></a>(<a href="oauth2client.client.html#OAuth2Credentials">OAuth2Credentials</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
+<td colspan=2><tt><a href="#Credentials">Credentials</a> <a href="__builtin__.html#object">object</a> for OAuth 2.0<br>
+ <br>
+<a href="#Credentials">Credentials</a> can be applied to an httplib2.Http <a href="__builtin__.html#object">object</a> using the <a href="#AccessTokenCredentials-authorize">authorize</a>()<br>
+method, which then signs each request from that <a href="__builtin__.html#object">object</a> with the OAuth 2.0<br>
+access token. This set of credentials is for the use case where you have<br>
+acquired an OAuth 2.0 access_token from another place such as a JavaScript<br>
+client or another web application, and wish to use it from Python. Because<br>
+only the access_token is present it can not be refreshed and will in time<br>
+expire.<br>
+ <br>
+<a href="#OAuth2Credentials">OAuth2Credentials</a> objects may be safely pickled and unpickled.<br>
+ <br>
+Usage:<br>
+ credentials = <a href="#AccessTokenCredentials">AccessTokenCredentials</a>('<an access token>',<br>
+ 'my-user-agent/1.0')<br>
+ http = httplib2.Http()<br>
+ http = credentials.<a href="#AccessTokenCredentials-authorize">authorize</a>(http)<br>
+ <br>
+Exceptions:<br>
+ AccessTokenCredentialsExpired: raised when the access_token expires or is<br>
+ revoked.<br> </tt></td></tr>
+<tr><td> </td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="oauth2client.client.html#AccessTokenCredentials">AccessTokenCredentials</a></dd>
+<dd><a href="oauth2client.client.html#OAuth2Credentials">OAuth2Credentials</a></dd>
+<dd><a href="oauth2client.client.html#Credentials">Credentials</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="AccessTokenCredentials-__init__"><strong>__init__</strong></a>(self, access_token, user_agent)</dt><dd><tt>Create an instance of <a href="#OAuth2Credentials">OAuth2Credentials</a><br>
+ <br>
+This is one of the few types if <a href="#Credentials">Credentials</a> that you should contrust,<br>
+<a href="#Credentials">Credentials</a> objects are usually instantiated by a <a href="#Flow">Flow</a>.<br>
+ <br>
+Args:<br>
+ token_uri: string, URI of token endpoint.<br>
+ user_agent: string, The HTTP User-Agent to provide for this application.<br>
+ <br>
+Notes:<br>
+ store: callable, a callable that when passed a Credential<br>
+ will store the credential back to where it came from.</tt></dd></dl>
+
+<hr>
+Methods inherited from <a href="oauth2client.client.html#OAuth2Credentials">OAuth2Credentials</a>:<br>
+<dl><dt><a name="AccessTokenCredentials-__getstate__"><strong>__getstate__</strong></a>(self)</dt><dd><tt>Trim the state down to something that can be pickled.</tt></dd></dl>
+
+<dl><dt><a name="AccessTokenCredentials-__setstate__"><strong>__setstate__</strong></a>(self, state)</dt><dd><tt>Reconstitute the state of the <a href="__builtin__.html#object">object</a> from being pickled.</tt></dd></dl>
+
+<dl><dt><a name="AccessTokenCredentials-authorize"><strong>authorize</strong></a>(self, http)</dt><dd><tt>Authorize an httplib2.Http instance with these credentials.<br>
+ <br>
+Args:<br>
+ http: An instance of httplib2.Http<br>
+ or something that acts like it.<br>
+ <br>
+Returns:<br>
+ A modified instance of http that was passed in.<br>
+ <br>
+Example:<br>
+ <br>
+ h = httplib2.Http()<br>
+ h = credentials.<a href="#AccessTokenCredentials-authorize">authorize</a>(h)<br>
+ <br>
+You can't create a new OAuth<br>
+subclass of httplib2.Authenication because<br>
+it never gets passed the absolute URI, which is<br>
+needed for signing. So instead we have to overload<br>
+'request' with a closure that adds in the<br>
+Authorization header and then calls the original version<br>
+of 'request()'.</tt></dd></dl>
+
+<dl><dt><a name="AccessTokenCredentials-set_store"><strong>set_store</strong></a>(self, store)</dt><dd><tt>Set the storage for the credential.<br>
+ <br>
+Args:<br>
+ store: callable, a callable that when passed a Credential<br>
+ will store the credential back to where it came from.<br>
+ This is needed to store the latest access_token if it<br>
+ has expired and been refreshed.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="oauth2client.client.html#OAuth2Credentials">OAuth2Credentials</a>:<br>
+<dl><dt><strong>invalid</strong></dt>
+<dd><tt>True if the credentials are invalid, such as being revoked.</tt></dd>
+</dl>
+<hr>
+Data descriptors inherited from <a href="oauth2client.client.html#Credentials">Credentials</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary for instance variables (if defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list of weak references to the object (if defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom> <br>
+<font color="#000000" face="helvetica, arial"><a name="AccessTokenCredentialsError">class <strong>AccessTokenCredentialsError</strong></a>(<a href="oauth2client.client.html#Error">Error</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
+<td colspan=2><tt>Having only the access_token means no refresh is possible.<br> </tt></td></tr>
+<tr><td> </td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="oauth2client.client.html#AccessTokenCredentialsError">AccessTokenCredentialsError</a></dd>
+<dd><a href="oauth2client.client.html#Error">Error</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors inherited from <a href="oauth2client.client.html#Error">Error</a>:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list of weak references to the object (if defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="AccessTokenCredentialsError-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#AccessTokenCredentialsError-__init__">__init__</a>(...) initializes x; see x.__class__.__doc__ for signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = <built-in method __new__ of type object><dd><tt>T.<a href="#AccessTokenCredentialsError-__new__">__new__</a>(S, ...) -> a new <a href="__builtin__.html#object">object</a> with type S, a subtype of T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="AccessTokenCredentialsError-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#AccessTokenCredentialsError-__delattr__">__delattr__</a>('name') <==> del x.name</tt></dd></dl>
+
+<dl><dt><a name="AccessTokenCredentialsError-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#AccessTokenCredentialsError-__getattribute__">__getattribute__</a>('name') <==> x.name</tt></dd></dl>
+
+<dl><dt><a name="AccessTokenCredentialsError-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#AccessTokenCredentialsError-__getitem__">__getitem__</a>(y) <==> x[y]</tt></dd></dl>
+
+<dl><dt><a name="AccessTokenCredentialsError-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#AccessTokenCredentialsError-__getslice__">__getslice__</a>(i, j) <==> x[i:j]<br>
+ <br>
+Use of negative indices is not supported.</tt></dd></dl>
+
+<dl><dt><a name="AccessTokenCredentialsError-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="AccessTokenCredentialsError-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#AccessTokenCredentialsError-__repr__">__repr__</a>() <==> repr(x)</tt></dd></dl>
+
+<dl><dt><a name="AccessTokenCredentialsError-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#AccessTokenCredentialsError-__setattr__">__setattr__</a>('name', value) <==> x.name = value</tt></dd></dl>
+
+<dl><dt><a name="AccessTokenCredentialsError-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="AccessTokenCredentialsError-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#AccessTokenCredentialsError-__str__">__str__</a>() <==> str(x)</tt></dd></dl>
+
+<dl><dt><a name="AccessTokenCredentialsError-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom> <br>
<font color="#000000" face="helvetica, arial"><a name="Credentials">class <strong>Credentials</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
@@ -172,73 +338,14 @@
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">
<td colspan=3 valign=bottom> <br>
-<font color="#000000" face="helvetica, arial"><a name="MissingParameter">class <strong>MissingParameter</strong></a>(<a href="oauth2client.client.html#Error">Error</a>)</font></td></tr>
-
-<tr><td bgcolor="#ffc8d8"><tt> </tt></td><td> </td>
-<td width="100%"><dl><dt>Method resolution order:</dt>
-<dd><a href="oauth2client.client.html#MissingParameter">MissingParameter</a></dd>
-<dd><a href="oauth2client.client.html#Error">Error</a></dd>
-<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
-<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
-<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
-</dl>
-<hr>
-Data descriptors inherited from <a href="oauth2client.client.html#Error">Error</a>:<br>
-<dl><dt><strong>__weakref__</strong></dt>
-<dd><tt>list of weak references to the object (if defined)</tt></dd>
-</dl>
-<hr>
-Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
-<dl><dt><a name="MissingParameter-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingParameter-__init__">__init__</a>(...) initializes x; see x.__class__.__doc__ for signature</tt></dd></dl>
-
-<hr>
-Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
-<dl><dt><strong>__new__</strong> = <built-in method __new__ of type object><dd><tt>T.<a href="#MissingParameter-__new__">__new__</a>(S, ...) -> a new <a href="__builtin__.html#object">object</a> with type S, a subtype of T</tt></dl>
-
-<hr>
-Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
-<dl><dt><a name="MissingParameter-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingParameter-__delattr__">__delattr__</a>('name') <==> del x.name</tt></dd></dl>
-
-<dl><dt><a name="MissingParameter-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingParameter-__getattribute__">__getattribute__</a>('name') <==> x.name</tt></dd></dl>
-
-<dl><dt><a name="MissingParameter-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingParameter-__getitem__">__getitem__</a>(y) <==> x[y]</tt></dd></dl>
-
-<dl><dt><a name="MissingParameter-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingParameter-__getslice__">__getslice__</a>(i, j) <==> x[i:j]<br>
- <br>
-Use of negative indices is not supported.</tt></dd></dl>
-
-<dl><dt><a name="MissingParameter-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
-
-<dl><dt><a name="MissingParameter-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingParameter-__repr__">__repr__</a>() <==> repr(x)</tt></dd></dl>
-
-<dl><dt><a name="MissingParameter-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingParameter-__setattr__">__setattr__</a>('name', value) <==> x.name = value</tt></dd></dl>
-
-<dl><dt><a name="MissingParameter-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
-
-<dl><dt><a name="MissingParameter-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingParameter-__str__">__str__</a>() <==> str(x)</tt></dd></dl>
-
-<dl><dt><a name="MissingParameter-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
-
-<hr>
-Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
-<dl><dt><strong>__dict__</strong></dt>
-</dl>
-<dl><dt><strong>args</strong></dt>
-</dl>
-<dl><dt><strong>message</strong></dt>
-</dl>
-</td></tr></table> <p>
-<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
-<tr bgcolor="#ffc8d8">
-<td colspan=3 valign=bottom> <br>
<font color="#000000" face="helvetica, arial"><a name="OAuth2Credentials">class <strong>OAuth2Credentials</strong></a>(<a href="oauth2client.client.html#Credentials">Credentials</a>)</font></td></tr>
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
<td colspan=2><tt><a href="#Credentials">Credentials</a> <a href="__builtin__.html#object">object</a> for OAuth 2.0<br>
<br>
-<a href="#Credentials">Credentials</a> can be applied to an httplib2.Http <a href="__builtin__.html#object">object</a><br>
-using the <a href="#OAuth2Credentials-authorize">authorize</a>() method, which then signs each<br>
-request from that <a href="__builtin__.html#object">object</a> with the OAuth 2.0 access token.<br>
+<a href="#Credentials">Credentials</a> can be applied to an httplib2.Http <a href="__builtin__.html#object">object</a> using the <a href="#OAuth2Credentials-authorize">authorize</a>()<br>
+method, which then signs each request from that <a href="__builtin__.html#object">object</a> with the OAuth 2.0<br>
+access token.<br>
<br>
<a href="#OAuth2Credentials">OAuth2Credentials</a> objects may be safely pickled and unpickled.<br> </tt></td></tr>
<tr><td> </td>
@@ -254,16 +361,15 @@
<dl><dt><a name="OAuth2Credentials-__init__"><strong>__init__</strong></a>(self, access_token, client_id, client_secret, refresh_token, token_expiry, token_uri, user_agent)</dt><dd><tt>Create an instance of <a href="#OAuth2Credentials">OAuth2Credentials</a><br>
<br>
This constructor is not usually called by the user, instead<br>
-<a href="#OAuth2Credentials">OAuth2Credentials</a> objects are instantiated by<br>
-the <a href="#OAuth2WebServerFlow">OAuth2WebServerFlow</a>.<br>
+<a href="#OAuth2Credentials">OAuth2Credentials</a> objects are instantiated by the <a href="#OAuth2WebServerFlow">OAuth2WebServerFlow</a>.<br>
<br>
Args:<br>
- token_uri: string, URI of token endpoint<br>
- client_id: string, client identifier<br>
- client_secret: string, client secret<br>
- access_token: string, access token<br>
- token_expiry: datetime, when the access_token expires<br>
- refresh_token: string, refresh token<br>
+ token_uri: string, URI of token endpoint.<br>
+ client_id: string, client identifier.<br>
+ client_secret: string, client secret.<br>
+ access_token: string, access token.<br>
+ token_expiry: datetime, when the access_token expires.<br>
+ refresh_token: string, refresh token.<br>
user_agent: string, The HTTP User-Agent to provide for this application.<br>
<br>
<br>
@@ -275,7 +381,9 @@
<dl><dt><a name="OAuth2Credentials-__setstate__"><strong>__setstate__</strong></a>(self, state)</dt><dd><tt>Reconstitute the state of the <a href="__builtin__.html#object">object</a> from being pickled.</tt></dd></dl>
-<dl><dt><a name="OAuth2Credentials-authorize"><strong>authorize</strong></a>(self, http)</dt><dd><tt>Args:<br>
+<dl><dt><a name="OAuth2Credentials-authorize"><strong>authorize</strong></a>(self, http)</dt><dd><tt>Authorize an httplib2.Http instance with these credentials.<br>
+ <br>
+Args:<br>
http: An instance of httplib2.Http<br>
or something that acts like it.<br>
<br>
@@ -304,6 +412,11 @@
has expired and been refreshed.</tt></dd></dl>
<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>invalid</strong></dt>
+<dd><tt>True if the credentials are invalid, such as being revoked.</tt></dd>
+</dl>
+<hr>
Data descriptors inherited from <a href="oauth2client.client.html#Credentials">Credentials</a>:<br>
<dl><dt><strong>__dict__</strong></dt>
<dd><tt>dictionary for instance variables (if defined)</tt></dd>
@@ -329,15 +442,17 @@
</dl>
<hr>
Methods defined here:<br>
-<dl><dt><a name="OAuth2WebServerFlow-__init__"><strong>__init__</strong></a>(self, client_id, client_secret, scope, user_agent, authorization_uri<font color="#909090">='https://www.google.com/accounts/o8/oauth2/authorization'</font>, token_uri<font color="#909090">='https://www.google.com/accounts/o8/oauth2/token'</font>, **kwargs)</dt><dd><tt>Constructor for <a href="#OAuth2WebServerFlow">OAuth2WebServerFlow</a><br>
+<dl><dt><a name="OAuth2WebServerFlow-__init__"><strong>__init__</strong></a>(self, client_id, client_secret, scope, user_agent, auth_uri<font color="#909090">='https://www.google.com/accounts/o8/oauth2/authorization'</font>, token_uri<font color="#909090">='https://www.google.com/accounts/o8/oauth2/token'</font>, **kwargs)</dt><dd><tt>Constructor for <a href="#OAuth2WebServerFlow">OAuth2WebServerFlow</a><br>
<br>
Args:<br>
- client_id: string, client identifier<br>
- client_secret: string client secret<br>
- scope: string, scope of the credentials being requested<br>
+ client_id: string, client identifier.<br>
+ client_secret: string client secret.<br>
+ scope: string, scope of the credentials being requested.<br>
user_agent: string, HTTP User-Agent to provide for this application.<br>
- authorization_uri: string, URI for authorization endpoint<br>
- token_uri: string, URI for token endpoint<br>
+ auth_uri: string, URI for authorization endpoint. For convenience<br>
+ defaults to Google's endpoints but any OAuth 2.0 provider can be used.<br>
+ token_uri: string, URI for token endpoint. For convenience<br>
+ defaults to Google's endpoints but any OAuth 2.0 provider can be used.<br>
**kwargs: dict, The keyword arguments are all optional and required<br>
parameters for the OAuth calls.</tt></dd></dl>
@@ -429,6 +544,36 @@
</dl>
<dl><dt><strong>message</strong></dt>
</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom> <br>
+<font color="#000000" face="helvetica, arial"><a name="Storage">class <strong>Storage</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
+<td colspan=2><tt>Base class for all <a href="#Storage">Storage</a> objects.<br>
+ <br>
+Store and retrieve a single credential.<br> </tt></td></tr>
+<tr><td> </td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="Storage-get"><strong>get</strong></a>(self)</dt><dd><tt>Retrieve credential.<br>
+ <br>
+Returns:<br>
+ apiclient.oauth.<a href="#Credentials">Credentials</a></tt></dd></dl>
+
+<dl><dt><a name="Storage-put"><strong>put</strong></a>(self, credentials)</dt><dd><tt>Write a credential.<br>
+ <br>
+Args:<br>
+ credentials: <a href="#Credentials">Credentials</a>, the credentials to store.</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary for instance variables (if defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list of weak references to the object (if defined)</tt></dd>
+</dl>
</td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#55aa55">
diff --git a/docs/oauth2client.django_orm.html b/docs/oauth2client.django_orm.html
index f26e966..437b1c8 100644
--- a/docs/oauth2client.django_orm.html
+++ b/docs/oauth2client.django_orm.html
@@ -8,8 +8,11 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="oauth2client.html"><font color="#ffffff">oauth2client</font></a>.django_orm</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/oauth2client/django_orm.py">/home/jcgregorio/projects/apiary/oauth2client/django_orm.py</a></font></td></tr></table>
- <p></p>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/oauth2client/django_orm.py">/usr/local/google/home/jcgregorio/projects/apiclient/oauth2client/django_orm.py</a></font></td></tr></table>
+ <p><tt>OAuth 2.0 utilities for Django.<br>
+ <br>
+Utilities for using OAuth 2.0 in conjunction with<br>
+the Django datastore.</tt></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#aa55cc">
@@ -17,8 +20,11 @@
<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
<tr><td bgcolor="#aa55cc"><tt> </tt></td><td> </td>
-<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="django.db.models.html">django.db.models</a><br>
-</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="base64.html">base64</a><br>
+</td><td width="25%" valign=top><a href="django.db.models.html">django.db.models</a><br>
+</td><td width="25%" valign=top><a href="oauth2client.html">oauth2client</a><br>
+</td><td width="25%" valign=top><a href="pickle.html">pickle</a><br>
+</td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ee77aa">
<td colspan=3 valign=bottom> <br>
@@ -33,6 +39,12 @@
</font></dt><dt><font face="helvetica, arial"><a href="oauth2client.django_orm.html#FlowField">FlowField</a>
</font></dt></dl>
</dd>
+<dt><font face="helvetica, arial"><a href="oauth2client.client.html#Storage">oauth2client.client.Storage</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="oauth2client.django_orm.html#Storage">Storage</a>
+</font></dt></dl>
+</dd>
</dl>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
@@ -230,5 +242,66 @@
<dl><dt><strong>empty_strings_allowed</strong> = True</dl>
-</td></tr></table></td></tr></table>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom> <br>
+<font color="#000000" face="helvetica, arial"><a name="Storage">class <strong>Storage</strong></a>(<a href="oauth2client.client.html#Storage">oauth2client.client.Storage</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
+<td colspan=2><tt>Store and retrieve a single credential to and from<br>
+the datastore.<br>
+ <br>
+This <a href="#Storage">Storage</a> helper presumes the Credentials<br>
+have been stored as a CredenialsField<br>
+on a db model class.<br> </tt></td></tr>
+<tr><td> </td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="oauth2client.django_orm.html#Storage">Storage</a></dd>
+<dd><a href="oauth2client.client.html#Storage">oauth2client.client.Storage</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="Storage-__init__"><strong>__init__</strong></a>(self, model_class, key_name, key_value, property_name)</dt><dd><tt>Constructor for <a href="#Storage">Storage</a>.<br>
+ <br>
+Args:<br>
+ model: db.Model, model class<br>
+ key_name: string, key name for the entity that has the credentials<br>
+ key_value: string, key value for the entity that has the credentials<br>
+ property_name: string, name of the property that is an CredentialsProperty</tt></dd></dl>
+
+<dl><dt><a name="Storage-get"><strong>get</strong></a>(self)</dt><dd><tt>Retrieve Credential from datastore.<br>
+ <br>
+Returns:<br>
+ oauth2client.Credentials</tt></dd></dl>
+
+<dl><dt><a name="Storage-put"><strong>put</strong></a>(self, credentials)</dt><dd><tt>Write a Credentials to the datastore.<br>
+ <br>
+Args:<br>
+ credentials: Credentials, the credentials to store.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="oauth2client.client.html#Storage">oauth2client.client.Storage</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary for instance variables (if defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list of weak references to the object (if defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom> <br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt> </tt></td><td> </td>
+<td width="100%"><strong>__author__</strong> = 'jcgregorio@google.com (Joe Gregorio)'</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#7799ee">
+<td colspan=3 valign=bottom> <br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Author</strong></big></font></td></tr>
+
+<tr><td bgcolor="#7799ee"><tt> </tt></td><td> </td>
+<td width="100%">jcgregorio@google.com (Joe Gregorio)</td></tr></table>
</body></html>
\ No newline at end of file
diff --git a/docs/oauth2client.file.html b/docs/oauth2client.file.html
index 14e13d4..003db2a 100644
--- a/docs/oauth2client.file.html
+++ b/docs/oauth2client.file.html
@@ -8,7 +8,7 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="oauth2client.html"><font color="#ffffff">oauth2client</font></a>.file</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/oauth2client/file.py">/home/jcgregorio/projects/apiary/oauth2client/file.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/oauth2client/file.py">/usr/local/google/home/jcgregorio/projects/apiclient/oauth2client/file.py</a></font></td></tr></table>
<p><tt>Utilities for OAuth.<br>
<br>
Utilities for making it easier to work with OAuth 2.0<br>
@@ -29,7 +29,7 @@
<tr><td bgcolor="#ee77aa"><tt> </tt></td><td> </td>
<td width="100%"><dl>
-<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+<dt><font face="helvetica, arial"><a href="oauth2client.client.html#Storage">oauth2client.client.Storage</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
</font></dt><dd>
<dl>
<dt><font face="helvetica, arial"><a href="oauth2client.file.html#Storage">Storage</a>
@@ -40,18 +40,24 @@
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">
<td colspan=3 valign=bottom> <br>
-<font color="#000000" face="helvetica, arial"><a name="Storage">class <strong>Storage</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+<font color="#000000" face="helvetica, arial"><a name="Storage">class <strong>Storage</strong></a>(<a href="oauth2client.client.html#Storage">oauth2client.client.Storage</a>)</font></td></tr>
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
<td colspan=2><tt>Store and retrieve a single credential to and from a file.<br> </tt></td></tr>
<tr><td> </td>
-<td width="100%">Methods defined here:<br>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="oauth2client.file.html#Storage">Storage</a></dd>
+<dd><a href="oauth2client.client.html#Storage">oauth2client.client.Storage</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
<dl><dt><a name="Storage-__init__"><strong>__init__</strong></a>(self, filename)</dt></dl>
<dl><dt><a name="Storage-get"><strong>get</strong></a>(self)</dt><dd><tt>Retrieve Credential from file.<br>
<br>
Returns:<br>
- apiclient.oauth.Credentials</tt></dd></dl>
+ oauth2client.client.Credentials</tt></dd></dl>
<dl><dt><a name="Storage-put"><strong>put</strong></a>(self, credentials)</dt><dd><tt>Write a pickled Credentials to file.<br>
<br>
@@ -59,7 +65,7 @@
credentials: Credentials, the credentials to store.</tt></dd></dl>
<hr>
-Data descriptors defined here:<br>
+Data descriptors inherited from <a href="oauth2client.client.html#Storage">oauth2client.client.Storage</a>:<br>
<dl><dt><strong>__dict__</strong></dt>
<dd><tt>dictionary for instance variables (if defined)</tt></dd>
</dl>
diff --git a/docs/oauth2client.html b/docs/oauth2client.html
index a8f23e0..9ca5fd4 100644
--- a/docs/oauth2client.html
+++ b/docs/oauth2client.html
@@ -8,7 +8,7 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong>oauth2client</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/oauth2client/__init__.py">/home/jcgregorio/projects/apiary/oauth2client/__init__.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/oauth2client/__init__.py">/usr/local/google/home/jcgregorio/projects/apiclient/oauth2client/__init__.py</a></font></td></tr></table>
<p></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
diff --git a/docs/oauth2client.tools.html b/docs/oauth2client.tools.html
index 8a45a21..84fb49d 100644
--- a/docs/oauth2client.tools.html
+++ b/docs/oauth2client.tools.html
@@ -8,32 +8,20 @@
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="oauth2client.html"><font color="#ffffff">oauth2client</font></a>.tools</strong></big></big></font></td
><td align=right valign=bottom
-><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/oauth2client/tools.py">/home/jcgregorio/projects/apiary/oauth2client/tools.py</a></font></td></tr></table>
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/oauth2client/tools.py">/usr/local/google/home/jcgregorio/projects/apiclient/oauth2client/tools.py</a></font></td></tr></table>
<p><tt>Command-line tools for authenticating via OAuth 2.0<br>
<br>
-Do the OAuth 2.0 Web Server dance for<br>
-a command line application. Stores the generated<br>
-credentials in a common file that is used by<br>
-other example apps in the same directory.</tt></p>
+Do the OAuth 2.0 Web Server dance for a command line application. Stores the<br>
+generated credentials in a common file that is used by other example apps in<br>
+the same directory.</tt></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
-<tr bgcolor="#aa55cc">
-<td colspan=3 valign=bottom> <br>
-<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
-
-<tr><td bgcolor="#aa55cc"><tt> </tt></td><td> </td>
-<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="BaseHTTPServer.html">BaseHTTPServer</a><br>
-</td><td width="25%" valign=top><a href="logging.html">logging</a><br>
-</td><td width="25%" valign=top><a href="socket.html">socket</a><br>
-</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
-</td></tr></table></td></tr></table><p>
-<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#eeaa77">
<td colspan=3 valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
<tr><td bgcolor="#eeaa77"><tt> </tt></td><td> </td>
-<td width="100%"><dl><dt><a name="-run"><strong>run</strong></a>(flow, filename)</dt><dd><tt>Core code for a command-line application.</tt></dd></dl>
+<td width="100%"><dl><dt><a name="-run"><strong>run</strong></a>(flow, storage)</dt><dd><tt>Core code for a command-line application.</tt></dd></dl>
</td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#55aa55">
diff --git a/oauth2client/appengine.py b/oauth2client/appengine.py
index f35da8f..f939bc0 100644
--- a/oauth2client/appengine.py
+++ b/oauth2client/appengine.py
@@ -14,8 +14,7 @@
"""Utilities for Google App Engine
-Utilities for making it easier to use OAuth 2.0
-on Google App Engine.
+Utilities for making it easier to use OAuth 2.0 on Google App Engine.
"""
__author__ = 'jcgregorio@google.com (Joe Gregorio)'
@@ -29,8 +28,9 @@
class FlowProperty(db.Property):
- """Utility property that allows easy
- storage and retreival of an
+ """App Engine datastore Property for Flow.
+
+ Utility property that allows easy storage and retreival of an
oauth2client.Flow"""
# Tell what the user type is.
@@ -60,8 +60,9 @@
class CredentialsProperty(db.Property):
- """Utility property that allows easy
- storage and retrieval of
+ """App Engine datastore Property for Credentials.
+
+ Utility property that allows easy storage and retrieval of
oath2client.Credentials
"""
@@ -109,9 +110,9 @@
key_name: string, key name for the entity that has the credentials
property_name: string, name of the property that is an CredentialsProperty
"""
- self.model = model
- self.key_name = key_name
- self.property_name = property_name
+ self._model = model
+ self._key_name = key_name
+ self._property_name = property_name
def get(self):
"""Retrieve Credential from datastore.
@@ -119,8 +120,8 @@
Returns:
oauth2client.Credentials
"""
- entity = self.model.get_or_insert(self.key_name)
- credential = getattr(entity, self.property_name)
+ entity = self._model.get_or_insert(self._key_name)
+ credential = getattr(entity, self._property_name)
if credential and hasattr(credential, 'set_store'):
credential.set_store(self.put)
return credential
@@ -131,6 +132,6 @@
Args:
credentials: Credentials, the credentials to store.
"""
- entity = self.model.get_or_insert(self.key_name)
- setattr(entity, self.property_name, credentials)
+ entity = self._model.get_or_insert(self._key_name)
+ setattr(entity, self._property_name, credentials)
entity.put()
diff --git a/oauth2client/client.py b/oauth2client/client.py
index 5ba7af8..3d7ded7 100644
--- a/oauth2client/client.py
+++ b/oauth2client/client.py
@@ -41,7 +41,8 @@
pass
-class MissingParameter(Error):
+class AccessTokenCredentialsError(Error):
+ """Having only the access_token means no refresh is possible."""
pass
@@ -97,9 +98,9 @@
class OAuth2Credentials(Credentials):
"""Credentials object for OAuth 2.0
- Credentials can be applied to an httplib2.Http object
- using the authorize() method, which then signs each
- request from that object with the OAuth 2.0 access token.
+ Credentials can be applied to an httplib2.Http object using the authorize()
+ method, which then signs each request from that object with the OAuth 2.0
+ access token.
OAuth2Credentials objects may be safely pickled and unpickled.
"""
@@ -109,16 +110,15 @@
"""Create an instance of OAuth2Credentials
This constructor is not usually called by the user, instead
- OAuth2Credentials objects are instantiated by
- the OAuth2WebServerFlow.
+ OAuth2Credentials objects are instantiated by the OAuth2WebServerFlow.
Args:
- token_uri: string, URI of token endpoint
- client_id: string, client identifier
- client_secret: string, client secret
- access_token: string, access token
- token_expiry: datetime, when the access_token expires
- refresh_token: string, refresh token
+ token_uri: string, URI of token endpoint.
+ client_id: string, client identifier.
+ client_secret: string, client secret.
+ access_token: string, access token.
+ token_expiry: datetime, when the access_token expires.
+ refresh_token: string, refresh token.
user_agent: string, The HTTP User-Agent to provide for this application.
@@ -137,6 +137,15 @@
self.token_uri = token_uri
self.user_agent = user_agent
+ # True if the credentials have been revoked or expired and can't be
+ # refreshed.
+ self._invalid = False
+
+ @property
+ def invalid(self):
+ """True if the credentials are invalid, such as being revoked."""
+ return self._invalid
+
def set_store(self, store):
"""Set the storage for the credential.
@@ -178,24 +187,37 @@
'user-agent': self.user_agent,
'content-type': 'application/x-www-form-urlencoded'
}
- resp, content = http_request(self.token_uri, method='POST', body=body, headers=headers)
+ resp, content = http_request(
+ self.token_uri, method='POST', body=body, headers=headers)
if resp.status == 200:
# TODO(jcgregorio) Raise an error if loads fails?
d = simplejson.loads(content)
self.access_token = d['access_token']
self.refresh_token = d.get('refresh_token', self.refresh_token)
if 'expires_in' in d:
- self.token_expiry = datetime.timedelta(seconds = int(d['expires_in'])) + datetime.datetime.now()
+ self.token_expiry = datetime.timedelta(
+ seconds = int(d['expires_in'])) + datetime.datetime.now()
else:
self.token_expiry = None
if self.store is not None:
self.store(self)
else:
+ # An {'error':...} response body means the token is expired or revoked, so
+ # we flag the credentials as such.
+ try:
+ d = simplejson.loads(content)
+ if 'error' in d:
+ self._invalid = True
+ if self.store is not None:
+ self.store(self)
+ except:
+ pass
logging.error('Failed to retrieve access token: %s' % content)
raise RequestError('Invalid response %s.' % resp['status'])
def authorize(self, http):
- """
+ """Authorize an httplib2.Http instance with these credentials.
+
Args:
http: An instance of httplib2.Http
or something that acts like it.
@@ -232,7 +254,7 @@
else:
headers['user-agent'] = self.user_agent
resp, content = request_orig(uri, method, body, headers,
- redirections, connection_type)
+ redirections, connection_type)
if resp.status == 401:
logging.info("Refreshing because we got a 401")
self._refresh(request_orig)
@@ -245,6 +267,57 @@
return http
+class AccessTokenCredentials(OAuth2Credentials):
+ """Credentials object for OAuth 2.0
+
+ Credentials can be applied to an httplib2.Http object using the authorize()
+ method, which then signs each request from that object with the OAuth 2.0
+ access token. This set of credentials is for the use case where you have
+ acquired an OAuth 2.0 access_token from another place such as a JavaScript
+ client or another web application, and wish to use it from Python. Because
+ only the access_token is present it can not be refreshed and will in time
+ expire.
+
+ AccessTokenCredentials objects may be safely pickled and unpickled.
+
+ Usage:
+ credentials = AccessTokenCredentials('<an access token>',
+ 'my-user-agent/1.0')
+ http = httplib2.Http()
+ http = credentials.authorize(http)
+
+ Exceptions:
+ AccessTokenCredentialsExpired: raised when the access_token expires or is
+ revoked.
+ """
+
+ def __init__(self, access_token, user_agent):
+ """Create an instance of OAuth2Credentials
+
+ This is one of the few types if Credentials that you should contrust,
+ Credentials objects are usually instantiated by a Flow.
+
+ Args:
+ token_uri: string, URI of token endpoint.
+ user_agent: string, The HTTP User-Agent to provide for this application.
+
+ Notes:
+ store: callable, a callable that when passed a Credential
+ will store the credential back to where it came from.
+ """
+ super(AccessTokenCredentials, self).__init__(
+ access_token,
+ None,
+ None,
+ None,
+ None,
+ None,
+ user_agent)
+
+ def _refresh(self, http_request):
+ raise AccessTokenCredentialsError(
+ "The access_token is expired or invalid and can't be refreshed.")
+
class OAuth2WebServerFlow(Flow):
"""Does the Web Server Flow for OAuth 2.0.
@@ -252,18 +325,20 @@
"""
def __init__(self, client_id, client_secret, scope, user_agent,
- authorization_uri='https://www.google.com/accounts/o8/oauth2/authorization',
+ auth_uri='https://www.google.com/accounts/o8/oauth2/authorization',
token_uri='https://www.google.com/accounts/o8/oauth2/token',
**kwargs):
"""Constructor for OAuth2WebServerFlow
Args:
- client_id: string, client identifier
- client_secret: string client secret
- scope: string, scope of the credentials being requested
+ client_id: string, client identifier.
+ client_secret: string client secret.
+ scope: string, scope of the credentials being requested.
user_agent: string, HTTP User-Agent to provide for this application.
- authorization_uri: string, URI for authorization endpoint
- token_uri: string, URI for token endpoint
+ auth_uri: string, URI for authorization endpoint. For convenience
+ defaults to Google's endpoints but any OAuth 2.0 provider can be used.
+ token_uri: string, URI for token endpoint. For convenience
+ defaults to Google's endpoints but any OAuth 2.0 provider can be used.
**kwargs: dict, The keyword arguments are all optional and required
parameters for the OAuth calls.
"""
@@ -271,7 +346,7 @@
self.client_secret = client_secret
self.scope = scope
self.user_agent = user_agent
- self.authorization_uri = authorization_uri
+ self.auth_uri = auth_uri
self.token_uri = token_uri
self.params = kwargs
self.redirect_uri = None
@@ -298,7 +373,7 @@
'scope': self.scope,
}
query.update(self.params)
- parts = list(urlparse.urlparse(self.authorization_uri))
+ parts = list(urlparse.urlparse(self.auth_uri))
query.update(dict(parse_qsl(parts[4]))) # 4 is the index of the query part
parts[4] = urllib.urlencode(query)
return urlparse.urlunparse(parts)
@@ -324,8 +399,8 @@
'scope': self.scope
})
headers = {
- 'user-agent': self.user_agent,
- 'content-type': 'application/x-www-form-urlencoded'
+ 'user-agent': self.user_agent,
+ 'content-type': 'application/x-www-form-urlencoded'
}
h = httplib2.Http()
resp, content = h.request(self.token_uri, method='POST', body=body, headers=headers)
@@ -340,8 +415,8 @@
logging.info('Successfully retrieved access token: %s' % content)
return OAuth2Credentials(access_token, self.client_id, self.client_secret,
- refresh_token, token_expiry, self.token_uri,
- self.user_agent)
+ refresh_token, token_expiry, self.token_uri,
+ self.user_agent)
else:
logging.error('Failed to retrieve access token: %s' % content)
raise RequestError('Invalid response %s.' % resp['status'])
diff --git a/oauth2client/django_orm.py b/oauth2client/django_orm.py
index b5e020e..18a4a28 100644
--- a/oauth2client/django_orm.py
+++ b/oauth2client/django_orm.py
@@ -1,3 +1,17 @@
+# Copyright 2010 Google Inc. All Rights Reserved.
+
+"""OAuth 2.0 utilities for Django.
+
+Utilities for using OAuth 2.0 in conjunction with
+the Django datastore.
+"""
+
+__author__ = 'jcgregorio@google.com (Joe Gregorio)'
+
+import oauth2client
+import base64
+import pickle
+
from django.db import models
from oauth2client.client import Storage as BaseStorage
@@ -9,9 +23,9 @@
return 'VARCHAR'
def to_python(self, value):
- if value is None:
+ if not value:
return None
- if isinstance(value, oauth2client.Credentials):
+ if isinstance(value, oauth2client.client.Credentials):
return value
return pickle.loads(base64.b64decode(value))
@@ -27,10 +41,9 @@
return 'VARCHAR'
def to_python(self, value):
- print "In to_python", value
if value is None:
return None
- if isinstance(value, oauth2client.Flow):
+ if isinstance(value, oauth2client.client.Flow):
return value
return pickle.loads(base64.b64decode(value))
@@ -67,11 +80,14 @@
Returns:
oauth2client.Credentials
"""
+ credential = None
+
query = {self.key_name: self.key_value}
- entity = self.model_class.objects.filter(*query)[0]
- credential = getattr(entity, self.property_name)
- if credential and hasattr(credential, 'set_store'):
- credential.set_store(self.put)
+ entities = self.model_class.objects.filter(**query)
+ if len(entities) > 0:
+ credential = getattr(entities[0], self.property_name)
+ if credential and hasattr(credential, 'set_store'):
+ credential.set_store(self.put)
return credential
def put(self, credentials):
@@ -80,6 +96,7 @@
Args:
credentials: Credentials, the credentials to store.
"""
- entity = self.model_class(self.key_name=self.key_value)
+ args = {self.key_name: self.key_value}
+ entity = self.model_class(**args)
setattr(entity, self.property_name, credentials)
entity.save()
diff --git a/oauth2client/file.py b/oauth2client/file.py
index 0bcab03..12dee91 100644
--- a/oauth2client/file.py
+++ b/oauth2client/file.py
@@ -17,21 +17,22 @@
"""Store and retrieve a single credential to and from a file."""
def __init__(self, filename):
- self.filename = filename
+ self._filename = filename
def get(self):
"""Retrieve Credential from file.
Returns:
- apiclient.oauth.Credentials
+ oauth2client.client.Credentials
"""
try:
- f = open(self.filename, 'r')
+ f = open(self._filename, 'r')
credentials = pickle.loads(f.read())
f.close()
credentials.set_store(self.put)
except:
credentials = None
+
return credentials
def put(self, credentials):
@@ -40,6 +41,6 @@
Args:
credentials: Credentials, the credentials to store.
"""
- f = open(self.filename, 'w')
+ f = open(self._filename, 'w')
f.write(pickle.dumps(credentials))
f.close()
diff --git a/oauth2client/tools.py b/oauth2client/tools.py
index 644e72b..edc8827 100644
--- a/oauth2client/tools.py
+++ b/oauth2client/tools.py
@@ -14,14 +14,13 @@
"""Command-line tools for authenticating via OAuth 2.0
-Do the OAuth 2.0 Web Server dance for
-a command line application. Stores the generated
-credentials in a common file that is used by
-other example apps in the same directory.
+Do the OAuth 2.0 Web Server dance for a command line application. Stores the
+generated credentials in a common file that is used by other example apps in
+the same directory.
"""
__author__ = 'jcgregorio@google.com (Joe Gregorio)'
-__all__ = ["run"]
+__all__ = ['run']
def run(flow, storage):
diff --git a/samples/buzz/buzz.py b/samples/buzz/buzz.py
index a4f6840..cf3581b 100644
--- a/samples/buzz/buzz.py
+++ b/samples/buzz/buzz.py
@@ -14,7 +14,8 @@
from apiclient.discovery import build
from apiclient.oauth import FlowThreeLegged
from apiclient.ext.authtools import run
-
+from apiclient.ext.file import Storage
+from apiclient.oauth import CredentialsInvalidError
import httplib2
import pickle
@@ -25,11 +26,8 @@
def main():
- try:
- f = open("buzz.dat", "r")
- credentials = pickle.loads(f.read())
- f.close()
- except:
+ credentials = Storage('buzz.dat').get()
+ if credentials is None or credentials.invalid == True:
buzz_discovery = build("buzz", "v1").auth_discovery()
flow = FlowThreeLegged(buzz_discovery,
@@ -49,43 +47,49 @@
developerKey="AIzaSyDRRpR3GS1F1_jKNNM9HCNd2wJQyPG3oN0")
activities = p.activities()
- # Retrieve the first two activities
- activitylist = activities.list(
- max_results='2', scope='@self', userId='@me').execute()
- print "Retrieved the first two activities"
+ try:
+ # Retrieve the first two activities
+ activitylist = activities.list(
+ max_results='2', scope='@self', userId='@me').execute()
+ print "Retrieved the first two activities"
- # Retrieve the next two activities
- if activitylist:
- activitylist = activities.list_next(activitylist).execute()
- print "Retrieved the next two activities"
+ # Retrieve the next two activities
+ if activitylist:
+ activitylist = activities.list_next(activitylist).execute()
+ print "Retrieved the next two activities"
- # Add a new activity
- new_activity_body = {
- "data": {
- 'title': 'Testing insert',
- 'object': {
- 'content': u'Just a short note to show that insert is working. ☄',
- 'type': 'note'}
- }
- }
- activity = activities.insert(userId='@me', body=new_activity_body).execute()
- print "Added a new activity"
-
- activitylist = activities.list(
- max_results='2', scope='@self', userId='@me').execute()
-
- # Add a comment to that activity
- comment_body = {
- "data": {
- "content": "This is a comment"
+ # Add a new activity
+ new_activity_body = {
+ "data": {
+ 'title': 'Testing insert',
+ 'object': {
+ 'content':
+ u'Just a short note to show that insert is working. ☄',
+ 'type': 'note'}
}
- }
- item = activitylist['items'][0]
- comment = p.comments().insert(
- userId=item['actor']['id'], postId=item['id'], body=comment_body
- ).execute()
- print 'Added a comment to the new activity'
- pprint.pprint(comment)
+ }
+ activity = activities.insert(
+ userId='@me', body=new_activity_body).execute()
+ print "Added a new activity"
+
+ activitylist = activities.list(
+ max_results='2', scope='@self', userId='@me').execute()
+
+ # Add a comment to that activity
+ comment_body = {
+ "data": {
+ "content": "This is a comment"
+ }
+ }
+ item = activitylist['items'][0]
+ comment = p.comments().insert(
+ userId=item['actor']['id'], postId=item['id'], body=comment_body
+ ).execute()
+ print 'Added a comment to the new activity'
+ pprint.pprint(comment)
+ except CredentialsInvalidError:
+ print 'Your credentials are no longer valid.'
+ print 'Please re-run this application to re-authorize.'
if __name__ == '__main__':
main()
diff --git a/samples/latitude/latitude.py b/samples/latitude/latitude.py
index 029b74a..c2ec635 100644
--- a/samples/latitude/latitude.py
+++ b/samples/latitude/latitude.py
@@ -17,14 +17,35 @@
import httplib2
import pickle
+from apiclient.discovery import build
+from apiclient.oauth import FlowThreeLegged
+from apiclient.ext.authtools import run
+from apiclient.ext.file import Storage
+
# Uncomment to get detailed logging
# httplib2.debuglevel = 4
def main():
- f = open("latitude.dat", "r")
- credentials = pickle.loads(f.read())
- f.close()
+ credentials = Storage('latitude.dat').get()
+ if credentials is None or credentials.invalid == True:
+ auth_discovery = build("latitude", "v1").auth_discovery()
+ flow = FlowThreeLegged(auth_discovery,
+ # You MUST have a consumer key and secret tied to a
+ # registered domain to use the latitude API.
+ #
+ # https://www.google.com/accounts/ManageDomains
+ consumer_key='REGISTERED DOMAIN NAME',
+ consumer_secret='KEY GIVEN DURING REGISTRATION',
+ user_agent='google-api-client-python-latitude/1.0',
+ domain='REGISTERED DOMAIN NAME',
+ scope='https://www.googleapis.com/auth/latitude',
+ xoauth_displayname='Google API Latitude Example',
+ location='current',
+ granularity='city'
+ )
+
+ credentials = run(flow, 'latitude.dat')
http = httplib2.Http()
http = credentials.authorize(http)
diff --git a/samples/latitude/three_legged_dance.py b/samples/latitude/three_legged_dance.py
deleted file mode 100644
index 45595bc..0000000
--- a/samples/latitude/three_legged_dance.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright (C) 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Do the OAuth 1.0a three legged dance.
-
-Do the OAuth 1.0a three legged dance for
-a Buzz command line application. Store the generated
-credentials in a common file that is used by
-other example apps in the same directory.
-"""
-
-__author__ = 'jcgregorio@google.com (Joe Gregorio)'
-
-from apiclient.discovery import build
-from apiclient.oauth import FlowThreeLegged
-from apiclient.ext.authtools import run
-
-moderator_discovery = build("latitude", "v1").auth_discovery()
-
-flow = FlowThreeLegged(moderator_discovery,
- # You MUST have a consumer key and secret tied to a
- # registered domain to use the latitude API.
- #
- # https://www.google.com/accounts/ManageDomains
- consumer_key='REGISTERED DOMAIN NAME',
- consumer_secret='KEY GIVEN DURING REGISTRATION',
- user_agent='google-api-client-python-latitude/1.0',
- domain='REGISTERED DOMAIN NAME',
- scope='https://www.googleapis.com/auth/latitude',
- xoauth_displayname='Google API Latitude Example',
- location='current',
- granularity='city'
- )
-
-run(flow, 'latitude.dat')
diff --git a/samples/oauth2/appengine/main.py b/samples/oauth2/appengine/main.py
index 78634e7..f037bb8 100644
--- a/samples/oauth2/appengine/main.py
+++ b/samples/oauth2/appengine/main.py
@@ -48,21 +48,7 @@
credentials = StorageByKeyName(
Credentials, user.user_id(), 'credentials').get()
- if credentials:
- http = httplib2.Http()
- http = credentials.authorize(http)
- p = build("buzz", "v1", http=http)
- activities = p.activities()
- activitylist = activities.list(scope='@consumption',
- userId='@me').execute()
- path = os.path.join(os.path.dirname(__file__), 'welcome.html')
- logout = users.create_logout_url('/')
- self.response.out.write(
- template.render(
- path, {'activitylist': activitylist,
- 'logout': logout
- }))
- else:
+ if credentials is None or credentials.invalid == True:
flow = OAuth2WebServerFlow(
# Visit https://code.google.com/apis/console to
# generate your client_id, client_secret and to
@@ -78,6 +64,20 @@
authorize_url = flow.step1_get_authorize_url(callback)
memcache.set(user.user_id(), pickle.dumps(flow))
self.redirect(authorize_url)
+ else:
+ http = httplib2.Http()
+ http = credentials.authorize(http)
+ p = build("buzz", "v1", http=http)
+ activities = p.activities()
+ activitylist = activities.list(scope='@consumption',
+ userId='@me').execute()
+ path = os.path.join(os.path.dirname(__file__), 'welcome.html')
+ logout = users.create_logout_url('/')
+ self.response.out.write(
+ template.render(
+ path, {'activitylist': activitylist,
+ 'logout': logout
+ }))
class OAuthHandler(webapp.RequestHandler):
diff --git a/samples/oauth2/buzz/buzz.py b/samples/oauth2/buzz/buzz.py
index fe30a32..a009517 100644
--- a/samples/oauth2/buzz/buzz.py
+++ b/samples/oauth2/buzz/buzz.py
@@ -27,7 +27,7 @@
def main():
storage = Storage('buzz.dat')
credentials = storage.get()
- if not credentials:
+ if credentials is None or credentials.invalid == True:
flow = OAuth2WebServerFlow(
client_id='433807057907.apps.googleusercontent.com',
client_secret='jigtZpMApkRxncxikFpR+SFg',
diff --git a/samples/oauth2/django_sample/__init__.py b/samples/oauth2/django_sample/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/samples/oauth2/django_sample/__init__.py
diff --git a/samples/oauth2/django_sample/buzz/__init__.py b/samples/oauth2/django_sample/buzz/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/samples/oauth2/django_sample/buzz/__init__.py
diff --git a/samples/oauth2/django_sample/buzz/models.py b/samples/oauth2/django_sample/buzz/models.py
new file mode 100644
index 0000000..69c180c
--- /dev/null
+++ b/samples/oauth2/django_sample/buzz/models.py
@@ -0,0 +1,33 @@
+import pickle
+import base64
+
+from django.contrib import admin
+from django.contrib.auth.models import User
+from django.db import models
+
+from oauth2client.django_orm import FlowField
+from oauth2client.django_orm import CredentialsField
+
+# The Flow could also be stored in memcache since it is short lived.
+
+
+class FlowModel(models.Model):
+ id = models.ForeignKey(User, primary_key=True)
+ flow = FlowField()
+
+
+class CredentialsModel(models.Model):
+ id = models.ForeignKey(User, primary_key=True)
+ credential = CredentialsField()
+
+
+class CredentialsAdmin(admin.ModelAdmin):
+ pass
+
+
+class FlowAdmin(admin.ModelAdmin):
+ pass
+
+
+admin.site.register(CredentialsModel, CredentialsAdmin)
+admin.site.register(FlowModel, FlowAdmin)
diff --git a/samples/oauth2/django_sample/buzz/tests.py b/samples/oauth2/django_sample/buzz/tests.py
new file mode 100644
index 0000000..927cadf
--- /dev/null
+++ b/samples/oauth2/django_sample/buzz/tests.py
@@ -0,0 +1,24 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+
+class SimpleTest(TestCase):
+
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
diff --git a/samples/oauth2/django_sample/buzz/views.py b/samples/oauth2/django_sample/buzz/views.py
new file mode 100644
index 0000000..f6903b7
--- /dev/null
+++ b/samples/oauth2/django_sample/buzz/views.py
@@ -0,0 +1,65 @@
+import os
+import logging
+import httplib2
+
+from django.http import HttpResponse
+from django.core.urlresolvers import reverse
+from django.contrib.auth.decorators import login_required
+
+from oauth2client.django_orm import Storage
+from oauth2client.client import OAuth2WebServerFlow
+from django_sample.buzz.models import CredentialsModel
+from django_sample.buzz.models import FlowModel
+from apiclient.discovery import build
+
+from django.http import HttpResponseRedirect
+from django.shortcuts import render_to_response
+
+STEP2_URI = 'http://gregorio2.cnc.corp.google.com:8000/auth_return'
+
+
+@login_required
+def index(request):
+ storage = Storage(CredentialsModel, 'id', request.user, 'credential')
+ credential = storage.get()
+ if credential is None or credential.invalid == True:
+ flow = OAuth2WebServerFlow(
+ client_id='837647042410.apps.googleusercontent.com',
+ client_secret='+SWwMCL9d8gWtzPRa1lXw5R8',
+ scope='https://www.googleapis.com/auth/buzz',
+ user_agent='buzz-django-sample/1.0',
+ )
+
+ authorize_url = flow.step1_get_authorize_url(STEP2_URI)
+ f = FlowModel(id=request.user, flow=flow)
+ f.save()
+ return HttpResponseRedirect(authorize_url)
+ else:
+ http = httplib2.Http()
+ http = credential.authorize(http)
+ p = build("buzz", "v1", http=http)
+ activities = p.activities()
+ activitylist = activities.list(scope='@consumption',
+ userId='@me').execute()
+ logging.info(activitylist)
+
+ return render_to_response('buzz/welcome.html', {
+ 'activitylist': activitylist,
+ })
+
+
+@login_required
+def auth_return(request):
+ try:
+ f = FlowModel.objects.get(id=request.user)
+ print f
+ print f.flow
+ print dir(f.flow)
+ print type(f.flow)
+ credential = f.flow.step2_exchange(request.REQUEST)
+ storage = Storage(CredentialsModel, 'id', request.user, 'credential')
+ storage.put(credential)
+ f.delete()
+ return HttpResponseRedirect("/")
+ except FlowModel.DoesNotExist:
+ pass
diff --git a/samples/oauth2/django_sample/manage.py b/samples/oauth2/django_sample/manage.py
new file mode 100755
index 0000000..0b932da
--- /dev/null
+++ b/samples/oauth2/django_sample/manage.py
@@ -0,0 +1,15 @@
+#!/usr/bin/python
+from django.core.management import execute_manager
+try:
+ import settings # Assumed to be in the same directory.
+except ImportError:
+ import sys
+ sys.stderr.write("""Error: Can't find the file 'settings.py' in the
+directory containing %r. It appears you've customized things. You'll
+have to run django-admin.py, passing it your settings module.
+(If the file settings.py does indeed exist, it's causing an ImportError
+somehow.)\n""" % __file__)
+ sys.exit(1)
+
+if __name__ == "__main__":
+ execute_manager(settings)
diff --git a/samples/oauth2/django_sample/settings.py b/samples/oauth2/django_sample/settings.py
new file mode 100644
index 0000000..565d2e5
--- /dev/null
+++ b/samples/oauth2/django_sample/settings.py
@@ -0,0 +1,83 @@
+# Django settings for django_sample project.
+import os
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+ # ('Your Name', 'your_email@domain.com'),
+)
+
+MANAGERS = ADMINS
+
+DATABASE_ENGINE = 'sqlite3'
+DATABASE_NAME = 'database.sqlite3'
+DATABASE_USER = ''
+DATABASE_PASSWORD = ''
+DATABASE_HOST = ''
+DATABASE_PORT = ''
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'America/New_York'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'en-us'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# Absolute path to the directory that holds media.
+# Example: "/home/media/media.lawrence.com/"
+MEDIA_ROOT = ''
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash if there is a path component (optional in other cases).
+# Examples: "http://media.lawrence.com", "http://example.com/media/"
+MEDIA_URL = ''
+
+# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
+# trailing slash.
+# Examples: "http://foo.com/media/", "/media/".
+ADMIN_MEDIA_PREFIX = '/media/'
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = '_=9hq-$t_uv1ckf&s!y2$9g$1dm*6p1cl%*!^mg=7gr)!zj32d'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.load_template_source',
+ 'django.template.loaders.app_directories.load_template_source',
+# 'django.template.loaders.eggs.load_template_source',
+)
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+)
+
+ROOT_URLCONF = 'django_sample.urls'
+
+TEMPLATE_DIRS = (
+ # Put strings here, like "/home/html/django_templates"
+ # Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
+ os.path.join(os.path.dirname(__file__), 'templates')
+)
+
+INSTALLED_APPS = (
+ 'django.contrib.admin',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'django_sample.buzz'
+)
diff --git a/samples/oauth2/django_sample/static/go.png b/samples/oauth2/django_sample/static/go.png
new file mode 100644
index 0000000..e5aacda
--- /dev/null
+++ b/samples/oauth2/django_sample/static/go.png
Binary files differ
diff --git a/samples/oauth2/django_sample/templates/buzz/login.html b/samples/oauth2/django_sample/templates/buzz/login.html
new file mode 100644
index 0000000..567bf68
--- /dev/null
+++ b/samples/oauth2/django_sample/templates/buzz/login.html
@@ -0,0 +1,23 @@
+{% block content %}
+
+{% if form.errors %}
+<p>Your username and password didn't match. Please try again.</p>
+{% endif %}
+
+<form method="post" action="{% url django.contrib.auth.views.login %}">
+<table>
+<tr>
+ <td>{{ form.username.label_tag }}</td>
+ <td>{{ form.username }}</td>
+</tr>
+<tr>
+ <td>{{ form.password.label_tag }}</td>
+ <td>{{ form.password }}</td>
+</tr>
+</table>
+
+<input type="submit" value="login" />
+<input type="hidden" name="next" value="{{ next }}" />
+</form>
+
+{% endblock %}
diff --git a/samples/oauth2/django_sample/templates/buzz/welcome.html b/samples/oauth2/django_sample/templates/buzz/welcome.html
new file mode 100644
index 0000000..07e8027
--- /dev/null
+++ b/samples/oauth2/django_sample/templates/buzz/welcome.html
@@ -0,0 +1,33 @@
+
+<html>
+ <head>
+ <title>Buzz Stuff</title>
+ <style type=text/css>
+ td { vertical-align: top; padding: 0.5em }
+ img { border:0 }
+ </style>
+ </head>
+ <body>
+ <table border=0>
+ {% for item in activitylist.items %}
+ <tr valign=top>
+ <td>
+ {% if item.actor.thumbnailUrl %}
+ <a href="{{ item.actor.profileUrl }}">
+ <img src="{{ item.actor.thumbnailUrl }}">
+ </a>
+ {% endif %}
+ <br>
+ <a href="{{ item.actor.profileUrl }}">{{ item.actor.name }}</a></td>
+ <td>
+ {{ item.object.content|safe }}
+ </td>
+ <td>
+ <a href="{{ item.object.links.alternate.0.href }}"><img
+ src="/static/go.png"></a>
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+ </body>
+</html>
diff --git a/samples/oauth2/django_sample/urls.py b/samples/oauth2/django_sample/urls.py
new file mode 100644
index 0000000..aeba620
--- /dev/null
+++ b/samples/oauth2/django_sample/urls.py
@@ -0,0 +1,25 @@
+import os
+from django.conf.urls.defaults import *
+
+# Uncomment the next two lines to enable the admin:
+from django.contrib import admin
+admin.autodiscover()
+
+urlpatterns = patterns('',
+ # Example:
+ (r'^$', 'django_sample.buzz.views.index'),
+ (r'^auth_return', 'django_sample.buzz.views.auth_return'),
+
+ # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
+ # to INSTALLED_APPS to enable admin documentation:
+ # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
+
+ # Uncomment the next line to enable the admin:
+ (r'^admin/', include(admin.site.urls)),
+ (r'^accounts/login/$', 'django.contrib.auth.views.login',
+ {'template_name': 'buzz/login.html'}),
+
+ (r'^static/(?P<path>.*)$', 'django.views.static.serve',
+ {'document_root': os.path.join(os.path.dirname(__file__), 'static')
+}),
+)
diff --git a/samples/oauth2/latitude/latitude.py b/samples/oauth2/latitude/latitude.py
index fc312dd..56df083 100644
--- a/samples/oauth2/latitude/latitude.py
+++ b/samples/oauth2/latitude/latitude.py
@@ -17,16 +17,15 @@
from oauth2client.file import Storage
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.tools import run
+from apiclient.oauth import CredentialsInvalidError
# Uncomment to get detailed logging
#httplib2.debuglevel = 4
def main():
- storage = Storage('latitude.dat')
- credentials = storage.get()
-
- if not credentials:
+ credentials = Storage('latitude.dat').get()
+ if credentials is None or credentials.invalid:
flow = OAuth2WebServerFlow(
client_id='433807057907.apps.googleusercontent.com',
client_secret='jigtZpMApkRxncxikFpR+SFg',
@@ -50,7 +49,11 @@
"altitude": 35
}
}
- print p.currentLocation().insert(body=body).execute()
+ try:
+ print p.currentLocation().insert(body=body).execute()
+ except CredentialsInvalidError:
+ print 'Your credentials are no longer valid.'
+ print 'Please re-run this application to re-authorize.'
if __name__ == '__main__':
main()
diff --git a/samples/oauth2/moderator/moderator.py b/samples/oauth2/moderator/moderator.py
index 5a6e2b8..ae6c6d3 100644
--- a/samples/oauth2/moderator/moderator.py
+++ b/samples/oauth2/moderator/moderator.py
@@ -26,7 +26,7 @@
storage = Storage('moderator.dat')
credentials = storage.get()
- if not credentials:
+ if credentials is None or credentials.invalid == True:
flow = OAuth2WebServerFlow(
client_id='433807057907.apps.googleusercontent.com',
client_secret='jigtZpMApkRxncxikFpR+SFg',
diff --git a/samples/oauth2/urlshortener/main.py b/samples/oauth2/urlshortener/main.py
index f995f38..e129069 100644
--- a/samples/oauth2/urlshortener/main.py
+++ b/samples/oauth2/urlshortener/main.py
@@ -16,6 +16,7 @@
from apiclient.discovery import build
from oauth2client.file import Storage
from oauth2client.client import OAuth2WebServerFlow
+from oauth2client.client import AccessTokenCredentials
from oauth2client.tools import run
# Uncomment to get detailed logging
@@ -26,7 +27,7 @@
storage = Storage('urlshortener.dat')
credentials = storage.get()
- if not credentials:
+ if credentials is None or credentials.invalid == True:
flow = OAuth2WebServerFlow(
client_id='433807057907.apps.googleusercontent.com',
client_secret='jigtZpMApkRxncxikFpR+SFg',
@@ -55,5 +56,6 @@
resp = url.get(shortUrl=shortUrl).execute()
pprint.pprint(resp)
+
if __name__ == '__main__':
main()