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.
diff --git a/oauth2client/tools.py b/oauth2client/tools.py
index 93b0171..839f296 100644
--- a/oauth2client/tools.py
+++ b/oauth2client/tools.py
@@ -24,7 +24,9 @@
import BaseHTTPServer
-import gflags
+import argparse
+import logging
+import os
import socket
import sys
import webbrowser
@@ -38,20 +40,31 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 ee6a100..90dff15 100644
--- a/oauth2client/util.py
+++ b/oauth2client/util.py
@@ -22,9 +22,11 @@
]
__all__ = [
'positional',
+ 'POSITIONAL_WARNING',
+ 'POSITIONAL_EXCEPTION',
+ 'POSITIONAL_IGNORE',
]
-import gflags
import inspect
import logging
import types
@@ -38,12 +40,13 @@
logger = logging.getLogger(__name__)
-FLAGS = gflags.FLAGS
+POSITIONAL_WARNING = 'WARNING'
+POSITIONAL_EXCEPTION = 'EXCEPTION'
+POSITIONAL_IGNORE = 'IGNORE'
+POSITIONAL_SET = frozenset([POSITIONAL_WARNING, POSITIONAL_EXCEPTION,
+ POSITIONAL_IGNORE])
-gflags.DEFINE_enum('positional_parameters_enforcement', 'WARNING',
- ['EXCEPTION', 'WARNING', 'IGNORE'],
- 'The action when an oauth2client.util.positional declaration is violated.')
-
+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 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 @@
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 @@
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