Moving all OAuth code and samples to use Storage consistently
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/docs/oauth2client.client.html b/docs/oauth2client.client.html
index 4a857fd..36bc502 100644
--- a/docs/oauth2client.client.html
+++ b/docs/oauth2client.client.html
@@ -158,6 +158,11 @@
 &nbsp;&nbsp;&nbsp;&nbsp;has&nbsp;expired&nbsp;and&nbsp;been&nbsp;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&nbsp;if&nbsp;the&nbsp;credentials&nbsp;are&nbsp;invalid,&nbsp;such&nbsp;as&nbsp;being&nbsp;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&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
@@ -407,6 +412,11 @@
 &nbsp;&nbsp;&nbsp;&nbsp;has&nbsp;expired&nbsp;and&nbsp;been&nbsp;refreshed.</tt></dd></dl>
 
 <hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>invalid</strong></dt>
+<dd><tt>True&nbsp;if&nbsp;the&nbsp;credentials&nbsp;are&nbsp;invalid,&nbsp;such&nbsp;as&nbsp;being&nbsp;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&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
diff --git a/oauth2client/client.py b/oauth2client/client.py
index 6ef38a6..3527a48 100644
--- a/oauth2client/client.py
+++ b/oauth2client/client.py
@@ -139,7 +139,12 @@
 
     # True if the credentials have been revoked or expired and can't be
     # refreshed.
-    self.invalid = False
+    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.
@@ -202,7 +207,7 @@
       try:
         d = simplejson.loads(content)
         if 'error' in d:
-          self.invalid = True
+          self._invalid = True
           self.store(self)
       except:
         pass
@@ -272,7 +277,7 @@
   only the access_token is present it can not be refreshed and will in time
   expire.
 
-  OAuth2Credentials objects may be safely pickled and unpickled.
+  AccessTokenCredentials objects may be safely pickled and unpickled.
 
   Usage:
     credentials = AccessTokenCredentials('<an access token>',
diff --git a/samples/buzz/buzz.py b/samples/buzz/buzz.py
index a82cfc7..a4f6840 100644
--- a/samples/buzz/buzz.py
+++ b/samples/buzz/buzz.py
@@ -35,7 +35,7 @@
     flow = FlowThreeLegged(buzz_discovery,
                            consumer_key='anonymous',
                            consumer_secret='anonymous',
-                           user_agent='google-api-client-python-buzz-cmdline/1.0',
+                           user_agent='python-buzz-sample/1.0',
                            domain='anonymous',
                            scope='https://www.googleapis.com/auth/buzz',
                            xoauth_displayname='Google API Client Example App')
diff --git a/samples/latitude/latitude.py b/samples/latitude/latitude.py
index 029b74a..1dd1c39 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:
+    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/buzz/views.py b/samples/oauth2/django_sample/buzz/views.py
index b59a334..f6903b7 100644
--- a/samples/oauth2/django_sample/buzz/views.py
+++ b/samples/oauth2/django_sample/buzz/views.py
@@ -22,7 +22,7 @@
 def index(request):
   storage = Storage(CredentialsModel, 'id', request.user, 'credential')
   credential = storage.get()
-  if credential is None:
+  if credential is None or credential.invalid == True:
     flow = OAuth2WebServerFlow(
         client_id='837647042410.apps.googleusercontent.com',
         client_secret='+SWwMCL9d8gWtzPRa1lXw5R8',
@@ -47,6 +47,7 @@
                 'activitylist': activitylist,
                 })
 
+
 @login_required
 def auth_return(request):
     try:
diff --git a/samples/oauth2/latitude/latitude.py b/samples/oauth2/latitude/latitude.py
index fc312dd..e0458f4 100644
--- a/samples/oauth2/latitude/latitude.py
+++ b/samples/oauth2/latitude/latitude.py
@@ -26,7 +26,7 @@
   storage = Storage('latitude.dat')
   credentials = storage.get()
 
-  if not credentials:
+  if credentials is None or credentials.invalid:
     flow = OAuth2WebServerFlow(
         client_id='433807057907.apps.googleusercontent.com',
         client_secret='jigtZpMApkRxncxikFpR+SFg',
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 41677fb..e129069 100644
--- a/samples/oauth2/urlshortener/main.py
+++ b/samples/oauth2/urlshortener/main.py
@@ -37,26 +37,6 @@
 
     credentials = run(flow, storage)
 
-
-#  # Test AccessTokenCredentials
-#  at_credentials = AccessTokenCredentials(
-#      credentials.access_token, 'urlshortener-cmdline-sample/1.0')
-#  http = httplib2.Http()
-#  http = at_credentials.authorize(http)
-#
-#  # Build the url shortener service
-#  service = build("urlshortener", "v1", http=http,
-#            developerKey="AIzaSyDRRpR3GS1F1_jKNNM9HCNd2wJQyPG3oN0")
-#  url = service.url()
-#
-#  # Create a shortened URL by inserting the URL into the url collection.
-#  body = {"longUrl": "http://code.google.com/apis/urlshortener/" }
-#  resp = url.insert(body=body).execute()
-#  pprint.pprint(resp)
-#  http = httplib2.Http()
-#  http = credentials.authorize(http)
-#
-
   http = httplib2.Http()
   http = credentials.authorize(http)
 
@@ -77,7 +57,5 @@
   pprint.pprint(resp)
 
 
-
-
 if __name__ == '__main__':
   main()