| Index: third_party/google-endpoints/endpoints/endpointscfg.py
|
| diff --git a/third_party/google-endpoints/endpoints/endpointscfg.py b/third_party/google-endpoints/endpoints/endpointscfg.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..465e020fa4cae78f46773c8c77a1377b5b95f366
|
| --- /dev/null
|
| +++ b/third_party/google-endpoints/endpoints/endpointscfg.py
|
| @@ -0,0 +1,625 @@
|
| +#!/usr/bin/python
|
| +# Copyright 2016 Google Inc. All Rights Reserved.
|
| +#
|
| +# 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.
|
| +r"""External script for generating Cloud Endpoints related files.
|
| +
|
| +The gen_discovery_doc subcommand takes a list of fully qualified ProtoRPC
|
| +service names and calls a cloud service which generates a discovery document in
|
| +REST or RPC style.
|
| +
|
| +Example:
|
| + endpointscfg.py gen_discovery_doc -o . -f rest postservice.GreetingsV1
|
| +
|
| +The gen_client_lib subcommand takes a discovery document and calls a cloud
|
| +service to generate a client library for a target language (currently just Java)
|
| +
|
| +Example:
|
| + endpointscfg.py gen_client_lib java -o . greetings-v0.1.discovery
|
| +
|
| +The get_client_lib subcommand does both of the above commands at once.
|
| +
|
| +Example:
|
| + endpointscfg.py get_client_lib java -o . postservice.GreetingsV1
|
| +
|
| +The gen_api_config command outputs an .api configuration file for a service.
|
| +
|
| +Example:
|
| + endpointscfg.py gen_api_config -o . -a /path/to/app \
|
| + --hostname myhost.appspot.com postservice.GreetingsV1
|
| +"""
|
| +
|
| +from __future__ import with_statement
|
| +
|
| +import argparse
|
| +import collections
|
| +import contextlib
|
| +# Conditional import, pylint: disable=g-import-not-at-top
|
| +try:
|
| + import json
|
| +except ImportError:
|
| + # If we can't find json packaged with Python import simplejson, which is
|
| + # packaged with the SDK.
|
| + import simplejson as json
|
| +import os
|
| +import re
|
| +import sys
|
| +import urllib
|
| +import urllib2
|
| +import _endpointscfg_setup # pylint: disable=unused-import
|
| +import api_config
|
| +from protorpc import remote
|
| +import openapi_generator
|
| +import yaml
|
| +
|
| +from google.appengine.ext import testbed
|
| +
|
| +DISCOVERY_DOC_BASE = ('https://webapis-discovery.appspot.com/_ah/api/'
|
| + 'discovery/v1/apis/generate/')
|
| +CLIENT_LIBRARY_BASE = 'https://google-api-client-libraries.appspot.com/generate'
|
| +_VISIBLE_COMMANDS = ('get_client_lib', 'get_discovery_doc', 'get_openapi_spec')
|
| +
|
| +
|
| +class ServerRequestException(Exception):
|
| + """Exception for problems with the request to a server."""
|
| +
|
| + def __init__(self, http_error):
|
| + """Create a ServerRequestException from a given urllib2.HTTPError.
|
| +
|
| + Args:
|
| + http_error: The HTTPError that the ServerRequestException will be
|
| + based on.
|
| + """
|
| + error_details = None
|
| + error_response = None
|
| + if http_error.fp:
|
| + try:
|
| + error_response = http_error.fp.read()
|
| + error_body = json.loads(error_response)
|
| + error_details = ['%s: %s' % (detail['message'], detail['debug_info'])
|
| + for detail in error_body['error']['errors']]
|
| + except (ValueError, TypeError, KeyError):
|
| + pass
|
| + if error_details:
|
| + error_details_str = ', '.join(error_details)
|
| + error_message = ('HTTP %s (%s) error when communicating with URL: %s. '
|
| + 'Details: %s' % (http_error.code, http_error.reason,
|
| + http_error.filename, error_details_str))
|
| + else:
|
| + error_message = ('HTTP %s (%s) error when communicating with URL: %s. '
|
| + 'Response: %s' % (http_error.code, http_error.reason,
|
| + http_error.filename,
|
| + error_response))
|
| + super(ServerRequestException, self).__init__(error_message)
|
| +
|
| +
|
| +class _EndpointsParser(argparse.ArgumentParser):
|
| + """Create a subclass of argparse.ArgumentParser for Endpoints."""
|
| +
|
| + def error(self, message):
|
| + """Override superclass to support customized error message.
|
| +
|
| + Error message needs to be rewritten in order to display visible commands
|
| + only, when invalid command is called by user. Otherwise, hidden commands
|
| + will be displayed in stderr, which is not expected.
|
| +
|
| + Refer the following argparse python documentation for detailed method
|
| + information:
|
| + http://docs.python.org/2/library/argparse.html#exiting-methods
|
| +
|
| + Args:
|
| + message: original error message that will be printed to stderr
|
| + """
|
| + # subcommands_quoted is the same as subcommands, except each value is
|
| + # surrounded with double quotes. This is done to match the standard
|
| + # output of the ArgumentParser, while hiding commands we don't want users
|
| + # to use, as they are no longer documented and only here for legacy use.
|
| + subcommands_quoted = ', '.join(
|
| + [repr(command) for command in _VISIBLE_COMMANDS])
|
| + subcommands = ', '.join(_VISIBLE_COMMANDS)
|
| + message = re.sub(
|
| + r'(argument {%s}: invalid choice: .*) \(choose from (.*)\)$'
|
| + % subcommands, r'\1 (choose from %s)' % subcommands_quoted, message)
|
| + super(_EndpointsParser, self).error(message)
|
| +
|
| +
|
| +def _WriteFile(output_path, name, content):
|
| + """Write given content to a file in a given directory.
|
| +
|
| + Args:
|
| + output_path: The directory to store the file in.
|
| + name: The name of the file to store the content in.
|
| + content: The content to write to the file.close
|
| +
|
| + Returns:
|
| + The full path to the written file.
|
| + """
|
| + path = os.path.join(output_path, name)
|
| + with open(path, 'wb') as f:
|
| + f.write(content)
|
| + return path
|
| +
|
| +
|
| +def GenApiConfig(service_class_names, config_string_generator=None,
|
| + hostname=None, application_path=None):
|
| + """Write an API configuration for endpoints annotated ProtoRPC services.
|
| +
|
| + Args:
|
| + service_class_names: A list of fully qualified ProtoRPC service classes.
|
| + config_string_generator: A generator object that produces API config strings
|
| + using its pretty_print_config_to_json method.
|
| + hostname: A string hostname which will be used as the default version
|
| + hostname. If no hostname is specificied in the @endpoints.api decorator,
|
| + this value is the fallback.
|
| + application_path: A string with the path to the AppEngine application.
|
| +
|
| + Raises:
|
| + TypeError: If any service classes don't inherit from remote.Service.
|
| + messages.DefinitionNotFoundError: If a service can't be found.
|
| +
|
| + Returns:
|
| + A map from service names to a string containing the API configuration of the
|
| + service in JSON format.
|
| + """
|
| + # First, gather together all the different APIs implemented by these
|
| + # classes. There may be fewer APIs than service classes. Each API is
|
| + # uniquely identified by (name, version). Order needs to be preserved here,
|
| + # so APIs that were listed first are returned first.
|
| + api_service_map = collections.OrderedDict()
|
| + for service_class_name in service_class_names:
|
| + module_name, base_service_class_name = service_class_name.rsplit('.', 1)
|
| + module = __import__(module_name, fromlist=base_service_class_name)
|
| + service = getattr(module, base_service_class_name)
|
| + if not isinstance(service, type) or not issubclass(service, remote.Service):
|
| + raise TypeError('%s is not a ProtoRPC service' % service_class_name)
|
| +
|
| + services = api_service_map.setdefault(
|
| + (service.api_info.name, service.api_info.version), [])
|
| + services.append(service)
|
| +
|
| + # If hostname isn't specified in the API or on the command line, we'll
|
| + # try to build it from information in app.yaml.
|
| + app_yaml_hostname = _GetAppYamlHostname(application_path)
|
| +
|
| + service_map = collections.OrderedDict()
|
| + config_string_generator = (
|
| + config_string_generator or api_config.ApiConfigGenerator())
|
| + for api_info, services in api_service_map.iteritems():
|
| + assert services, 'An API must have at least one ProtoRPC service'
|
| + # Only override hostname if None. Hostname will be the same for all
|
| + # services within an API, since it's stored in common info.
|
| + hostname = services[0].api_info.hostname or hostname or app_yaml_hostname
|
| +
|
| + # Map each API by name-version.
|
| + service_map['%s-%s' % api_info] = (
|
| + config_string_generator.pretty_print_config_to_json(
|
| + services, hostname=hostname))
|
| +
|
| + return service_map
|
| +
|
| +
|
| +def _GetAppYamlHostname(application_path, open_func=open):
|
| + """Build the hostname for this app based on the name in app.yaml.
|
| +
|
| + Args:
|
| + application_path: A string with the path to the AppEngine application. This
|
| + should be the directory containing the app.yaml file.
|
| + open_func: Function to call to open a file. Used to override the default
|
| + open function in unit tests.
|
| +
|
| + Returns:
|
| + A hostname, usually in the form of "myapp.appspot.com", based on the
|
| + application name in the app.yaml file. If the file can't be found or
|
| + there's a problem building the name, this will return None.
|
| + """
|
| + try:
|
| + app_yaml_file = open_func(os.path.join(application_path or '.', 'app.yaml'))
|
| + config = yaml.safe_load(app_yaml_file.read())
|
| + except IOError:
|
| + # Couldn't open/read app.yaml.
|
| + return None
|
| +
|
| + application = config.get('application')
|
| + if not application:
|
| + return None
|
| +
|
| + if ':' in application:
|
| + # Don't try to deal with alternate domains.
|
| + return None
|
| +
|
| + # If there's a prefix ending in a '~', strip it.
|
| + tilde_index = application.rfind('~')
|
| + if tilde_index >= 0:
|
| + application = application[tilde_index + 1:]
|
| + if not application:
|
| + return None
|
| +
|
| + return '%s.appspot.com' % application
|
| +
|
| +
|
| +def _FetchDiscoveryDoc(config, doc_format):
|
| + """Fetch discovery documents generated from a cloud service.
|
| +
|
| + Args:
|
| + config: An API config.
|
| + doc_format: The requested format for the discovery doc. (rest|rpc)
|
| +
|
| + Raises:
|
| + ServerRequestException: If fetching the generated discovery doc fails.
|
| +
|
| + Returns:
|
| + A list of discovery doc strings.
|
| + """
|
| + body = json.dumps({'config': config}, indent=2, sort_keys=True)
|
| + request = urllib2.Request(DISCOVERY_DOC_BASE + doc_format, body)
|
| + request.add_header('content-type', 'application/json')
|
| +
|
| + try:
|
| + with contextlib.closing(urllib2.urlopen(request)) as response:
|
| + return response.read()
|
| + except urllib2.HTTPError, error:
|
| + raise ServerRequestException(error)
|
| +
|
| +
|
| +def _GenDiscoveryDoc(service_class_names, doc_format,
|
| + output_path, hostname=None,
|
| + application_path=None):
|
| + """Write discovery documents generated from a cloud service to file.
|
| +
|
| + Args:
|
| + service_class_names: A list of fully qualified ProtoRPC service names.
|
| + doc_format: The requested format for the discovery doc. (rest|rpc)
|
| + output_path: The directory to output the discovery docs to.
|
| + hostname: A string hostname which will be used as the default version
|
| + hostname. If no hostname is specificied in the @endpoints.api decorator,
|
| + this value is the fallback. Defaults to None.
|
| + application_path: A string containing the path to the AppEngine app.
|
| +
|
| + Raises:
|
| + ServerRequestException: If fetching the generated discovery doc fails.
|
| +
|
| + Returns:
|
| + A list of discovery doc filenames.
|
| + """
|
| + output_files = []
|
| + service_configs = GenApiConfig(service_class_names, hostname=hostname,
|
| + application_path=application_path)
|
| + for api_name_version, config in service_configs.iteritems():
|
| + discovery_doc = _FetchDiscoveryDoc(config, doc_format)
|
| + discovery_name = api_name_version + '.discovery'
|
| + output_files.append(_WriteFile(output_path, discovery_name, discovery_doc))
|
| +
|
| + return output_files
|
| +
|
| +
|
| +def _GenOpenApiSpec(service_class_names, output_path, hostname=None,
|
| + application_path=None):
|
| + """Write discovery documents generated from a cloud service to file.
|
| +
|
| + Args:
|
| + service_class_names: A list of fully qualified ProtoRPC service names.
|
| + output_path: The directory to which to output the OpenAPI specs.
|
| + hostname: A string hostname which will be used as the default version
|
| + hostname. If no hostname is specified in the @endpoints.api decorator,
|
| + this value is the fallback. Defaults to None.
|
| + application_path: A string containing the path to the AppEngine app.
|
| +
|
| + Returns:
|
| + A list of OpenAPI spec filenames.
|
| + """
|
| + output_files = []
|
| + service_configs = GenApiConfig(
|
| + service_class_names, hostname=hostname,
|
| + config_string_generator=openapi_generator.OpenApiGenerator(),
|
| + application_path=application_path)
|
| + for api_name_version, config in service_configs.iteritems():
|
| + openapi_name = api_name_version.replace('-', '') + 'openapi.json'
|
| + output_files.append(_WriteFile(output_path, openapi_name, config))
|
| +
|
| + return output_files
|
| +
|
| +
|
| +def _GenClientLib(discovery_path, language, output_path, build_system):
|
| + """Write a client library from a discovery doc, using a cloud service to file.
|
| +
|
| + Args:
|
| + discovery_path: Path to the discovery doc used to generate the client
|
| + library.
|
| + language: The client library language to generate. (java)
|
| + output_path: The directory to output the client library zip to.
|
| + build_system: The target build system for the client library language.
|
| +
|
| + Raises:
|
| + IOError: If reading the discovery doc fails.
|
| + ServerRequestException: If fetching the generated client library fails.
|
| +
|
| + Returns:
|
| + The path to the zipped client library.
|
| + """
|
| + with open(discovery_path) as f:
|
| + discovery_doc = f.read()
|
| +
|
| + client_name = re.sub(r'\.discovery$', '.zip',
|
| + os.path.basename(discovery_path))
|
| +
|
| + return _GenClientLibFromContents(discovery_doc, language, output_path,
|
| + build_system, client_name)
|
| +
|
| +
|
| +def _GenClientLibFromContents(discovery_doc, language, output_path,
|
| + build_system, client_name):
|
| + """Write a client library from a discovery doc, using a cloud service to file.
|
| +
|
| + Args:
|
| + discovery_doc: A string, the contents of the discovery doc used to
|
| + generate the client library.
|
| + language: A string, the client library language to generate. (java)
|
| + output_path: A string, the directory to output the client library zip to.
|
| + build_system: A string, the target build system for the client language.
|
| + client_name: A string, the filename used to save the client lib.
|
| +
|
| + Raises:
|
| + IOError: If reading the discovery doc fails.
|
| + ServerRequestException: If fetching the generated client library fails.
|
| +
|
| + Returns:
|
| + The path to the zipped client library.
|
| + """
|
| +
|
| + body = urllib.urlencode({'lang': language, 'content': discovery_doc,
|
| + 'layout': build_system})
|
| + request = urllib2.Request(CLIENT_LIBRARY_BASE, body)
|
| + try:
|
| + with contextlib.closing(urllib2.urlopen(request)) as response:
|
| + content = response.read()
|
| + return _WriteFile(output_path, client_name, content)
|
| + except urllib2.HTTPError, error:
|
| + raise ServerRequestException(error)
|
| +
|
| +
|
| +def _GetClientLib(service_class_names, language, output_path, build_system,
|
| + hostname=None, application_path=None):
|
| + """Fetch client libraries from a cloud service.
|
| +
|
| + Args:
|
| + service_class_names: A list of fully qualified ProtoRPC service names.
|
| + language: The client library language to generate. (java)
|
| + output_path: The directory to output the discovery docs to.
|
| + build_system: The target build system for the client library language.
|
| + hostname: A string hostname which will be used as the default version
|
| + hostname. If no hostname is specificied in the @endpoints.api decorator,
|
| + this value is the fallback. Defaults to None.
|
| + application_path: A string containing the path to the AppEngine app.
|
| +
|
| + Returns:
|
| + A list of paths to client libraries.
|
| + """
|
| + client_libs = []
|
| + service_configs = GenApiConfig(service_class_names, hostname=hostname,
|
| + application_path=application_path)
|
| + for api_name_version, config in service_configs.iteritems():
|
| + discovery_doc = _FetchDiscoveryDoc(config, 'rest')
|
| + client_name = api_name_version + '.zip'
|
| + client_libs.append(
|
| + _GenClientLibFromContents(discovery_doc, language, output_path,
|
| + build_system, client_name))
|
| + return client_libs
|
| +
|
| +
|
| +def _GenApiConfigCallback(args, api_func=GenApiConfig):
|
| + """Generate an api file.
|
| +
|
| + Args:
|
| + args: An argparse.Namespace object to extract parameters from.
|
| + api_func: A function that generates and returns an API configuration
|
| + for a list of services.
|
| + """
|
| + service_configs = api_func(args.service,
|
| + hostname=args.hostname,
|
| + application_path=args.application)
|
| +
|
| + for api_name_version, config in service_configs.iteritems():
|
| + _WriteFile(args.output, api_name_version + '.api', config)
|
| +
|
| +
|
| +def _GetClientLibCallback(args, client_func=_GetClientLib):
|
| + """Generate discovery docs and client libraries to files.
|
| +
|
| + Args:
|
| + args: An argparse.Namespace object to extract parameters from.
|
| + client_func: A function that generates client libraries and stores them to
|
| + files, accepting a list of service names, a client library language,
|
| + an output directory, a build system for the client library language, and
|
| + a hostname.
|
| + """
|
| + client_paths = client_func(
|
| + args.service, args.language, args.output, args.build_system,
|
| + hostname=args.hostname, application_path=args.application)
|
| +
|
| + for client_path in client_paths:
|
| + print 'API client library written to %s' % client_path
|
| +
|
| +
|
| +def _GenDiscoveryDocCallback(args, discovery_func=_GenDiscoveryDoc):
|
| + """Generate discovery docs to files.
|
| +
|
| + Args:
|
| + args: An argparse.Namespace object to extract parameters from
|
| + discovery_func: A function that generates discovery docs and stores them to
|
| + files, accepting a list of service names, a discovery doc format, and an
|
| + output directory.
|
| + """
|
| + discovery_paths = discovery_func(args.service, args.format,
|
| + args.output, hostname=args.hostname,
|
| + application_path=args.application)
|
| + for discovery_path in discovery_paths:
|
| + print 'API discovery document written to %s' % discovery_path
|
| +
|
| +
|
| +def _GenOpenApiSpecCallback(args, openapi_func=_GenOpenApiSpec):
|
| + """Generate OpenAPI (Swagger) specs to files.
|
| +
|
| + Args:
|
| + args: An argparse.Namespace object to extract parameters from
|
| + openapi_func: A function that generates OpenAPI specs and stores them to
|
| + files, accepting a list of service names and an output directory.
|
| + """
|
| + openapi_paths = openapi_func(args.service, args.output,
|
| + hostname=args.hostname,
|
| + application_path=args.application)
|
| + for openapi_path in openapi_paths:
|
| + print 'OpenAPI spec written to %s' % openapi_path
|
| +
|
| +
|
| +def _GenClientLibCallback(args, client_func=_GenClientLib):
|
| + """Generate a client library to file.
|
| +
|
| + Args:
|
| + args: An argparse.Namespace object to extract parameters from
|
| + client_func: A function that generates client libraries and stores them to
|
| + files, accepting a path to a discovery doc, a client library language, an
|
| + output directory, and a build system for the client library language.
|
| + """
|
| + client_path = client_func(args.discovery_doc[0], args.language, args.output,
|
| + args.build_system)
|
| + print 'API client library written to %s' % client_path
|
| +
|
| +
|
| +def MakeParser(prog):
|
| + """Create an argument parser.
|
| +
|
| + Args:
|
| + prog: The name of the program to use when outputting help text.
|
| +
|
| + Returns:
|
| + An argparse.ArgumentParser built to specification.
|
| + """
|
| +
|
| + def AddStandardOptions(parser, *args):
|
| + """Add common endpoints options to a parser.
|
| +
|
| + Args:
|
| + parser: The parser to add options to.
|
| + *args: A list of option names to add. Possible names are: application,
|
| + format, output, language, service, and discovery_doc.
|
| + """
|
| + if 'application' in args:
|
| + parser.add_argument('-a', '--application', default='.',
|
| + help='The path to the Python App Engine App')
|
| + if 'format' in args:
|
| + parser.add_argument('-f', '--format', default='rest',
|
| + choices=['rest', 'rpc'],
|
| + help='The requested API protocol type')
|
| + if 'hostname' in args:
|
| + help_text = ('Default application hostname, if none is specified '
|
| + 'for API service.')
|
| + parser.add_argument('--hostname', help=help_text)
|
| + if 'output' in args:
|
| + parser.add_argument('-o', '--output', default='.',
|
| + help='The directory to store output files')
|
| + if 'language' in args:
|
| + parser.add_argument('language',
|
| + help='The target output programming language')
|
| + if 'service' in args:
|
| + parser.add_argument('service', nargs='+',
|
| + help='Fully qualified service class name')
|
| + if 'discovery_doc' in args:
|
| + parser.add_argument('discovery_doc', nargs=1,
|
| + help='Path to the discovery document')
|
| + if 'build_system' in args:
|
| + parser.add_argument('-bs', '--build_system', default='default',
|
| + help='The target build system')
|
| +
|
| + parser = _EndpointsParser(prog=prog)
|
| + subparsers = parser.add_subparsers(
|
| + title='subcommands', metavar='{%s}' % ', '.join(_VISIBLE_COMMANDS))
|
| +
|
| + get_client_lib = subparsers.add_parser(
|
| + 'get_client_lib', help=('Generates discovery documents and client '
|
| + 'libraries from service classes'))
|
| + get_client_lib.set_defaults(callback=_GetClientLibCallback)
|
| + AddStandardOptions(get_client_lib, 'application', 'hostname', 'output',
|
| + 'language', 'service', 'build_system')
|
| +
|
| + get_discovery_doc = subparsers.add_parser(
|
| + 'get_discovery_doc',
|
| + help='Generates discovery documents from service classes')
|
| + get_discovery_doc.set_defaults(callback=_GenDiscoveryDocCallback)
|
| + AddStandardOptions(get_discovery_doc, 'application', 'format', 'hostname',
|
| + 'output', 'service')
|
| +
|
| + get_openapi_spec = subparsers.add_parser(
|
| + 'get_openapi_spec',
|
| + help='Generates OpenAPI (Swagger) specs from service classes')
|
| + get_openapi_spec.set_defaults(callback=_GenOpenApiSpecCallback)
|
| + AddStandardOptions(get_openapi_spec, 'application', 'hostname', 'output',
|
| + 'service')
|
| +
|
| + # Create an alias for get_openapi_spec called get_swagger_spec to support
|
| + # the old-style naming. This won't be a visible command, but it will still
|
| + # function to support legacy scripts.
|
| + get_swagger_spec = subparsers.add_parser(
|
| + 'get_swagger_spec',
|
| + help='Generates OpenAPI (Swagger) specs from service classes')
|
| + get_swagger_spec.set_defaults(callback=_GenOpenApiSpecCallback)
|
| + AddStandardOptions(get_swagger_spec, 'application', 'hostname', 'output',
|
| + 'service')
|
| +
|
| + # By removing the help attribute, the following three actions won't be
|
| + # displayed in usage message
|
| + gen_api_config = subparsers.add_parser('gen_api_config')
|
| + gen_api_config.set_defaults(callback=_GenApiConfigCallback)
|
| + AddStandardOptions(gen_api_config, 'application', 'hostname', 'output',
|
| + 'service')
|
| +
|
| + gen_discovery_doc = subparsers.add_parser('gen_discovery_doc')
|
| + gen_discovery_doc.set_defaults(callback=_GenDiscoveryDocCallback)
|
| + AddStandardOptions(gen_discovery_doc, 'application', 'format', 'hostname',
|
| + 'output', 'service')
|
| +
|
| + gen_client_lib = subparsers.add_parser('gen_client_lib')
|
| + gen_client_lib.set_defaults(callback=_GenClientLibCallback)
|
| + AddStandardOptions(gen_client_lib, 'output', 'language', 'discovery_doc',
|
| + 'build_system')
|
| +
|
| + return parser
|
| +
|
| +
|
| +def _SetupStubs():
|
| + tb = testbed.Testbed()
|
| + tb.setup_env(CURRENT_VERSION_ID='1.0')
|
| + tb.activate()
|
| + for k, v in testbed.INIT_STUB_METHOD_NAMES.iteritems():
|
| + # The old stub initialization code didn't support the image service at all
|
| + # so we just ignore it here.
|
| + if k != 'images':
|
| + getattr(tb, v)()
|
| +
|
| +
|
| +def main(argv):
|
| + _SetupStubs()
|
| +
|
| + parser = MakeParser(argv[0])
|
| + args = parser.parse_args(argv[1:])
|
| +
|
| + # Handle the common "application" argument here, since most of the handlers
|
| + # use this.
|
| + application_path = getattr(args, 'application', None)
|
| + if application_path is not None:
|
| + sys.path.insert(0, os.path.abspath(application_path))
|
| +
|
| + args.callback(args)
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + main(sys.argv)
|
|
|