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
	 Joe Gregorio
					Joe Gregorio