Move to using setuptools exclusively.
Take the opportunity to clean up contrib/ as all that functionality has been subsumed in the oauth2decorator. Reviwed in http://codereview.appspot.com/5271053/
This commit is contained in:
@@ -30,6 +30,7 @@ import gflags
|
||||
import logging
|
||||
import sys
|
||||
import os
|
||||
import pkg_resources
|
||||
|
||||
from distutils.dir_util import copy_tree
|
||||
from distutils.file_util import copy_file
|
||||
@@ -72,13 +73,13 @@ def find_source(module):
|
||||
basename = os.path.basename(m.__file__)
|
||||
if basename.startswith('__init__.'):
|
||||
isdir = True
|
||||
location = os.path.dirname(m.__file__)
|
||||
location = os.path.dirname(
|
||||
pkg_resources.resource_filename(module, '__init__.py'))
|
||||
else:
|
||||
if os.path.isfile(m.__file__):
|
||||
location = m.__file__.rsplit('.', 1)[0] + '.py'
|
||||
else:
|
||||
# The file is an egg, extract to a temporary location
|
||||
import pkg_resources
|
||||
location = pkg_resources.resource_filename(module, module + '.py')
|
||||
|
||||
return (isdir, location)
|
||||
@@ -103,8 +104,8 @@ def main(argv):
|
||||
# Check if the supplied directory is an App Engine project by looking
|
||||
# for an app.yaml
|
||||
if not os.path.isfile(os.path.join(dir, 'app.yaml')):
|
||||
sys.exit('The given directory is not a Google App Engine project: %s' % dir)
|
||||
|
||||
sys.exit('The given directory is not a Google App Engine project: %s' %
|
||||
dir)
|
||||
|
||||
# Build up the set of file or directory copying actions we need to do
|
||||
action = [] # (src, dst, isdir)
|
||||
|
||||
@@ -1,173 +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.
|
||||
|
||||
from google.appengine.api import users
|
||||
from google.appengine.ext import db
|
||||
|
||||
import apiclient.ext.appengine
|
||||
import logging
|
||||
import simple_wrapper
|
||||
|
||||
|
||||
class Flow(db.Model):
|
||||
flow = apiclient.ext.appengine.FlowThreeLeggedProperty()
|
||||
|
||||
|
||||
class Credentials(db.Model):
|
||||
credentials = apiclient.ext.appengine.OAuthCredentialsProperty()
|
||||
|
||||
|
||||
class oauth_required(object):
|
||||
def __init__(self, *decorator_args, **decorator_kwargs):
|
||||
"""A decorator to require that a user has gone through the OAuth dance before accessing a handler.
|
||||
|
||||
To use it, decorate your get() method like this:
|
||||
@oauth_required
|
||||
def get(self):
|
||||
buzz_wrapper = oauth_handlers.build_buzz_wrapper_for_current_user()
|
||||
user_profile_data = buzz_wrapper.get_profile()
|
||||
self.response.out.write('Hello, ' + user_profile_data.displayName)
|
||||
|
||||
We will redirect the user to the OAuth endpoint and afterwards the OAuth
|
||||
will send the user back to the DanceFinishingHandler that you have configured.
|
||||
|
||||
This should only used for GET requests since any payload in a POST request
|
||||
will be lost. Any parameters in the original URL will be preserved.
|
||||
"""
|
||||
self.decorator_args = decorator_args
|
||||
self.decorator_kwargs = decorator_kwargs
|
||||
|
||||
def __load_settings_from_file__(self):
|
||||
# Load settings from settings.py module if it's available
|
||||
# Only return the keys that the user has explicitly set
|
||||
try:
|
||||
import settings
|
||||
|
||||
# This uses getattr so that the user can set just the parameters they care about
|
||||
flow_settings = {
|
||||
'consumer_key' : getattr(settings, 'CONSUMER_KEY', None),
|
||||
'consumer_secret' : getattr(settings, 'CONSUMER_SECRET', None),
|
||||
'user_agent' : getattr(settings, 'USER_AGENT', None),
|
||||
'domain' : getattr(settings, 'DOMAIN', None),
|
||||
'scope' : getattr(settings, 'SCOPE', None),
|
||||
'xoauth_display_name' : getattr(settings, 'XOAUTH_DISPLAY_NAME', None)
|
||||
}
|
||||
|
||||
# Strip out all the keys that weren't specified in the settings.py
|
||||
# This is needed to ensure that those keys don't override what's
|
||||
# specified in the decorator invocation
|
||||
cleaned_flow_settings = {}
|
||||
for key,value in flow_settings.items():
|
||||
if value is not None:
|
||||
cleaned_flow_settings[key] = value
|
||||
|
||||
return cleaned_flow_settings
|
||||
except ImportError:
|
||||
return {}
|
||||
|
||||
def __load_settings__(self):
|
||||
# Set up the default arguments and override them with whatever values have been given to the decorator
|
||||
flow_settings = {
|
||||
'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_display_name' : 'Default Display Name For OAuth Application'
|
||||
}
|
||||
logging.info('OAuth settings: %s ' % flow_settings)
|
||||
|
||||
# Override the defaults with whatever the user may have put into settings.py
|
||||
settings_kwargs = self.__load_settings_from_file__()
|
||||
flow_settings.update(settings_kwargs)
|
||||
logging.info('OAuth settings: %s ' % flow_settings)
|
||||
|
||||
# Override the defaults with whatever the user have specified in the decorator's invocation
|
||||
flow_settings.update(self.decorator_kwargs)
|
||||
logging.info('OAuth settings: %s ' % flow_settings)
|
||||
return flow_settings
|
||||
|
||||
def __call__(self, handler_method):
|
||||
def check_oauth_credentials_wrapper(*args, **kwargs):
|
||||
handler_instance = args[0]
|
||||
# TODO(ade) Add support for POST requests
|
||||
if handler_instance.request.method != 'GET':
|
||||
raise webapp.Error('The check_oauth decorator can only be used for GET '
|
||||
'requests')
|
||||
|
||||
# Is this a request from the OAuth system after finishing the OAuth dance?
|
||||
if handler_instance.request.get('oauth_verifier'):
|
||||
user = users.get_current_user()
|
||||
logging.debug('Finished OAuth dance for: %s' % user.email())
|
||||
|
||||
f = Flow.get_by_key_name(user.user_id())
|
||||
if f:
|
||||
credentials = f.flow.step2_exchange(handler_instance.request.params)
|
||||
c = Credentials(key_name=user.user_id(), credentials=credentials)
|
||||
c.put()
|
||||
|
||||
# We delete the flow so that a malicious actor can't pretend to be the OAuth service
|
||||
# and replace a valid token with an invalid token
|
||||
f.delete()
|
||||
|
||||
handler_method(*args)
|
||||
return
|
||||
|
||||
# Find out who the user is. If we don't know who you are then we can't
|
||||
# look up your OAuth credentials thus we must ensure the user is logged in.
|
||||
user = users.get_current_user()
|
||||
if not user:
|
||||
handler_instance.redirect(users.create_login_url(handler_instance.request.uri))
|
||||
return
|
||||
|
||||
# Now that we know who the user is look up their OAuth credentials
|
||||
# if we don't find the credentials then send them through the OAuth dance
|
||||
if not Credentials.get_by_key_name(user.user_id()):
|
||||
flow_settings = self.__load_settings__()
|
||||
|
||||
p = apiclient.discovery.build("buzz", "v1")
|
||||
flow = apiclient.oauth.FlowThreeLegged(p.auth_discovery(),
|
||||
consumer_key=flow_settings['consumer_key'],
|
||||
consumer_secret=flow_settings['consumer_secret'],
|
||||
user_agent=flow_settings['user_agent'],
|
||||
domain=flow_settings['domain'],
|
||||
scope=flow_settings['scope'],
|
||||
xoauth_displayname=flow_settings['xoauth_display_name'])
|
||||
|
||||
# The OAuth system needs to send the user right back here so that they
|
||||
# get to the page they originally intended to visit.
|
||||
oauth_return_url = handler_instance.request.uri
|
||||
authorize_url = flow.step1_get_authorize_url(oauth_return_url)
|
||||
|
||||
f = Flow(key_name=user.user_id(), flow=flow)
|
||||
f.put()
|
||||
|
||||
handler_instance.redirect(authorize_url)
|
||||
return
|
||||
|
||||
# If the user already has a token then call the wrapped handler
|
||||
handler_method(*args)
|
||||
return check_oauth_credentials_wrapper
|
||||
|
||||
def build_buzz_wrapper_for_current_user(api_key=None):
|
||||
user = users.get_current_user()
|
||||
credentials = Credentials.get_by_key_name(user.user_id()).credentials
|
||||
if not api_key:
|
||||
try:
|
||||
import settings
|
||||
api_key = getattr(settings, 'API_KEY', None)
|
||||
except ImportError:
|
||||
return {}
|
||||
return simple_wrapper.SimpleWrapper(api_key=api_key,
|
||||
credentials=credentials)
|
||||
@@ -1,82 +0,0 @@
|
||||
#!/usr/bin/python2.4
|
||||
#
|
||||
# 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.
|
||||
|
||||
__author__ = 'ade@google.com (Ade Oshineye)'
|
||||
|
||||
import apiclient.discovery
|
||||
import httplib2
|
||||
import logging
|
||||
|
||||
class SimpleWrapper(object):
|
||||
"Simple client that exposes the bare minimum set of common Buzz operations"
|
||||
|
||||
def __init__(self, api_key=None, credentials=None):
|
||||
self.http = httplib2.Http()
|
||||
if credentials:
|
||||
logging.debug('Using api_client with credentials')
|
||||
self.http = credentials.authorize(self.http)
|
||||
self.api_client = apiclient.discovery.build('buzz', 'v1', http=self.http, developerKey=api_key)
|
||||
else:
|
||||
logging.debug('Using api_client that doesn\'t have credentials')
|
||||
self.api_client = apiclient.discovery.build('buzz', 'v1', http=self.http, developerKey=api_key)
|
||||
|
||||
def search(self, query, user_token=None, max_results=10):
|
||||
if query is None or query.strip() is '':
|
||||
return None
|
||||
|
||||
json = self.api_client.activities().search(q=query, max_results=max_results).execute()
|
||||
if json.has_key('items'):
|
||||
return json['items']
|
||||
return []
|
||||
|
||||
def post(self, message_body, user_id='@me'):
|
||||
if message_body is None or message_body.strip() is '':
|
||||
return None
|
||||
|
||||
activities = self.api_client.activities()
|
||||
logging.info('Retrieved activities for: %s' % user_id)
|
||||
activity = activities.insert(userId=user_id, body={
|
||||
'data' : {
|
||||
'title': message_body,
|
||||
'object': {
|
||||
'content': message_body,
|
||||
'type': 'note'}
|
||||
}
|
||||
}
|
||||
).execute()
|
||||
url = activity['links']['alternate'][0]['href']
|
||||
logging.info('Just created: %s' % url)
|
||||
return url
|
||||
|
||||
def get_profile(self, user_id='@me'):
|
||||
user_profile_data = self.api_client.people().get(userId=user_id).execute()
|
||||
return user_profile_data
|
||||
|
||||
def get_follower_count(self, user_id='@me'):
|
||||
return self.__get_group_count(user_id, '@followers')
|
||||
|
||||
def get_following_count(self, user_id='@me'):
|
||||
return self.__get_group_count(user_id, '@following')
|
||||
|
||||
def __get_group_count(self, user_id, group_id):
|
||||
# Fetching 0 results is a performance optimisation that minimises the
|
||||
# amount of data that's getting retrieved from the server
|
||||
cmd = self.api_client.people().list(userId=user_id, groupId=group_id,
|
||||
max_results=0)
|
||||
members = cmd.execute()
|
||||
if 'totalResults' not in members.keys():
|
||||
return -1
|
||||
return members['totalResults']
|
||||
@@ -1,118 +0,0 @@
|
||||
#!/usr/bin/python2.4
|
||||
#
|
||||
# Copyright 2010 Google Inc. All Rights Reserved.
|
||||
|
||||
__author__ = 'ade@google.com (Ade Oshineye)'
|
||||
|
||||
from contrib.buzz.simple_wrapper import SimpleWrapper
|
||||
|
||||
import apiclient.oauth
|
||||
import httplib2
|
||||
import logging
|
||||
import oauth2 as oauth
|
||||
import os
|
||||
import pickle
|
||||
import unittest
|
||||
|
||||
class SimpleWrapperTest(unittest.TestCase):
|
||||
# None of these tests make a remote call. We assume the underlying libraries
|
||||
# and servers are working.
|
||||
|
||||
def test_wrapper_rejects_empty_post(self):
|
||||
wrapper = SimpleWrapper()
|
||||
self.assertEquals(None, wrapper.post('', '108242092577082601423'))
|
||||
|
||||
def test_wrapper_rejects_post_containing_only_whitespace(self):
|
||||
wrapper = SimpleWrapper()
|
||||
self.assertEquals(None, wrapper.post(' ', '108242092577082601423'))
|
||||
|
||||
def test_wrapper_rejects_none_post(self):
|
||||
wrapper = SimpleWrapper()
|
||||
self.assertEquals(None, wrapper.post(None, '108242092577082601423'))
|
||||
|
||||
def test_wrapper_rejects_empty_search(self):
|
||||
wrapper = SimpleWrapper()
|
||||
self.assertEquals(None, wrapper.search(''))
|
||||
|
||||
def test_wrapper_rejects_search_containing_only_whitespace(self):
|
||||
wrapper = SimpleWrapper()
|
||||
self.assertEquals(None, wrapper.search(' '))
|
||||
|
||||
def test_wrapper_rejects_search_with_none(self):
|
||||
wrapper = SimpleWrapper()
|
||||
self.assertEquals(None, wrapper.search(None))
|
||||
|
||||
def test_wrapper_returns_minus_one_for_hidden_follower_count(self):
|
||||
wrapper = SimpleWrapper()
|
||||
self.assertEquals(-1, wrapper.get_follower_count(user_id='108242092577082601423'))
|
||||
|
||||
def test_wrapper_returns_positive_value_for_visible_follower_count(self):
|
||||
wrapper = SimpleWrapper()
|
||||
count = wrapper.get_follower_count(user_id='googlebuzz')
|
||||
self.assertTrue(count > 0, "Got %s instead" % count)
|
||||
|
||||
def test_wrapper_returns_minus_one_for_hidden_following_count(self):
|
||||
wrapper = SimpleWrapper()
|
||||
self.assertEquals(-1, wrapper.get_following_count(user_id='108242092577082601423'))
|
||||
|
||||
def test_wrapper_returns_positive_value_for_visible_following_count(self):
|
||||
wrapper = SimpleWrapper()
|
||||
count = wrapper.get_following_count(user_id='googlebuzz')
|
||||
self.assertTrue(count > 0, "Got %s instead" % count)
|
||||
|
||||
class SimpleWrapperRemoteTest(unittest.TestCase):
|
||||
# These tests make remote calls
|
||||
def __init__(self, method_name):
|
||||
unittest.TestCase.__init__(self, method_name)
|
||||
oauth_params_dict = {}
|
||||
for line in open('./contrib_tests/test_account.oacurl.properties'):
|
||||
line = line.strip()
|
||||
if line.startswith('#'):
|
||||
continue
|
||||
key,value = line.split('=')
|
||||
oauth_params_dict[key.strip()] = value.strip()
|
||||
|
||||
consumer = oauth.Consumer(oauth_params_dict['consumerKey'],
|
||||
oauth_params_dict['consumerSecret'])
|
||||
token = oauth.Token(oauth_params_dict['accessToken'],
|
||||
oauth_params_dict['accessTokenSecret'])
|
||||
user_agent = 'google-api-client-python-buzz-webapp/1.0'
|
||||
credentials = apiclient.oauth.OAuthCredentials(consumer, token, user_agent)
|
||||
self.wrapper = SimpleWrapper(credentials=credentials)
|
||||
|
||||
def test_searching_returns_results(self):
|
||||
results = self.wrapper.search('oshineye')
|
||||
self.assertTrue(results is not None)
|
||||
|
||||
def test_searching_honours_max_results(self):
|
||||
max = 5
|
||||
results = self.wrapper.search('oshineye', max_results=max)
|
||||
self.assertEquals(max, len(results))
|
||||
|
||||
def test_can_fetch_profile(self):
|
||||
profile = self.wrapper.get_profile('googlebuzz')
|
||||
self.assertTrue(profile is not None)
|
||||
|
||||
profile = self.wrapper.get_profile(user_id='adewale')
|
||||
self.assertTrue(profile is not None)
|
||||
|
||||
def test_can_post_without_user_id(self):
|
||||
url = self.wrapper.post('test message')
|
||||
self.assertTrue(url is not None)
|
||||
self.assertTrue(url.startswith('https://profiles.google.com/'), url)
|
||||
|
||||
def test_can_post_with_user_id(self):
|
||||
url = self.wrapper.post('test message', '108242092577082601423')
|
||||
self.assertTrue(url is not None)
|
||||
self.assertTrue(url.startswith('https://profiles.google.com/'), url)
|
||||
|
||||
def test_wrapper_returns_positive_value_for_hidden_follower_count_when_authorised(self):
|
||||
count = self.wrapper.get_follower_count(user_id='108242092577082601423')
|
||||
self.assertTrue(count > 0, "Got %s instead" % count)
|
||||
|
||||
def test_wrapper_returns_positive_value_for_hidden_following_count_when_authorised(self):
|
||||
count = self.wrapper.get_following_count(user_id='108242092577082601423')
|
||||
self.assertTrue(count > 0, "Got %s instead" % count)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,6 +0,0 @@
|
||||
#Mon Oct 04 23:45:49 PDT 2010
|
||||
#A set of credentials for posting as http://www.google.com/profiles/108242092577082601423
|
||||
consumerSecret=anonymous
|
||||
accessToken=1/80QKKG4CbMwOZjmW1udam-fVaiUOY1zO-8u3dhiLK6g
|
||||
consumerKey=anonymous
|
||||
accessTokenSecret=R6CnehJTZf9aKuSMtgkmX7KZ
|
||||
@@ -18,7 +18,7 @@
|
||||
"""Copy files from source to dest expanding symlinks along the way.
|
||||
"""
|
||||
|
||||
from distutils.dir_util import copy_tree
|
||||
from shutil import copytree
|
||||
|
||||
import gflags
|
||||
import sys
|
||||
@@ -26,10 +26,27 @@ import sys
|
||||
|
||||
FLAGS = gflags.FLAGS
|
||||
|
||||
# Ignore these files and directories when copying over files into the snapshot.
|
||||
IGNORE = set(['.hg', 'httplib2', 'oauth2', 'simplejson', 'static', 'gflags.py',
|
||||
'gflags_validators.py'])
|
||||
|
||||
# In addition to the above files also ignore these files and directories when
|
||||
# copying over samples into the snapshot.
|
||||
IGNORE_IN_SAMPLES = set(['apiclient', 'oauth2client', 'uritemplate'])
|
||||
|
||||
|
||||
gflags.DEFINE_string('source', '.', 'Directory name to copy from.')
|
||||
gflags.DEFINE_string('dest', 'snapshot', 'Directory name to copy to.')
|
||||
|
||||
|
||||
def _ignore(path, names):
|
||||
retval = set()
|
||||
if path != '.':
|
||||
retval = retval.union(IGNORE_IN_SAMPLES.intersection(names))
|
||||
retval = retval.union(IGNORE.intersection(names))
|
||||
return retval
|
||||
|
||||
|
||||
def main(argv):
|
||||
# Let the gflags module process the command-line arguments
|
||||
try:
|
||||
@@ -38,7 +55,8 @@ def main(argv):
|
||||
print '%s\\nUsage: %s ARGS\\n%s' % (e, argv[0], FLAGS)
|
||||
sys.exit(1)
|
||||
|
||||
copy_tree(FLAGS.source, FLAGS.dest, verbose=True)
|
||||
copytree(FLAGS.source, FLAGS.dest, symlinks=True,
|
||||
ignore=_ignore)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
34
setup.py
34
setup.py
@@ -17,8 +17,6 @@
|
||||
Also installs included versions of third party libraries, if those libraries
|
||||
are not already installed.
|
||||
"""
|
||||
import setup_utils
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
packages = [
|
||||
@@ -30,30 +28,28 @@ packages = [
|
||||
'apiclient.contrib.latitude',
|
||||
'apiclient.contrib.moderator',
|
||||
'uritemplate',
|
||||
]
|
||||
]
|
||||
|
||||
install_requires = []
|
||||
py_modules = []
|
||||
install_requires = [
|
||||
'httplib2',
|
||||
'oauth2',
|
||||
'python-gflags',
|
||||
]
|
||||
|
||||
try:
|
||||
import json
|
||||
needs_json = False
|
||||
except ImportError:
|
||||
needs_json = True
|
||||
|
||||
# (module to test for, install_requires to add if missing, packages to add if missing, py_modules to add if missing)
|
||||
REQUIREMENTS = [
|
||||
('httplib2', 'httplib2', 'httplib2', None),
|
||||
('oauth2', 'oauth2', 'oauth2', None),
|
||||
('gflags', 'python-gflags', None, ['gflags', 'gflags_validators']),
|
||||
(['json', 'simplejson', 'django.utils'], 'simplejson', 'simplejson', None)
|
||||
]
|
||||
|
||||
for import_name, requires, package, modules in REQUIREMENTS:
|
||||
if setup_utils.is_missing(import_name):
|
||||
install_requires.append(requires)
|
||||
|
||||
if needs_json:
|
||||
install_requires.append('simplejson')
|
||||
|
||||
long_desc = """The Google API Client for Python is a client library for
|
||||
accessing the Buzz, Moderator, and Latitude APIs."""
|
||||
|
||||
setup(name="google-api-python-client",
|
||||
version="1.0beta4",
|
||||
version="1.0beta5prerelease",
|
||||
description="Google API Client Library for Python",
|
||||
long_description=long_desc,
|
||||
author="Joe Gregorio",
|
||||
@@ -61,11 +57,9 @@ setup(name="google-api-python-client",
|
||||
url="http://code.google.com/p/google-api-python-client/",
|
||||
install_requires=install_requires,
|
||||
packages=packages,
|
||||
py_modules=py_modules,
|
||||
package_data={
|
||||
'apiclient': ['contrib/*/*.json']
|
||||
},
|
||||
scripts=['bin/enable-app-engine-project'],
|
||||
license="Apache 2.0",
|
||||
keywords="google api client",
|
||||
classifiers=['Development Status :: 4 - Beta',
|
||||
|
||||
@@ -17,34 +17,30 @@
|
||||
Also installs included versions of third party libraries, if those libraries
|
||||
are not already installed.
|
||||
"""
|
||||
import setup_utils
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
packages = [
|
||||
'oauth2client',
|
||||
]
|
||||
|
||||
install_requires = []
|
||||
py_modules = []
|
||||
install_requires = [
|
||||
'httplib2',
|
||||
'python-gflags',
|
||||
]
|
||||
|
||||
try:
|
||||
import json
|
||||
needs_json = False
|
||||
except ImportError
|
||||
needs_json = True
|
||||
|
||||
# (module to test for, install_requires to add if missing, packages to add if missing, py_modules to add if missing)
|
||||
REQUIREMENTS = [
|
||||
('httplib2', 'httplib2', 'httplib2', None),
|
||||
('gflags', 'python-gflags', None, ['gflags', 'gflags_validators']),
|
||||
(['json', 'simplejson', 'django.utils'], 'simplejson', 'simplejson', None)
|
||||
]
|
||||
|
||||
for import_name, requires, package, modules in REQUIREMENTS:
|
||||
if setup_utils.is_missing(import_name):
|
||||
install_requires.append(requires)
|
||||
|
||||
if needs_json:
|
||||
install_requires.append('simplejson')
|
||||
|
||||
long_desc = """The oauth2client is a client library for OAuth 2.0."""
|
||||
|
||||
setup(name="oauth2client",
|
||||
version="1.0beta4",
|
||||
version="1.0beta5prerelease",
|
||||
description="OAuth 2.0 client library",
|
||||
long_description=long_desc,
|
||||
author="Joe Gregorio",
|
||||
|
||||
@@ -1,52 +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.
|
||||
|
||||
"""Utility functions for setup.py file(s)."""
|
||||
|
||||
|
||||
__author__ = 'tom.h.miller@gmail.com (Tom Miller)'
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
def is_missing(packages):
|
||||
"""Return True if a package can't be imported."""
|
||||
|
||||
retval = True
|
||||
sys_path_original = sys.path[:]
|
||||
# Remove the current directory from the list of paths to check when
|
||||
# importing modules.
|
||||
try:
|
||||
# Sometimes it's represented by an empty string?
|
||||
sys.path.remove('')
|
||||
except ValueError:
|
||||
import os.path
|
||||
try:
|
||||
sys.path.remove(os.path.abspath(os.path.curdir))
|
||||
except ValueError:
|
||||
pass
|
||||
if not isinstance(packages, type([])):
|
||||
packages = [packages]
|
||||
for name in packages:
|
||||
try:
|
||||
__import__(name)
|
||||
retval = False
|
||||
except ImportError:
|
||||
retval = True
|
||||
if retval == False:
|
||||
break
|
||||
|
||||
sys.path = sys_path_original
|
||||
|
||||
return retval
|
||||
Reference in New Issue
Block a user