Adds apiclient.sample_tools.

Consolidates many of the common idioms used in the code samples which will
make the samples shorter, easier to maintain, and more focused on API and not
on Auth.

Demonstrates how much simpler samples get by bringing the Plus sample up to
date.
diff --git a/apiclient/sample_tools.py b/apiclient/sample_tools.py
new file mode 100644
index 0000000..ff17b2b
--- /dev/null
+++ b/apiclient/sample_tools.py
@@ -0,0 +1,93 @@
+# 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.
+# 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.
+
+"""Utilities for making samples.
+
+Consolidates a lot of code commonly repeated in sample applications.
+"""
+
+__author__ = 'jcgregorio@google.com (Joe Gregorio)'
+__all__ = ['init']
+
+
+import argparse
+import httplib2
+import os
+
+from apiclient import discovery
+from oauth2client import client
+from oauth2client import file
+from oauth2client import tools
+
+
+def init(argv, name, version, doc, filename, scope=None, parents=[]):
+  """A common initialization routine for samples.
+
+  Many of the sample applications do the same initialization, which has now
+  been consolidated into this function. This function uses common idioms found
+  in almost all the samples, i.e. for an API with name 'apiname', the
+  credentials are stored in a file named apiname.dat, and the
+  client_secrets.json file is stored in the same directory as the application
+  main file.
+
+  Args:
+    argv: list of string, the command-line parameters of the application.
+    name: string, name of the API.
+    version: string, version of the API.
+    doc: string, description of the application. Usually set to __doc__.
+    file: string, filename of the application. Usually set to __file__.
+    parents: list of argparse.ArgumentParser, additional command-line flags.
+    scope: string, The OAuth scope used.
+
+  Returns:
+    A tuple of (service, flags), where service is the service object and flags
+    is the parsed command-line flags.
+  """
+  if scope is None:
+    scope = 'https://www.googleapis.com/auth/' + name
+
+  # Parser command-line arguments.
+  parent_parsers = [tools.argparser]
+  parent_parsers.extend(parents)
+  parser = argparse.ArgumentParser(
+      description=doc,
+      formatter_class=argparse.RawDescriptionHelpFormatter,
+      parents=parent_parsers)
+  flags = parser.parse_args(argv[1:])
+
+  # 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 = os.path.join(os.path.dirname(filename),
+                                'client_secrets.json')
+
+  # Set up a Flow object to be used if we need to authenticate.
+  flow = client.flow_from_clientsecrets(client_secrets,
+      scope=scope,
+      message=tools.message_if_missing(client_secrets))
+
+  # Prepare credentials, and authorize HTTP object with them.
+  # 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 = file.Storage(name + '.dat')
+  credentials = storage.get()
+  if credentials is None or credentials.invalid:
+    credentials = tools.run(flow, storage, flags)
+  http = credentials.authorize(http = httplib2.Http())
+
+  # Construct a service object via the discovery service.
+  service = discovery.build(name, version, http=http)
+  return (service, flags)
diff --git a/oauth2client/tools.py b/oauth2client/tools.py
index 839f296..e283a8a 100644
--- a/oauth2client/tools.py
+++ b/oauth2client/tools.py
@@ -1,4 +1,4 @@
-# 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.
@@ -20,19 +20,20 @@
 """
 
 __author__ = 'jcgregorio@google.com (Joe Gregorio)'
-__all__ = ['run']
+__all__ = ['argparser', 'run', 'message_if_missing']
 
 
 import BaseHTTPServer
 import argparse
+import httplib2
 import logging
 import os
 import socket
 import sys
 import webbrowser
 
-from oauth2client.client import FlowExchangeError
-from oauth2client.client import OOB_CALLBACK_URN
+from oauth2client import client
+from oauth2client import file
 from oauth2client import util
 
 try:
@@ -180,7 +181,7 @@
   if not flags.noauth_local_webserver:
     oauth_callback = 'http://%s:%s/' % (flags.auth_host_name, port_number)
   else:
-    oauth_callback = OOB_CALLBACK_URN
+    oauth_callback = client.OOB_CALLBACK_URN
   flow.redirect_uri = oauth_callback
   authorize_url = flow.step1_get_authorize_url()
 
@@ -216,7 +217,7 @@
 
   try:
     credential = flow.step2_exchange(code, http=http)
-  except FlowExchangeError, e:
+  except client.FlowExchangeError, e:
     sys.exit('Authentication has failed: %s' % e)
 
   storage.put(credential)
diff --git a/samples/plus/plus.py b/samples/plus/plus.py
index b88395b..d8375ca 100755
--- a/samples/plus/plus.py
+++ b/samples/plus/plus.py
@@ -21,53 +21,17 @@
 
 __author__ = 'jcgregorio@google.com (Joe Gregorio)'
 
-import argparse
-import logging
-import os
 import sys
 
-import httplib2
-
-from apiclient import discovery
-from oauth2client import file
 from oauth2client import client
-from oauth2client import tools
-
-
-# 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 = os.path.join(os.path.dirname(__file__), 'client_secrets.json')
-
-# Set up a Flow object to be used if we need to authenticate.
-FLOW = client.flow_from_clientsecrets(CLIENT_SECRETS,
-    scope='https://www.googleapis.com/auth/plus.me',
-    message=tools.message_if_missing(CLIENT_SECRETS))
+from apiclient import sample_tools
 
 
 def main(argv):
-  # 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 = file.Storage('plus.dat')
-  credentials = storage.get()
-
-  if credentials is None or credentials.invalid:
-    credentials = tools.run(FLOW, storage, flags)
-
-  # Create an httplib2.Http object to handle our HTTP requests and authorize it
-  # with our good Credentials.
-  http = credentials.authorize(httplib2.Http())
-
-  service = discovery.build('plus', 'v1', http=http)
+  # Authenticate and construct service.
+  service, flags = sample_tools.init(
+      argv, 'plus', 'v1', __doc__, __file__,
+      scope='https://www.googleapis.com/auth/plus.me')
 
   try:
     person = service.people().get(userId='me').execute()