Starting to cleanup, organize files, and make it look like a real project.
diff --git a/samples/cmdline/buzz.py b/samples/cmdline/buzz.py
new file mode 100644
index 0000000..9a0a909
--- /dev/null
+++ b/samples/cmdline/buzz.py
@@ -0,0 +1,115 @@
+#!/usr/bin/python2.4
+# -*- coding: utf-8 -*-
+#
+# Copyright 2010 Google Inc. All Rights Reserved.
+
+"""One-line documentation for discovery module.
+
+A detailed description of discovery.
+"""
+
+__author__ = 'jcgregorio@google.com (Joe Gregorio)'
+
+# TODO
+# - Add normalize_ that converts max-results into MaxResults
+#
+# - Each 'resource' should be its own object accessible
+# from the service object returned from discovery.
+#
+# - Methods can either execute immediately or return
+# RestRequest objects which can be batched.
+#
+# - 'Body' parameter for non-GET requests
+#
+# - 2.x and 3.x compatible
+
+# JS also has the idea of a TransportRequest and a Transport.
+# The Transport has a doRequest() method that takes a request
+# and a callback function.
+#
+
+
+# Discovery doc notes
+# - Which parameters are optional vs mandatory
+# - Is pattern a regex?
+# - Inconsistent naming max-results vs userId
+
+
+from apiclient.discovery import build
+
+import httplib2
+import simplejson
+import re
+
+import oauth2 as oauth
+
+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)
+
+
+def main():
+ http = get_wrapped_http()
+ p = build("buzz", "v1", http = http)
+ activities = p.activities()
+ activitylist = activities.list(scope='@self', userId='@me')
+ print activitylist['items'][0]['title']
+ activities.insert(userId='@me', body={
+ 'title': 'Testing insert',
+ 'object': {
+ 'content': u'Just a short note to show that insert is working. ☄',
+ 'type': 'note'}
+ }
+ )
+
+if __name__ == '__main__':
+ main()
diff --git a/samples/cmdline/oauth_token.dat b/samples/cmdline/oauth_token.dat
new file mode 100644
index 0000000..147863c
--- /dev/null
+++ b/samples/cmdline/oauth_token.dat
@@ -0,0 +1 @@
+{"consumer_secret": "anonymous", "oauth_token_secret": "R/eOG4BzDwvlXH+NwBuUzxFz", "consumer_key": "anonymous", "oauth_token": "1/41pApdDCG0cySvfZVhA5pT4I1F7cKRKR0P6Mb1Ik08o"}
\ No newline at end of file
diff --git a/samples/cmdline/three_legged_dance.py b/samples/cmdline/three_legged_dance.py
new file mode 100644
index 0000000..7219216
--- /dev/null
+++ b/samples/cmdline/three_legged_dance.py
@@ -0,0 +1,97 @@
+import urlparse
+import oauth2 as oauth
+import httplib2
+import urllib
+import simplejson
+
+try:
+ from urlparse import parse_qs, parse_qsl
+except ImportError:
+ from cgi import parse_qs, parse_qsl
+
+httplib2.debuglevel=4
+headers = {"user-agent": "jcgregorio-buzz-client",
+ 'content-type': 'application/x-www-form-urlencoded'
+ }
+
+consumer_key = 'anonymous'
+consumer_secret = 'anonymous'
+
+request_token_url = 'https://www.google.com/accounts/OAuthGetRequestToken?domain=anonymous&scope=https://www.googleapis.com/auth/buzz'
+access_token_url = 'https://www.google.com/accounts/OAuthGetAccessToken?domain=anonymous&scope=https://www.googleapis.com/auth/buzz'
+authorize_url = 'https://www.google.com/buzz/api/auth/OAuthAuthorizeToken?domain=anonymous&scope=https://www.googleapis.com/auth/buzz'
+
+consumer = oauth.Consumer(consumer_key, consumer_secret)
+client = oauth.Client(consumer)
+
+# Step 1: Get a request token. This is a temporary token that is used for
+# having the user authorize an access token and to sign the request to obtain
+# said access token.
+
+resp, content = client.request(request_token_url, "POST", headers=headers, body="oauth_callback=oob")
+if resp['status'] != '200':
+ print content
+ raise Exception("Invalid response %s." % resp['status'])
+
+request_token = dict(parse_qsl(content))
+
+print "Request Token:"
+print " - oauth_token = %s" % request_token['oauth_token']
+print " - oauth_token_secret = %s" % request_token['oauth_token_secret']
+print
+
+# Step 2: Redirect to the provider. Since this is a CLI script we do not
+# redirect. In a web application you would redirect the user to the URL
+# below.
+
+base_url = urlparse.urlparse(authorize_url)
+query = parse_qs(base_url.query)
+query['oauth_token'] = request_token['oauth_token']
+
+print urllib.urlencode(query, True)
+
+url = (base_url.scheme, base_url.netloc, base_url.path, base_url.params,
+ urllib.urlencode(query, True), base_url.fragment)
+authorize_url = urlparse.urlunparse(url)
+
+print "Go to the following link in your browser:"
+print authorize_url
+print
+
+# After the user has granted access to you, the consumer, the provider will
+# redirect you to whatever URL you have told them to redirect to. You can
+# usually define this in the oauth_callback argument as well.
+accepted = 'n'
+while accepted.lower() == 'n':
+ accepted = raw_input('Have you authorized me? (y/n) ')
+oauth_verifier = raw_input('What is the PIN? ')
+
+# Step 3: Once the consumer has redirected the user back to the oauth_callback
+# URL you can request the access token the user has approved. You use the
+# request token to sign this request. After this is done you throw away the
+# request token and use the access token returned. You should store this
+# access token somewhere safe, like a database, for future use.
+token = oauth.Token(request_token['oauth_token'],
+ request_token['oauth_token_secret'])
+token.set_verifier(oauth_verifier)
+client = oauth.Client(consumer, token)
+
+resp, content = client.request(access_token_url, "POST", headers=headers)
+access_token = dict(parse_qsl(content))
+
+print "Access Token:"
+print " - oauth_token = %s" % access_token['oauth_token']
+print " - oauth_token_secret = %s" % access_token['oauth_token_secret']
+print
+print "You may now access protected resources using the access tokens above."
+print
+
+d = dict(
+ consumer_key = 'anonymous',
+ consumer_secret = 'anonymous'
+ )
+d.update(access_token)
+
+f = open("oauth_token.dat", "w")
+f.write(simplejson.dumps(d))
+f.close()