diff options
author | Joe Gregorio <jcgregorio@google.com> | 2013-03-29 16:25:52 -0400 |
---|---|---|
committer | Joe Gregorio <jcgregorio@google.com> | 2013-03-29 16:25:52 -0400 |
commit | 79daca0a32c7eba4867692f650411d099025501d (patch) | |
tree | c13ce0fa121436b6f0d36a65dc6f4a66078147da | |
parent | 731680a341ddd4e4e58febe207f40f894d56577a (diff) | |
download | google-api-python-client-79daca0a32c7eba4867692f650411d099025501d.tar.gz |
Start removing dependence on gflags.
Reviewed in https://codereview.appspot.com/7628044/.
This only removes the dependency from the core library, a second CL will
update all the samples.
-rw-r--r-- | LICENSE | 1 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | README | 1 | ||||
-rw-r--r-- | README_oauth2client | 1 | ||||
-rw-r--r-- | apiclient/model.py | 11 | ||||
-rwxr-xr-x | bin/enable-app-engine-project | 137 | ||||
-rwxr-xr-x[-rw-r--r--] | describe.py | 49 | ||||
-rw-r--r-- | expandsymlinks.py (renamed from expand-symlinks.py) | 27 | ||||
-rw-r--r-- | oauth2client/tools.py | 73 | ||||
-rw-r--r-- | oauth2client/util.py | 34 | ||||
-rw-r--r-- | runsamples.py | 101 | ||||
-rwxr-xr-x[-rw-r--r--] | samples/plus/plus.py | 106 | ||||
-rw-r--r-- | setup.py | 5 | ||||
-rw-r--r-- | setup_oauth2client.py | 1 | ||||
-rw-r--r-- | tests/__init__.py | 5 | ||||
-rw-r--r-- | tests/test_discovery.py | 23 | ||||
-rw-r--r-- | tests/test_json_model.py | 6 | ||||
-rw-r--r-- | tests/test_protobuf_model.py | 3 | ||||
-rwxr-xr-x | tools/gae-zip-creator.sh | 2 |
19 files changed, 157 insertions, 433 deletions
@@ -20,4 +20,3 @@ above and beyond the Python standard library: uritemplates - Apache License 2.0 httplib2 - MIT License -python-gflags - New BSD License @@ -30,7 +30,7 @@ prerelease: test -rm -rf snapshot/ -sudo rm -rf snapshot/ ./tools/gae-zip-creator.sh - python expand-symlinks.py + python expandsymlinks.py cd snapshot; python setup.py clean cd snapshot; python setup.py sdist --formats=gztar,zip cd snapshot; tar czf google-api-python-client-samples-$(shell python setup.py --version).tar.gz samples @@ -58,7 +58,7 @@ oauth2_prerelease: test -rm -rf snapshot/ -sudo rm -rf snapshot/ mkdir snapshot - python expand-symlinks.py --source=oauth2client --dest=snapshot/oauth2client + python expandsymlinks.py --source=oauth2client --dest=snapshot/oauth2client cp setup_oauth2client.py snapshot/setup.py cp MANIFEST_oauth2client.in snapshot/MANIFEST.in cp README_oauth2client snapshot/README @@ -22,7 +22,6 @@ These libraries will be installed when you install the client library: http://code.google.com/p/httplib2 http://code.google.com/p/uri-templates -http://code.google.com/p/python-gflags Depending on your version of Python, these libraries may also be installed: diff --git a/README_oauth2client b/README_oauth2client index 7c51b9eda..4b32ac006 100644 --- a/README_oauth2client +++ b/README_oauth2client @@ -15,7 +15,6 @@ 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: diff --git a/apiclient/model.py b/apiclient/model.py index 12fcab62a..ef91bbda4 100644 --- a/apiclient/model.py +++ b/apiclient/model.py @@ -24,18 +24,14 @@ object representation. __author__ = 'jcgregorio@google.com (Joe Gregorio)' -import gflags import logging import urllib from errors import HttpError from oauth2client.anyjson import simplejson -FLAGS = gflags.FLAGS -gflags.DEFINE_boolean('dump_request_response', False, - 'Dump all http server requests and responses. ' - ) +dump_request_response = False def _abstract(): @@ -106,7 +102,7 @@ class BaseModel(Model): def _log_request(self, headers, path_params, query, body): """Logs debugging information about the request if requested.""" - if FLAGS.dump_request_response: + if dump_request_response: logging.info('--request-start--') logging.info('-headers-start-') for h, v in headers.iteritems(): @@ -177,7 +173,7 @@ class BaseModel(Model): def _log_response(self, resp, content): """Logs debugging information about the response if requested.""" - if FLAGS.dump_request_response: + if dump_request_response: logging.info('--response-start--') for h, v in resp.iteritems(): logging.info('%s: %s', h, v) @@ -198,6 +194,7 @@ class BaseModel(Model): Raises: apiclient.errors.HttpError if a non 2xx response is received. """ + content = content.decode('utf-8') self._log_response(resp, content) # Error handling is TBD, for example, do we retry # for some operation/error combinations? diff --git a/bin/enable-app-engine-project b/bin/enable-app-engine-project deleted file mode 100755 index 2cd22cd6b..000000000 --- a/bin/enable-app-engine-project +++ /dev/null @@ -1,137 +0,0 @@ -#!/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. - -"""Copy the sources for google-api-python-client into an App Engine project. - -Copies the sources of the google-api-python-client -library into a Google App Engine project. This is necessary so that the -source can be uploaded when the application is deployed. - - $ enable-app-engine-project [flags] directory - -""" - -__author__ = 'jcgregorio@google.com (Joe Gregorio)' - -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 -from distutils.errors import DistutilsFileError - -FLAGS = gflags.FLAGS -SOURCES = [ - 'gflags', - 'gflags_validators', - 'httplib2', - 'oauth2client', - 'apiclient', - 'uritemplate', - ] - -gflags.DEFINE_enum('logging_level', 'ERROR', - ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], - 'Set the level of logging detail.') - -gflags.DEFINE_boolean('force', 'False', - 'Forcibly copy over client library files.') - -gflags.DEFINE_boolean('dry_run', 'False', 'Don\'t actually do anything.') - -def find_source(module): - """Find the absolute path for the source of a module. - - Args: - module: str, Name of the module. - Returns: - A tuple of (isdir, location), a boolean that's True if - the source is a directory, False is it's a file, - and the absolute path of the source. - """ - isdir = False - location = '' - m = __import__(module) - logging.debug('Absolute path for module %s: %s' % (module, m.__file__)) - basename = os.path.basename(m.__file__) - if basename.startswith('__init__.'): - isdir = True - 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 - location = pkg_resources.resource_filename(module, module + '.py') - - return (isdir, location) - -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) - - if len(argv) == 1: - print 'Usage: %s ARGS\n%s' % (argv[0], FLAGS) - sys.exit(1) - - # Set the logging according to the command-line flag - logging.getLogger().setLevel(getattr(logging, FLAGS.logging_level)) - - logging.info('Setting up the directories: %s' % argv[1:]) - for dir in argv[1:]: - # Check if the supplied directory is an App Engine project by looking - # for an app.yaml - if not FLAGS.force and not os.path.isfile(os.path.join(dir, 'app.yaml')): - 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) - for source in SOURCES: - isdir, source_location = find_source(source) - if isdir: - target = source - else: - target = source + ".py" - full_target = os.path.join(dir, target) - if not FLAGS.force and os.path.exists(full_target): - noun = isdir and 'Directory' or 'File' - sys.exit("%s already exists in project: %s" % (noun, target)) - action.append((source_location, full_target, isdir)) - - # Now perform all the copying actions we collected - try: - for src, dst, isdir in action: - if isdir: - results = copy_tree(src, dst, FLAGS.dry_run) - for filename in results: - print 'Copied: %s' % filename - else: - filename, copied = copy_file(src, dst, FLAGS.dry_run) - print 'Copied: %s Successfully: %s' % (filename, copied) - except DistutilsFileError, e: - sys.exit(str(e)) - -if __name__ == '__main__': - main(sys.argv) diff --git a/describe.py b/describe.py index 174941e3f..5cecf641b 100644..100755 --- a/describe.py +++ b/describe.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python # # Copyright 2012 Google Inc. # @@ -23,21 +23,19 @@ the generated API surface itself. __author__ = 'jcgregorio@google.com (Joe Gregorio)' +import argparse import os import re +import string import sys -import httplib2 - -from string import Template +from apiclient.discovery import DISCOVERY_URI from apiclient.discovery import build from apiclient.discovery import build_from_document -from apiclient.discovery import DISCOVERY_URI from oauth2client.anyjson import simplejson -import gflags +import httplib2 import uritemplate - CSS = """<style> body, h1, h2, h3, div, span, p, pre, a { @@ -132,19 +130,22 @@ BASE = 'docs/dyn' DIRECTORY_URI = 'https://www.googleapis.com/discovery/v1/apis?preferred=true' -FLAGS = gflags.FLAGS +parser = argparse.ArgumentParser(description=__doc__) -gflags.DEFINE_string('discovery_uri_template', DISCOVERY_URI, - 'URI Template for discovery.') +parser.add_argument('--discovery_uri_template', default=DISCOVERY_URI, + help='URI Template for discovery.') -gflags.DEFINE_string('discovery_uri', '', 'URI of discovery document. ' - 'If supplied then only this API will be documented.') +parser.add_argument('--discovery_uri', default='', + help=('URI of discovery document. If supplied then only ' + 'this API will be documented.')) -gflags.DEFINE_string('directory_uri', DIRECTORY_URI, - 'URI of directory document. ' - 'Unused if --discovery_uri is supplied.') +parser.add_argument('--directory_uri', default=DIRECTORY_URI, + help=('URI of directory document. Unused if --discovery_uri' + ' is supplied.')) + +parser.add_argument('--dest', default=BASE, + help='Directory name to write documents into.') -gflags.DEFINE_string('dest', BASE, 'Directory name to write documents into.') def safe_version(version): @@ -222,7 +223,8 @@ def method(name, doc): """ params = method_params(doc) - return Template(METHOD_TEMPLATE).substitute(name=name, params=params, doc=doc) + return string.Template(METHOD_TEMPLATE).substitute( + name=name, params=params, doc=doc) def breadcrumbs(path, root_discovery): @@ -290,7 +292,8 @@ def document_collection(resource, path, root_discovery, discovery, css=CSS): for name in collections: if not name.startswith('_') and callable(getattr(resource, name)): href = path + name + '.html' - html.append(Template(COLLECTION_LINK).substitute(href=href, name=name)) + html.append(string.Template(COLLECTION_LINK).substitute( + href=href, name=name)) if methods: for name in methods: @@ -298,7 +301,7 @@ def document_collection(resource, path, root_discovery, discovery, css=CSS): doc = getattr(resource, name).__doc__ params = method_params(doc) firstline = doc.splitlines()[0] - html.append(Template(METHOD_LINK).substitute( + html.append(string.Template(METHOD_LINK).substitute( name=name, params=params, firstline=firstline)) if methods: @@ -371,13 +374,7 @@ def document_api_from_discovery_document(uri): if __name__ == '__main__': - # Let the gflags module process the command-line arguments - try: - argv = FLAGS(sys.argv) - except gflags.FlagsError, e: - print '%s\\nUsage: %s ARGS\\n%s' % (e, argv[0], FLAGS) - sys.exit(1) - + FLAGS = parser.parse_args(sys.argv[1:]) if FLAGS.discovery_uri: document_api_from_discovery_document(FLAGS.discovery_uri) else: diff --git a/expand-symlinks.py b/expandsymlinks.py index 39b2c21e0..50967ae98 100644 --- a/expand-symlinks.py +++ b/expandsymlinks.py @@ -20,23 +20,24 @@ from shutil import copytree -import gflags +import argparse 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']) +IGNORE = set(['.hg', 'httplib2', 'oauth2', 'simplejson', 'static']) # 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']) +parser = argparse.ArgumentParser(description=__doc__) + +parser.add_argument('--source', default='.', + help='Directory name to copy from.') -gflags.DEFINE_string('source', '.', 'Directory name to copy from.') -gflags.DEFINE_string('dest', 'snapshot', 'Directory name to copy to.') +parser.add_argument('--dest', default='snapshot', + help='Directory name to copy to.') def _ignore(path, names): @@ -47,17 +48,11 @@ def _ignore(path, names): return retval -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) - +def main(): copytree(FLAGS.source, FLAGS.dest, symlinks=True, ignore=_ignore) if __name__ == '__main__': - main(sys.argv) + FLAGS = parser.parse_args(sys.argv[1:]) + main() diff --git a/oauth2client/tools.py b/oauth2client/tools.py index 93b0171dc..839f29692 100644 --- a/oauth2client/tools.py +++ b/oauth2client/tools.py @@ -24,7 +24,9 @@ __all__ = ['run'] import BaseHTTPServer -import gflags +import argparse +import logging +import os import socket import sys import webbrowser @@ -38,20 +40,31 @@ try: except ImportError: from cgi import parse_qsl +_CLIENT_SECRETS_MESSAGE = """WARNING: Please configure OAuth 2.0 -FLAGS = gflags.FLAGS +To make this sample run you will need to populate the client_secrets.json file +found at: -gflags.DEFINE_boolean('auth_local_webserver', True, - ('Run a local web server to handle redirects during ' - 'OAuth authorization.')) + %s -gflags.DEFINE_string('auth_host_name', 'localhost', - ('Host name to use when running a local web server to ' - 'handle redirects during OAuth authorization.')) +with information from the APIs Console <https://code.google.com/apis/console>. -gflags.DEFINE_multi_int('auth_host_port', [8080, 8090], - ('Port to use when running a local web server to ' - 'handle redirects during OAuth authorization.')) +""" + +# run_parser is an ArgumentParser that contains command-line options expected +# by tools.run(). Pass it in as part of the 'parents' argument to your own +# ArgumentParser. +argparser = argparse.ArgumentParser(add_help=False) +argparser.add_argument('--auth_host_name', default='localhost', + help='Hostname when running a local web server.') +argparser.add_argument('--noauth_local_webserver', action='store_true', + default=False, help='Do not run a local web server.') +argparser.add_argument('--auth_host_port', default=[8080, 8090], type=int, + nargs='*', help='Port web server should listen on.') +argparser.add_argument('--logging_level', default='ERROR', + choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', + 'CRITICAL'], + help='Set the logging level of detail.') class ClientRedirectServer(BaseHTTPServer.HTTPServer): @@ -92,8 +105,8 @@ class ClientRedirectHandler(BaseHTTPServer.BaseHTTPRequestHandler): pass -@util.positional(2) -def run(flow, storage, http=None): +@util.positional(3) +def run(flow, storage, flags, http=None): """Core code for a command-line application. The run() function is called from your application and runs through all the @@ -121,32 +134,40 @@ def run(flow, storage, http=None): during OAuth authorization. (default: 'true') - Since it uses flags make sure to initialize the gflags module before calling - run(). + The tools module defines an ArgumentParser the already contains the flag + definitions that run() requires. You can pass that ArgumentParser to your + ArgumentParser constructor: + + parser = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + parents=[tools.run_parser]) + flags = parser.parse_args(argv) Args: flow: Flow, an OAuth 2.0 Flow to step through. storage: Storage, a Storage to store the credential in. + flags: argparse.ArgumentParser, the command-line flags. http: An instance of httplib2.Http.request or something that acts like it. Returns: Credentials, the obtained credential. """ - if FLAGS.auth_local_webserver: + logging.getLogger().setLevel(getattr(logging, flags.logging_level)) + if not flags.noauth_local_webserver: success = False port_number = 0 - for port in FLAGS.auth_host_port: + for port in flags.auth_host_port: port_number = port try: - httpd = ClientRedirectServer((FLAGS.auth_host_name, port), + httpd = ClientRedirectServer((flags.auth_host_name, port), ClientRedirectHandler) except socket.error, e: pass else: success = True break - FLAGS.auth_local_webserver = success + flags.noauth_local_webserver = not success if not success: print 'Failed to start a local webserver listening on either port 8080' print 'or port 9090. Please check your firewall settings and locally' @@ -156,14 +177,14 @@ def run(flow, storage, http=None): print 'authorization.' print - if FLAGS.auth_local_webserver: - oauth_callback = 'http://%s:%s/' % (FLAGS.auth_host_name, port_number) + if not flags.noauth_local_webserver: + oauth_callback = 'http://%s:%s/' % (flags.auth_host_name, port_number) else: oauth_callback = OOB_CALLBACK_URN flow.redirect_uri = oauth_callback authorize_url = flow.step1_get_authorize_url() - if FLAGS.auth_local_webserver: + if not flags.noauth_local_webserver: webbrowser.open(authorize_url, new=1, autoraise=True) print 'Your browser has been opened to visit:' print @@ -181,7 +202,7 @@ def run(flow, storage, http=None): print code = None - if FLAGS.auth_local_webserver: + if not flags.noauth_local_webserver: httpd.handle_request() if 'error' in httpd.query_params: sys.exit('Authentication request was rejected.') @@ -203,3 +224,9 @@ def run(flow, storage, http=None): print 'Authentication successful.' return credential + + +def message_if_missing(filename): + """Helpful message to display if the CLIENT_SECRETS file is missing.""" + + return _CLIENT_SECRETS_MESSAGE % filename diff --git a/oauth2client/util.py b/oauth2client/util.py index ee6a10038..90dff155b 100644 --- a/oauth2client/util.py +++ b/oauth2client/util.py @@ -22,9 +22,11 @@ __author__ = ['rafek@google.com (Rafe Kaplan)', ] __all__ = [ 'positional', + 'POSITIONAL_WARNING', + 'POSITIONAL_EXCEPTION', + 'POSITIONAL_IGNORE', ] -import gflags import inspect import logging import types @@ -38,12 +40,13 @@ except ImportError: logger = logging.getLogger(__name__) -FLAGS = gflags.FLAGS - -gflags.DEFINE_enum('positional_parameters_enforcement', 'WARNING', - ['EXCEPTION', 'WARNING', 'IGNORE'], - 'The action when an oauth2client.util.positional declaration is violated.') +POSITIONAL_WARNING = 'WARNING' +POSITIONAL_EXCEPTION = 'EXCEPTION' +POSITIONAL_IGNORE = 'IGNORE' +POSITIONAL_SET = frozenset([POSITIONAL_WARNING, POSITIONAL_EXCEPTION, + POSITIONAL_IGNORE]) +positional_parameters_enforcement = POSITIONAL_WARNING def positional(max_positional_args): """A decorator to declare that only the first N arguments my be positional. @@ -93,10 +96,11 @@ def positional(max_positional_args): def my_method(cls, pos1, kwonly1=None): ... - The positional decorator behavior is controlled by the - --positional_parameters_enforcement flag. The flag may be set to 'EXCEPTION', - 'WARNING' or 'IGNORE' to raise an exception, log a warning, or do nothing, - respectively, if a declaration is violated. + The positional decorator behavior is controlled by + util.positional_parameters_enforcement, which may be set to + POSITIONAL_EXCEPTION, POSITIONAL_WARNING or POSITIONAL_IGNORE to raise an + exception, log a warning, or do nothing, respectively, if a declaration is + violated. Args: max_positional_arguments: Maximum number of positional arguments. All @@ -107,9 +111,9 @@ def positional(max_positional_args): being used as positional parameters. Raises: - TypeError if a key-word only argument is provided as a positional parameter, - but only if the --positional_parameters_enforcement flag is set to - 'EXCEPTION'. + TypeError if a key-word only argument is provided as a positional + parameter, but only if util.positional_parameters_enforcement is set to + POSITIONAL_EXCEPTION. """ def positional_decorator(wrapped): def positional_wrapper(*args, **kwargs): @@ -119,9 +123,9 @@ def positional(max_positional_args): plural_s = 's' message = '%s() takes at most %d positional argument%s (%d given)' % ( wrapped.__name__, max_positional_args, plural_s, len(args)) - if FLAGS.positional_parameters_enforcement == 'EXCEPTION': + if positional_parameters_enforcement == POSITIONAL_EXCEPTION: raise TypeError(message) - elif FLAGS.positional_parameters_enforcement == 'WARNING': + elif positional_parameters_enforcement == POSITIONAL_WARNING: logger.warning(message) else: # IGNORE pass diff --git a/runsamples.py b/runsamples.py deleted file mode 100644 index a526f712f..000000000 --- a/runsamples.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python -"""Execute all sample applications. - -Runs over all the sample applications, determines their type (App Engine, -Django, or a command-line application), and then runs them checking for a good -return status in the case of command-line applications and a 200 OK response in -the case of the App Engine and Django samples. -""" -import gflags -import httplib2 -import logging -import os -import signal -import subprocess -import sys -import time - -FLAGS = gflags.FLAGS - -gflags.DEFINE_list('samples_to_skip', ['latitude'], - 'A comma separated list of project directory names to be skipped.') - -gflags.DEFINE_enum('logging_level', 'INFO', - ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], - 'Set the level of logging detail.') - -gflags.DEFINE_string('app_engine_dir', '../google_appengine/', - 'Directory where Google App Engine is installed.') - -gflags.DEFINE_string('sample_root', 'samples/oauth2', - 'The root directory for all the samples.') - - -def main(argv): - try: - argv = FLAGS(argv) - except gflags.FlagsError, e: - print '%s\\nUsage: %s ARGS\\n%s' % (e, argv[0], FLAGS) - sys.exit(1) - - logging.getLogger().setLevel(getattr(logging, FLAGS.logging_level)) - - for dirname in os.listdir(FLAGS.sample_root): - fulldirname = os.path.join(FLAGS.sample_root, dirname) - if dirname in FLAGS.samples_to_skip: - logging.debug('Skipping ' + fulldirname + ' (blacklist)') - continue - filelist = os.listdir(fulldirname) - if 'settings.py' in filelist and 'manage.py' in filelist: - logging.info(fulldirname + ' [Django]') - proc = subprocess.Popen( - [os.path.join(fulldirname, 'manage.py'), - 'runserver']) - # Now just wait, because Django actually spawns a sub-process that does - # the I/O and does something funky with stdout so we can't read it and - # figure out when it is started. - time.sleep(3) - h = httplib2.Http() - resp, content = h.request('http://localhost:8000/') - assert(200 == resp.status) - time.sleep(1) - logging.debug('Django ppid: %d', proc.pid) - # Find and kill the sub-process manage.py forked. - findpids = subprocess.Popen(['ps', '--ppid', str(proc.pid), 'o', 'pid',], - stdout=subprocess.PIPE) - for p in findpids.stdout.readlines(): - if 'PID' not in p: - os.kill(int(p), signal.SIGINT) - os.kill(proc.pid, signal.SIGINT) - proc.wait() - elif 'app.yaml' in filelist: - logging.info(fulldirname + ' [App Engine]') - proc = subprocess.Popen( - [os.path.join(FLAGS.app_engine_dir, 'dev_appserver.py'), - fulldirname], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - line = proc.stdout.readline() - logging.debug('READ: ' + line) - while '] Running application' not in line: - line = proc.stdout.readline() - logging.debug('READ: ' + line) - h = httplib2.Http() - resp, content = h.request('http://localhost:8080/') - assert(200 == resp.status) - time.sleep(1) - os.kill(proc.pid, signal.SIGINT) - proc.wait() - else: - logging.info(fulldirname + ' [Command-line]') - for filename in os.listdir(fulldirname): - if filename.endswith('.py'): - logging.info('Running: ' + filename) - proc = subprocess.Popen(['python', - os.path.join(fulldirname, filename)]) - returncode = proc.wait() - assert(returncode == 0) - - -if __name__ == '__main__': - main(sys.argv) diff --git a/samples/plus/plus.py b/samples/plus/plus.py index c6089f9e8..b88395b25 100644..100755 --- a/samples/plus/plus.py +++ b/samples/plus/plus.py @@ -1,7 +1,7 @@ -#!/usr/bin/python2.4 +#!/usr/bin/env python # -*- coding: utf-8 -*- # -# Copyright (C) 2010 Google Inc. +# Copyright (C) 2013 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,122 +17,80 @@ """Simple command-line sample for the Google+ API. -Command-line application that retrieves the users latest content and -then adds a new entry. - -Usage: - $ python plus.py - -You can also get help on all the command-line flags the program understands -by running: - - $ python plus.py --help - -To get detailed log output run: - - $ python plus.py --logging_level=DEBUG -""" +Command-line application that retrieves the list of the user's posts.""" __author__ = 'jcgregorio@google.com (Joe Gregorio)' -import gflags -import httplib2 +import argparse import logging import os -import pprint import sys -from apiclient.discovery import build -from oauth2client.file import Storage -from oauth2client.client import AccessTokenRefreshError -from oauth2client.client import flow_from_clientsecrets -from oauth2client.tools import run +import httplib2 +from apiclient import discovery +from oauth2client import file +from oauth2client import client +from oauth2client import tools -FLAGS = gflags.FLAGS # CLIENT_SECRETS, name of a file containing the OAuth 2.0 information for this # application, including client_id and client_secret, which are found # on the API Access tab on the Google APIs -# Console <http://code.google.com/apis/console> -CLIENT_SECRETS = 'client_secrets.json' - -# Helpful message to display in the browser if the CLIENT_SECRETS file -# is missing. -MISSING_CLIENT_SECRETS_MESSAGE = """ -WARNING: Please configure OAuth 2.0 - -To make this sample run you will need to populate the client_secrets.json file -found at: - - %s - -with information from the APIs Console <https://code.google.com/apis/console>. - -""" % os.path.join(os.path.dirname(__file__), CLIENT_SECRETS) +# Console <http://code.google.com/apis/console>. +CLIENT_SECRETS = os.path.join(os.path.dirname(__file__), 'client_secrets.json') # Set up a Flow object to be used if we need to authenticate. -FLOW = flow_from_clientsecrets(CLIENT_SECRETS, +FLOW = client.flow_from_clientsecrets(CLIENT_SECRETS, scope='https://www.googleapis.com/auth/plus.me', - message=MISSING_CLIENT_SECRETS_MESSAGE) - - -# The gflags module makes defining command-line options easy for -# applications. Run this program with the '--help' argument to see -# all the flags that it understands. -gflags.DEFINE_enum('logging_level', 'ERROR', - ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], - 'Set the level of logging detail.') + message=tools.message_if_missing(CLIENT_SECRETS)) 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) - - # Set the logging according to the command-line flag - logging.getLogger().setLevel(getattr(logging, FLAGS.logging_level)) + # Parse command-line options. + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + parents=[tools.argparser]) + flags = parser.parse_args(argv[1:]) # If the Credentials don't exist or are invalid run through the native client # flow. The Storage object will ensure that if successful the good # Credentials will get written back to a file. - storage = Storage('plus.dat') + storage = file.Storage('plus.dat') credentials = storage.get() if credentials is None or credentials.invalid: - credentials = run(FLOW, storage) + credentials = tools.run(FLOW, storage, flags) # Create an httplib2.Http object to handle our HTTP requests and authorize it # with our good Credentials. - http = httplib2.Http() - http = credentials.authorize(http) + http = credentials.authorize(httplib2.Http()) - service = build("plus", "v1", http=http) + service = discovery.build('plus', 'v1', http=http) try: - person = service.people().get(userId='me').execute(http=http) + person = service.people().get(userId='me').execute() - print "Got your ID: %s" % person['displayName'] + print 'Got your ID: %s' % person['displayName'] print - print "%-040s -> %s" % ("[Activitity ID]", "[Content]") + print '%-040s -> %s' % ('[Activitity ID]', '[Content]') - # Don't execute the request until we reach the paging loop below + # Don't execute the request until we reach the paging loop below. request = service.activities().list( userId=person['id'], collection='public') + # Loop over every activity and print the ID and a short snippet of content. - while ( request != None ): + while request is not None: activities_doc = request.execute() for item in activities_doc.get('items', []): print '%-040s -> %s' % (item['id'], item['object']['content'][:30]) request = service.activities().list_next(request, activities_doc) - except AccessTokenRefreshError: - print ("The credentials have been revoked or expired, please re-run" - "the application to re-authorize") + except client.AccessTokenRefreshError: + print ('The credentials have been revoked or expired, please re-run' + 'the application to re-authorize.') if __name__ == '__main__': main(sys.argv) @@ -26,7 +26,6 @@ packages = [ install_requires = [ 'httplib2>=0.8', - 'python-gflags', ] needs_json = False @@ -56,9 +55,7 @@ setup(name="google-api-python-client", url="http://code.google.com/p/google-api-python-client/", install_requires=install_requires, packages=packages, - package_data={ - }, - scripts=['bin/enable-app-engine-project'], + package_data={}, license="Apache 2.0", keywords="google api client", classifiers=['Development Status :: 5 - Production/Stable', diff --git a/setup_oauth2client.py b/setup_oauth2client.py index e67377d9e..581ed6189 100644 --- a/setup_oauth2client.py +++ b/setup_oauth2client.py @@ -26,7 +26,6 @@ packages = [ install_requires = [ 'httplib2>=0.8', - 'python-gflags', ] needs_json = False diff --git a/tests/__init__.py b/tests/__init__.py index 245199564..7913e6ffe 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -14,9 +14,8 @@ __author__ = 'afshar@google.com (Ali Afshar)' -import gflags +import oauth2client.util def setup_package(): """Run on testing package.""" - FLAGS = gflags.FLAGS - FLAGS.positional_parameters_enforcement = 'EXCEPTION' + oauth2client.util.positional_parameters_enforcement = 'EXCEPTION' diff --git a/tests/test_discovery.py b/tests/test_discovery.py index b8b5ac024..499edda42 100644 --- a/tests/test_discovery.py +++ b/tests/test_discovery.py @@ -25,7 +25,6 @@ __author__ = 'jcgregorio@google.com (Joe Gregorio)' import copy import datetime -import gflags import httplib2 import os import pickle @@ -65,16 +64,16 @@ from apiclient.http import MediaUpload from apiclient.http import MediaUploadProgress from apiclient.http import tunnel_patch from oauth2client import GOOGLE_TOKEN_URI +from oauth2client import util from oauth2client.anyjson import simplejson from oauth2client.client import OAuth2Credentials -from oauth2client.util import _add_query_parameter + import uritemplate DATA_DIR = os.path.join(os.path.dirname(__file__), 'data') -FLAGS = gflags.FLAGS -FLAGS.positional_parameters_enforcement = 'EXCEPTION' +util.positional_parameters_enforcement = util.POSITIONAL_EXCEPTION def assertUrisEqual(testcase, expected, actual): @@ -331,20 +330,20 @@ class DiscoveryErrors(unittest.TestCase): class DiscoveryFromDocument(unittest.TestCase): def test_can_build_from_local_document(self): - discovery = file(datafile('plus.json')).read() + discovery = open(datafile('plus.json')).read() plus = build_from_document(discovery, base="https://www.googleapis.com/") self.assertTrue(plus is not None) self.assertTrue(hasattr(plus, 'activities')) def test_can_build_from_local_deserialized_document(self): - discovery = file(datafile('plus.json')).read() + discovery = open(datafile('plus.json')).read() discovery = simplejson.loads(discovery) plus = build_from_document(discovery, base="https://www.googleapis.com/") self.assertTrue(plus is not None) self.assertTrue(hasattr(plus, 'activities')) def test_building_with_base_remembers_base(self): - discovery = file(datafile('plus.json')).read() + discovery = open(datafile('plus.json')).read() base = "https://www.example.com/" plus = build_from_document(discovery, base=base) @@ -364,7 +363,7 @@ class DiscoveryFromHttp(unittest.TestCase): os.environ['REMOTE_ADDR'] = '10.0.0.1' try: http = HttpMockSequence([ - ({'status': '400'}, file(datafile('zoo.json'), 'r').read()), + ({'status': '400'}, open(datafile('zoo.json'), 'rb').read()), ]) zoo = build('zoo', 'v1', http=http, developerKey='foo', discoveryServiceUrl='http://example.com') @@ -377,7 +376,7 @@ class DiscoveryFromHttp(unittest.TestCase): # out of the raised exception. try: http = HttpMockSequence([ - ({'status': '400'}, file(datafile('zoo.json'), 'r').read()), + ({'status': '400'}, open(datafile('zoo.json'), 'rb').read()), ]) zoo = build('zoo', 'v1', http=http, developerKey=None, discoveryServiceUrl='http://example.com') @@ -501,7 +500,7 @@ class Discovery(unittest.TestCase): def test_tunnel_patch(self): http = HttpMockSequence([ - ({'status': '200'}, file(datafile('zoo.json'), 'r').read()), + ({'status': '200'}, open(datafile('zoo.json'), 'rb').read()), ({'status': '200'}, 'echo_request_headers_as_json'), ]) http = tunnel_patch(http) @@ -1091,8 +1090,8 @@ class Discovery(unittest.TestCase): zoo_uri = uritemplate.expand(DISCOVERY_URI, {'api': 'zoo', 'apiVersion': 'v1'}) if 'REMOTE_ADDR' in os.environ: - zoo_uri = _add_query_parameter(zoo_uri, 'userIp', - os.environ['REMOTE_ADDR']) + zoo_uri = util._add_query_parameter(zoo_uri, 'userIp', + os.environ['REMOTE_ADDR']) http = httplib2.Http() original_request = http.request diff --git a/tests/test_json_model.py b/tests/test_json_model.py index d6cf0c0bd..281affb2e 100644 --- a/tests/test_json_model.py +++ b/tests/test_json_model.py @@ -22,7 +22,6 @@ Unit tests for the JSON model. __author__ = 'jcgregorio@google.com (Joe Gregorio)' import copy -import gflags import os import unittest import httplib2 @@ -32,8 +31,6 @@ from apiclient.errors import HttpError from apiclient.model import JsonModel from oauth2client.anyjson import simplejson -FLAGS = gflags.FLAGS - # Python 2.5 requires different modules try: from urlparse import parse_qs @@ -212,8 +209,7 @@ class Model(unittest.TestCase): self[key] = value old_logging = apiclient.model.logging apiclient.model.logging = MockLogging() - apiclient.model.FLAGS = copy.deepcopy(FLAGS) - apiclient.model.FLAGS.dump_request_response = True + apiclient.model.dump_request_response = True model = JsonModel() request_body = { 'field1': 'value1', diff --git a/tests/test_protobuf_model.py b/tests/test_protobuf_model.py index 02e88465e..b9c92b021 100644 --- a/tests/test_protobuf_model.py +++ b/tests/test_protobuf_model.py @@ -21,7 +21,6 @@ Unit tests for the Protocol Buffer model. __author__ = 'mmcdonald@google.com (Matt McDonald)' -import gflags import unittest import httplib2 import apiclient.model @@ -29,8 +28,6 @@ import apiclient.model from apiclient.errors import HttpError from apiclient.model import ProtocolBufferModel -FLAGS = gflags.FLAGS - # Python 2.5 requires different modules try: from urlparse import parse_qs diff --git a/tools/gae-zip-creator.sh b/tools/gae-zip-creator.sh index 2e63da516..1f225b1ba 100755 --- a/tools/gae-zip-creator.sh +++ b/tools/gae-zip-creator.sh @@ -57,7 +57,7 @@ echo "Built zip in ${ZIP_PATH}" # Sanity test the zip. # TODO (afshar): Run the complete test suite. echo "Sanity testing the zip:" -export SANITY_MODS="gflags httplib2 apiclient uritemplate oauth2client" +export SANITY_MODS="httplib2 apiclient uritemplate oauth2client" export SANITY_ZIP=${ZIP_PATH} export PYTHONPATH=${ZIP_PATH} ${ENV_PATH}/bin/python -c "import sys, os |