Cleaned up oauth code based on feedback. Created FlowThreeLegged and OAuthCredentials classes.
diff --git a/samples/appengine/apiclient b/samples/appengine/apiclient
new file mode 120000
index 0000000..22e4c9c
--- /dev/null
+++ b/samples/appengine/apiclient
@@ -0,0 +1 @@
+../../apiclient/
\ No newline at end of file
diff --git a/samples/appengine/app.yaml b/samples/appengine/app.yaml
new file mode 100644
index 0000000..66a711a
--- /dev/null
+++ b/samples/appengine/app.yaml
@@ -0,0 +1,8 @@
+application: m-buzz
+version: 1
+runtime: python
+api_version: 1
+
+handlers:
+- url: .*
+  script: main.py
diff --git a/samples/appengine/httplib2 b/samples/appengine/httplib2
new file mode 120000
index 0000000..488ae9f
--- /dev/null
+++ b/samples/appengine/httplib2
@@ -0,0 +1 @@
+../../httplib2/
\ No newline at end of file
diff --git a/samples/appengine/index.yaml b/samples/appengine/index.yaml
new file mode 100644
index 0000000..a3b9e05
--- /dev/null
+++ b/samples/appengine/index.yaml
@@ -0,0 +1,11 @@
+indexes:
+
+# AUTOGENERATED
+
+# This index.yaml is automatically updated whenever the dev_appserver
+# detects that a new type of query is run.  If you want to manage the
+# index.yaml file manually, remove the above marker line (the line
+# saying "# AUTOGENERATED").  If you want to manage some indexes
+# manually, move them above the marker line.  The index.yaml file is
+# automatically uploaded to the admin console when you next deploy
+# your application using appcfg.py.
diff --git a/samples/appengine/main.py b/samples/appengine/main.py
new file mode 100755
index 0000000..6832dda
--- /dev/null
+++ b/samples/appengine/main.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 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.
+#
+
+__author__ = 'jcgregorio@google.com (Joe Gregorio)'
+
+
+import httplib2
+import os
+
+from apiclient.discovery import build
+from apiclient.ext.appengine import FlowThreeLeggedProperty
+from apiclient.ext.appengine import OAuthCredentialsProperty
+from apiclient.oauth import FlowThreeLegged
+from apiclient.oauth import buzz_discovery
+from google.appengine.api import users
+from google.appengine.ext import db
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import template
+from google.appengine.ext.webapp import util
+from google.appengine.ext.webapp.util import login_required
+
+STEP2_URI = 'http://m-buzz.appspot.com/auth_return'
+
+
+class Flow(db.Model):
+  # FlowThreeLegged could also be stored in memcache.
+  flow = FlowThreeLeggedProperty()
+
+
+class Credentials(db.Model):
+  credentials = OAuthCredentialsProperty()
+
+
+class MainHandler(webapp.RequestHandler):
+
+  @login_required
+  def get(self):
+    user = users.get_current_user()
+    c = Credentials.get_by_key_name(user.user_id())
+
+    if c:
+      http = httplib2.Http()
+      http = c.credentials.authorize(http)
+      p = build("buzz", "v1", http=http)
+      activities = p.activities()
+      activitylist = activities.list(scope='@self', userId='@me')
+      path = os.path.join(os.path.dirname(__file__), 'welcome.html')
+      self.response.out.write(template.render(path, activitylist))
+    else:
+      flow = FlowThreeLegged(buzz_discovery,
+                     consumer_key='anonymous',
+                     consumer_secret='anonymous',
+                     user_agent='google-api-client-python-buzz-webapp/1.0',
+                     domain='anonymous',
+                     scope='https://www.googleapis.com/auth/buzz',
+                     xoauth_displayname='Example Web App')
+
+      authorize_url = flow.step1_get_authorize_url(STEP2_URI)
+      f = Flow(key_name=user.user_id(), flow=flow)
+      f.put()
+      self.redirect(authorize_url)
+
+
+class OAuthHandler(webapp.RequestHandler):
+
+  @login_required
+  def get(self):
+    user = users.get_current_user()
+    f = Flow.get_by_key_name(user.user_id())
+    if f:
+      credentials = f.flow.step2_exchange(self.request.params)
+      c = Credentials(key_name=user.user_id(), credentials=credentials)
+      c.put()
+      f.delete()
+      self.redirect("/")
+    else:
+      pass
+
+
+def main():
+  application = webapp.WSGIApplication(
+      [
+      ('/', MainHandler),
+      ('/auth_return', OAuthHandler)
+      ],
+      debug=True)
+  util.run_wsgi_app(application)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/samples/appengine/oauth2 b/samples/appengine/oauth2
new file mode 120000
index 0000000..af104cc
--- /dev/null
+++ b/samples/appengine/oauth2
@@ -0,0 +1 @@
+../../oauth2
\ No newline at end of file
diff --git a/samples/appengine/simplejson b/samples/appengine/simplejson
new file mode 120000
index 0000000..148c7cf
--- /dev/null
+++ b/samples/appengine/simplejson
@@ -0,0 +1 @@
+../../simplejson/
\ No newline at end of file
diff --git a/samples/appengine/uritemplate b/samples/appengine/uritemplate
new file mode 120000
index 0000000..ce92dcb
--- /dev/null
+++ b/samples/appengine/uritemplate
@@ -0,0 +1 @@
+../../uritemplate/
\ No newline at end of file
diff --git a/samples/appengine/welcome.html b/samples/appengine/welcome.html
new file mode 100644
index 0000000..421711b
--- /dev/null
+++ b/samples/appengine/welcome.html
@@ -0,0 +1,13 @@
+<html>
+  <head>
+    <title>Buzz Stuff</title>
+  </head>
+  <body>
+
+    <ul>
+      {% for item in items %}
+      <li>{{ item.object.content }}</li>
+      {% endfor %}
+    </ul>
+  </body>
+</html>
diff --git a/samples/cmdline/buzz.py b/samples/cmdline/buzz.py
index e6b2ff4..b71f400 100644
--- a/samples/cmdline/buzz.py
+++ b/samples/cmdline/buzz.py
@@ -3,9 +3,10 @@
 #
 # Copyright 2010 Google Inc. All Rights Reserved.
 
-"""One-line documentation for discovery module.
+"""Simple command-line example for Buzz.
 
-A detailed description of discovery.
+Command-line application that retrieves the users
+latest content and then adds a new entry.
 """
 
 __author__ = 'jcgregorio@google.com (Joe Gregorio)'
@@ -14,72 +15,17 @@
 from apiclient.discovery import build
 
 import httplib2
-import oauth2 as oauth
-import re
-import simplejson
-
-
-def oauth_wrap(consumer, token, http):
-    """
-    Args:
-       http - An instance of httplib2.Http
-           or something that acts like it.
-
-    Returns:
-       A modified instance of http that was passed in.
-
-    Example:
-
-      h = httplib2.Http()
-      h = oauth_wrap(h)
-
-    Grumble. You can't create a new OAuth
-    subclass of httplib2.Authenication because
-    it never gets passed the absolute URI, which is
-    needed for signing. So instead we have to overload
-    'request' with a closure that adds in the
-    Authorization header and then calls the original version
-    of 'request()'.
-    """
-    request_orig = http.request
-    signer = oauth.SignatureMethod_HMAC_SHA1()
-
-    def new_request(uri, method="GET", body=None, headers=None,
-        redirections=httplib2.DEFAULT_MAX_REDIRECTS, connection_type=None):
-      """Modify the request headers to add the appropriate
-      Authorization header."""
-      req = oauth.Request.from_consumer_and_token(
-          consumer, token, http_method=method, http_url=uri)
-      req.sign_request(signer, consumer, token)
-      if headers == None:
-        headers = {}
-      headers.update(req.to_header())
-      headers['user-agent'] = 'jcgregorio-test-client'
-      return request_orig(uri, method, body, headers,
-          redirections, connection_type)
-
-    http.request = new_request
-    return http
-
-
-def get_wrapped_http():
-  f = open("oauth_token.dat", "r")
-  oauth_params = simplejson.loads(f.read())
-
-  consumer = oauth.Consumer(
-      oauth_params['consumer_key'], oauth_params['consumer_secret'])
-  token = oauth.Token(
-      oauth_params['oauth_token'], oauth_params['oauth_token_secret'])
-
-  # Create a simple monkeypatch for httplib2.Http.request
-  # just adds in the oauth authorization header and then calls
-  # the original request().
-  http = httplib2.Http()
-  return oauth_wrap(consumer, token, http)
+import pickle
 
 
 def main():
-  http = get_wrapped_http()
+  f = open("oauth_token.dat", "r")
+  credentials = pickle.loads(f.read())
+  f.close()
+
+  http = httplib2.Http()
+  http = credentials.authorize(http)
+
   p = build("buzz", "v1", http=http)
   activities = p.activities()
   activitylist = activities.list(scope='@self', userId='@me')
diff --git a/samples/cmdline/three_legged_dance.py b/samples/cmdline/three_legged_dance.py
index 31a22df..f0a4a20 100644
--- a/samples/cmdline/three_legged_dance.py
+++ b/samples/cmdline/three_legged_dance.py
@@ -1,17 +1,45 @@
-from apiclient.oauth import buzz_discovery, Flow3LO
+# 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.
 
-import simplejson
+"""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.oauth import buzz_discovery
+from apiclient.oauth import FlowThreeLegged
+
+import pickle
 
 user_agent = 'google-api-client-python-buzz-cmdline/1.0',
 consumer_key = 'anonymous'
 consumer_secret = 'anonymous'
 
-flow = Flow3LO(buzz_discovery, consumer_key, consumer_secret, user_agent,
-               domain='anonymous',
-               scope='https://www.googleapis.com/auth/buzz',
-               xoauth_displayname='Google API Client for Python Example App')
+flow = FlowThreeLegged(buzz_discovery,
+                       consumer_key='anonymous',
+                       consumer_secret='anonymous',
+                       user_agent='google-api-client-python-buzz-cmdline/1.0',
+                       domain='anonymous',
+                       scope='https://www.googleapis.com/auth/buzz',
+                       xoauth_displayname='Google API Client Example App')
 
-authorize_url = flow.step1()
+authorize_url = flow.step1_get_authorize_url()
 
 print 'Go to the following link in your browser:'
 print authorize_url
@@ -20,17 +48,10 @@
 accepted = 'n'
 while accepted.lower() == 'n':
     accepted = raw_input('Have you authorized me? (y/n) ')
-pin = raw_input('What is the PIN? ').strip()
+verification = raw_input('What is the verification code? ').strip()
 
-access_token = flow.step2_pin(pin)
-
-d = dict(
-  consumer_key='anonymous',
-  consumer_secret='anonymous'
-    )
-
-d.update(access_token)
+credentials = flow.step2_exchange(verification)
 
 f = open('oauth_token.dat', 'w')
-f.write(simplejson.dumps(d))
+f.write(pickle.dumps(credentials))
 f.close()