From c47fab7a57f719fa855a1282dc6894a3575e02ea Mon Sep 17 00:00:00 2001 From: Joe Gregorio Date: Wed, 6 Jul 2011 08:29:20 -0400 Subject: [PATCH] Add oauth2client as a completely separate library. Reviewed in http://codereview.appspot.com/4630079/ --- MANIFEST_oauth2client.in | 7 ++++ Makefile | 29 ++++++++++++++ README_oauth2client | 31 +++++++++++++++ expand-symlinks.py | 44 +++++++++++++++++++++- samples/appengine/main.py | 29 +++++++------- samples/oauth2/dailymotion/apiclient | 1 - samples/oauth2/dailymotion/main.py | 43 ++++++++++----------- samples/oauth2/dailymotion/welcome.html | 6 +-- samples/oauth2/django_sample/buzz/views.py | 17 ++++----- setpath.sh | 2 +- setup.py | 2 +- 11 files changed, 155 insertions(+), 56 deletions(-) create mode 100644 MANIFEST_oauth2client.in create mode 100644 README_oauth2client delete mode 120000 samples/oauth2/dailymotion/apiclient diff --git a/MANIFEST_oauth2client.in b/MANIFEST_oauth2client.in new file mode 100644 index 0000000..1e189f3 --- /dev/null +++ b/MANIFEST_oauth2client.in @@ -0,0 +1,7 @@ +recursive-include httplib2 *.py +recursive-include simplejson *.py *.c +recursive-include samples *.py *.png *.html *.yaml *.json +include setup_utils.py +include gflags.py +include gflags_validators.py +include README diff --git a/Makefile b/Makefile index e88e4d1..6c08a9a 100644 --- a/Makefile +++ b/Makefile @@ -30,3 +30,32 @@ release: prerelease wget "http://support.googlecode.com/svn/trunk/scripts/googlecode_upload.py" -O googlecode_upload.py python googlecode_upload.py --summary="Version $(shell python setup.py --version)" --project=google-api-python-client snapshot/dist/*.tar.gz python googlecode_upload.py --summary="Version $(shell python setup.py --version)" --project=google-api-python-client snapshot/dist/*.zip + + +.PHONY: oauth2_prerelease +oauth2_prerelease: + -sudo rm -rf dist/ + -sudo rm -rf snapshot/ + mkdir snapshot + python expand-symlinks.py --source=oauth2client --dest=snapshot/oauth2client + python expand-symlinks.py --source=samples/oauth2/dailymotion --dest=snapshot/samples/dailymotion + python expand-symlinks.py --source=samples/appengine_with_decorator --dest=snapshot/samples/appengine_with_decorator + python expand-symlinks.py --source=samples/appengine_with_decorator2 --dest=snapshot/samples/appengine_with_decorator2 + python expand-symlinks.py --source=samples/appengine --dest=snapshot/samples/appengine + cp setup_oauth2client.py snapshot/setup.py + cp setup_utils.py snapshot/setup_utils.py + cp MANIFEST_oauth2client.in snapshot/MANIFEST.in + cp README_oauth2client snapshot/README + cd snapshot; python setup.py clean + cd snapshot; python setup.py sdist --formats=gztar,zip + +.PHONY: oauth2_release +oauth2_release: oauth2_prerelease + @echo "This target will upload a new release to PyPi and code.google.com hosting." + @echo "Are you sure you want to proceed? (yes/no)" + @read yn; [ "yes" == $$yn ] + @echo "Here we go..." + cd snapshot; python setup.py sdist --formats=gztar,zip register upload + wget "http://support.googlecode.com/svn/trunk/scripts/googlecode_upload.py" -O googlecode_upload.py + python googlecode_upload.py --summary="Version $(shell python setup.py --version)" --project=google-api-python-client snapshot/dist/*.tar.gz + python googlecode_upload.py --summary="Version $(shell python setup.py --version)" --project=google-api-python-client snapshot/dist/*.zip diff --git a/README_oauth2client b/README_oauth2client new file mode 100644 index 0000000..857613b --- /dev/null +++ b/README_oauth2client @@ -0,0 +1,31 @@ +This is a client library for accessing resources protected by OAuth 2.0. + + +Installation +============ + +To install, simply say + + $ python setup.py install + +If you want to do a "mock install" and simply extend your PYTHONPATH +for the current shell to include this folder and the packages in it, do + + $ source setpath.sh + +from the root of the project directory. + + + +Third Party Libraries +===================== + +These libraries will be installed when you install the client library: + +http://code.google.com/p/httplib2 +http://code.google.com/p/python-gflags + +Depending on your version of Python, these libraries may also be installed: + +http://pypi.python.org/pypi/simplejson/ + diff --git a/expand-symlinks.py b/expand-symlinks.py index 29535d6..73d2bdd 100644 --- a/expand-symlinks.py +++ b/expand-symlinks.py @@ -1,3 +1,45 @@ +#!/usr/bin/python2.4 +# -*- coding: utf-8 -*- +# +# 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. + +"""Copy files from source to dest expanding symlinks along the way. +""" + from distutils.dir_util import copy_tree -copy_tree('.', 'snapshot', verbose=True) +import gflags +import sys + + +FLAGS = gflags.FLAGS + +gflags.DEFINE_string('source', '.', 'Directory name to copy from.') +gflags.DEFINE_string('dest', 'snapshot', 'Directory name to copy to.') + + +def main(argv): + # Let the gflags module process the command-line arguments + try: + argv = FLAGS(argv) + except gflags.FlagsError, e: + print '%s\\nUsage: %s ARGS\\n%s' % (e, argv[0], FLAGS) + sys.exit(1) + + copy_tree(FLAGS.source, FLAGS.dest, verbose=True) + + +if __name__ == '__main__': + main(sys.argv) diff --git a/samples/appengine/main.py b/samples/appengine/main.py index 087a136..184f5fa 100755 --- a/samples/appengine/main.py +++ b/samples/appengine/main.py @@ -36,6 +36,16 @@ from google.appengine.ext.webapp import util from google.appengine.ext.webapp.util import login_required +FLOW = OAuth2WebServerFlow( + # Visit https://code.google.com/apis/console to + # generate your client_id, client_secret and to + # register your redirect_uri. + client_id='', + client_secret='', + scope='https://www.googleapis.com/auth/buzz', + user_agent='buzz-cmdline-sample/1.0') + + class Credentials(db.Model): credentials = CredentialsProperty() @@ -49,20 +59,9 @@ class MainHandler(webapp.RequestHandler): Credentials, user.user_id(), 'credentials').get() 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 - # register your redirect_uri. - client_id='', - client_secret='', - scope='https://www.googleapis.com/auth/buzz', - user_agent='buzz-cmdline-sample/1.0', - domain='anonymous', - xoauth_displayname='Google App Engine Example App') - - callback = self.request.relative_url('/auth_return') - authorize_url = flow.step1_get_authorize_url(callback) - memcache.set(user.user_id(), pickle.dumps(flow)) + callback = self.request.relative_url('/oauth2callback') + authorize_url = FLOW.step1_get_authorize_url(callback) + memcache.set(user.user_id(), pickle.dumps(FLOW)) self.redirect(authorize_url) else: http = httplib2.Http() @@ -99,7 +98,7 @@ def main(): application = webapp.WSGIApplication( [ ('/', MainHandler), - ('/auth_return', OAuthHandler) + ('/oauth2callback', OAuthHandler) ], debug=True) util.run_wsgi_app(application) diff --git a/samples/oauth2/dailymotion/apiclient b/samples/oauth2/dailymotion/apiclient deleted file mode 120000 index f53af07..0000000 --- a/samples/oauth2/dailymotion/apiclient +++ /dev/null @@ -1 +0,0 @@ -../../../apiclient/ \ No newline at end of file diff --git a/samples/oauth2/dailymotion/main.py b/samples/oauth2/dailymotion/main.py index c904e3b..1b75239 100644 --- a/samples/oauth2/dailymotion/main.py +++ b/samples/oauth2/dailymotion/main.py @@ -23,7 +23,6 @@ import logging import os import pickle -from apiclient.discovery import build from oauth2client.appengine import CredentialsProperty from oauth2client.appengine import StorageByKeyName from oauth2client.client import OAuth2WebServerFlow @@ -36,6 +35,16 @@ from google.appengine.ext.webapp import util from google.appengine.ext.webapp.util import login_required +FLOW = OAuth2WebServerFlow( + client_id='2ad565600216d25d9cde', + client_secret='03b56df2949a520be6049ff98b89813f17b467dc', + scope='read', + user_agent='oauth2client-sample/1.0', + auth_uri='https://api.dailymotion.com/oauth/authorize', + token_uri='https://api.dailymotion.com/oauth/token' + ) + + class Credentials(db.Model): credentials = CredentialsProperty() @@ -49,37 +58,23 @@ class MainHandler(webapp.RequestHandler): Credentials, user.user_id(), 'credentials').get() if credentials is None or credentials.invalid == True: - flow = OAuth2WebServerFlow( - client_id='2ad565600216d25d9cde', - client_secret='03b56df2949a520be6049ff98b89813f17b467dc', - scope='read', - user_agent='oauth2client-sample/1.0', - auth_uri='https://api.dailymotion.com/oauth/authorize', - token_uri='https://api.dailymotion.com/oauth/token' - ) - callback = self.request.relative_url('/auth_return') - authorize_url = flow.step1_get_authorize_url(callback) - memcache.set(user.user_id(), pickle.dumps(flow)) + authorize_url = FLOW.step1_get_authorize_url(callback) + memcache.set(user.user_id(), pickle.dumps(FLOW)) self.redirect(authorize_url) else: http = httplib2.Http() - - resp, content1 = http.request('https://api.dailymotion.com/me?access_token=%s' % - credentials.access_token) - http = credentials.authorize(http) - resp, content2 = http.request('https://api.dailymotion.com/me') + + resp, content = http.request('https://api.dailymotion.com/me') path = os.path.join(os.path.dirname(__file__), 'welcome.html') logout = users.create_logout_url('/') - self.response.out.write( - template.render( - path, { - 'content1': content1, - 'content2': content2, - 'logout': logout - })) + variables = { + 'content': content, + 'logout': logout + } + self.response.out.write(template.render(path, variables)) class OAuthHandler(webapp.RequestHandler): diff --git a/samples/oauth2/dailymotion/welcome.html b/samples/oauth2/dailymotion/welcome.html index 06fcb95..f86902f 100644 --- a/samples/oauth2/dailymotion/welcome.html +++ b/samples/oauth2/dailymotion/welcome.html @@ -8,9 +8,7 @@

Logout

-

First request with access_token in query parameter:

-
{{ content1 }} 
-

Second request with access_token in header:

-
{{ content2 }} 
+

Response body:

+
{{ content }} 
diff --git a/samples/oauth2/django_sample/buzz/views.py b/samples/oauth2/django_sample/buzz/views.py index c942aaf..9a051ea 100644 --- a/samples/oauth2/django_sample/buzz/views.py +++ b/samples/oauth2/django_sample/buzz/views.py @@ -16,22 +16,21 @@ from django.http import HttpResponseRedirect from django.shortcuts import render_to_response STEP2_URI = 'http://localhost:8000/auth_return' - +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', + ) @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) + authorize_url = FLOW.step1_get_authorize_url(STEP2_URI) + f = FlowModel(id=request.user, flow=FLOW) f.save() return HttpResponseRedirect(authorize_url) else: diff --git a/setpath.sh b/setpath.sh index 45826d6..8fb8f1b 100644 --- a/setpath.sh +++ b/setpath.sh @@ -1 +1 @@ -export PYTHONPATH=`pwd`:$PYTHONPATH +export PYTHONPATH=`pwd`:${PYTHONPATH} diff --git a/setup.py b/setup.py index 58827dc..db17fcb 100644 --- a/setup.py +++ b/setup.py @@ -79,7 +79,7 @@ setup(name="google-api-python-client", scripts=['bin/enable-app-engine-project'], license="Apache 2.0", keywords="google api client", - classifiers=['Development Status :: 3 - Alpha', + classifiers=['Development Status :: 4 - Beta', 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX',