Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Unified Diff: third_party/gsutil/third_party/protorpc/gen_protorpc.py

Issue 1377933002: [catapult] - Copy Telemetry's gsutilz over to third_party. (Closed) Base URL: https://github.com/catapult-project/catapult.git@master
Patch Set: Rename to gsutil. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/gsutil/third_party/protorpc/gen_protorpc.py
diff --git a/third_party/gsutil/third_party/protorpc/gen_protorpc.py b/third_party/gsutil/third_party/protorpc/gen_protorpc.py
new file mode 100755
index 0000000000000000000000000000000000000000..101a70ff12f29bb6ecf5f0b6e0f8a7d5c5c04728
--- /dev/null
+++ b/third_party/gsutil/third_party/protorpc/gen_protorpc.py
@@ -0,0 +1,300 @@
+#!/usr/bin/env python
+#
+# Copyright 2011 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.
+#
+
+"""Command line tool for generating ProtoRPC definitions from descriptors."""
+
+import errno
+import logging
+import optparse
+import os
+import sys
+
+from protorpc import descriptor
+from protorpc import generate_python
+from protorpc import protobuf
+from protorpc import registry
+from protorpc import transport
+from protorpc import util
+
+EXCLUDED_PACKAGES = frozenset(['protorpc.registry',
+ 'protorpc.messages',
+ 'protorpc.descriptor',
+ 'protorpc.message_types',
+ ])
+
+commands = {}
+
+
+def usage():
+ """Print usage help and exit with an error code."""
+ parser.print_help()
+ sys.exit(2)
+
+
+def fatal_error(message):
+ """Print fatal error messages exit with an error code.
+
+ Args:
+ message: Message to print to stderr before exit.
+ """
+ sys.stderr.write(message)
+ sys.exit(1)
+
+
+def open_input_file(filename):
+ """Open file for reading.
+
+ Args:
+ filename: Name of input file to open or None to open stdin.
+
+ Returns:
+ Opened file if string provided, stdin if filename is None.
+ """
+ # TODO(rafek): Detect missing or invalid files, generating user friendly
+ # error messages.
+ if filename is None:
+ return sys.stdin
+ else:
+ try:
+ return open(filename, 'rb')
+ except IOError, err:
+ fatal_error(str(err))
+
+
+@util.positional(1)
+def generate_file_descriptor(dest_dir, file_descriptor, force_overwrite):
+ """Generate a single file descriptor to destination directory.
+
+ Will generate a single Python file from a file descriptor under dest_dir.
+ The sub-directory where the file is generated is determined by the package
+ name of descriptor.
+
+ Descriptors without package names will not be generated.
+
+ Descriptors that are part of the ProtoRPC distribution will not be generated.
+
+ Args:
+ dest_dir: Directory under which to generate files.
+ file_descriptor: FileDescriptor instance to generate source code from.
+ force_overwrite: If True, existing files will be overwritten.
+ """
+ package = file_descriptor.package
+ if not package:
+ # TODO(rafek): Option to cause an error on this condition.
+ logging.warn('Will not generate descriptor without package name')
+ return
+
+ if package in EXCLUDED_PACKAGES:
+ logging.warn('Will not generate main ProtoRPC class %s' % package)
+ return
+
+ package_path = package.split('.')
+ directory = package_path[:-1]
+ package_file_name = package_path[-1]
+ directory_name = os.path.join(dest_dir, *directory)
+ output_file_name = os.path.join(directory_name,
+ '%s.py' % (package_file_name,))
+
+ try:
+ os.makedirs(directory_name)
+ except OSError, err:
+ if err.errno != errno.EEXIST:
+ raise
+
+ if not force_overwrite and os.path.exists(output_file_name):
+ logging.warn('Not overwriting %s with package %s',
+ output_file_name, package)
+ return
+
+ output_file = open(output_file_name, 'w')
+
+ logging.info('Writing package %s to %s',
+ file_descriptor.package, output_file_name)
+ generate_python.format_python_file(file_descriptor, output_file)
+
+
+@util.positional(1)
+def command(name, required=(), optional=()):
+ """Decorator used for declaring commands used on command line.
+
+ Each command of this tool can have any number of sequential required
+ parameters and optional parameters. The required and optional parameters
+ will be displayed in the command usage. Arguments passed in to the command
+ are checked to ensure they have at least the required parameters and not
+ too many parameters beyond the optional ones. When there are not enough
+ or too few parameters the usage message is generated and the program exits
+ with an error code.
+
+ Functions decorated thus are added to commands by their name.
+
+ Resulting decorated functions will have required and optional attributes
+ assigned to them so that appear in the usage message.
+
+ Args:
+ name: Name of command that will follow the program name on the command line.
+ required: List of required parameter names as displayed in the usage
+ message.
+ optional: List of optional parameter names as displayed in the usage
+ message.
+ """
+ def check_params_decorator(function):
+ def check_params_wrapper(options, *args):
+ if not (len(required) <= len(args) <= len(required) + len(optional)):
+ sys.stderr.write("Incorrect usage for command '%s'\n\n" % name)
+ usage()
+ function(options, *args)
+ check_params_wrapper.required = required
+ check_params_wrapper.optional = optional
+ commands[name] = check_params_wrapper
+ return check_params_wrapper
+ return check_params_decorator
+
+
+@command('file', optional=['input-filename', 'output-filename'])
+def file_command(options, input_filename=None, output_filename=None):
+ """Generate a single descriptor file to Python.
+
+ Args:
+ options: Parsed command line options.
+ input_filename: File to read protobuf FileDescriptor from. If None
+ will read from stdin.
+ output_filename: File to write Python source code to. If None will
+ generate to stdout.
+ """
+ with open_input_file(input_filename) as input_file:
+ descriptor_content = input_file.read()
+
+ if output_filename:
+ output_file = open(output_filename, 'w')
+ else:
+ output_file = sys.stdout
+
+ file_descriptor = protobuf.decode_message(descriptor.FileDescriptor,
+ descriptor_content)
+ generate_python.format_python_file(file_descriptor, output_file)
+
+
+@command('fileset', optional=['filename'])
+def fileset_command(options, input_filename=None):
+ """Generate source directory structure from FileSet.
+
+ Args:
+ options: Parsed command line options.
+ input_filename: File to read protobuf FileSet from. If None will read from
+ stdin.
+ """
+ with open_input_file(input_filename) as input_file:
+ descriptor_content = input_file.read()
+
+ dest_dir = os.path.expanduser(options.dest_dir)
+
+ if not os.path.isdir(dest_dir) and os.path.exists(dest_dir):
+ fatal_error("Destination '%s' is not a directory" % dest_dir)
+
+ file_set = protobuf.decode_message(descriptor.FileSet,
+ descriptor_content)
+
+ for file_descriptor in file_set.files:
+ generate_file_descriptor(dest_dir, file_descriptor=file_descriptor,
+ force_overwrite=options.force)
+
+
+@command('registry',
+ required=['host'],
+ optional=['service-name', 'registry-path'])
+def registry_command(options,
+ host,
+ service_name=None,
+ registry_path='/protorpc'):
+ """Generate source directory structure from remote registry service.
+
+ Args:
+ options: Parsed command line options.
+ host: Web service host where registry service is located. May include
+ port.
+ service_name: Name of specific service to read. Will generate only Python
+ files that service is dependent on. If None, will generate source code
+ for all services known by the registry.
+ registry_path: Path to find registry if not the default 'protorpc'.
+ """
+ dest_dir = os.path.expanduser(options.dest_dir)
+
+ url = 'http://%s%s' % (host, registry_path)
+ reg = registry.RegistryService.Stub(transport.HttpTransport(url))
+
+ if service_name is None:
+ service_names = [service.name for service in reg.services().services]
+ else:
+ service_names = [service_name]
+
+ file_set = reg.get_file_set(names=service_names).file_set
+
+ for file_descriptor in file_set.files:
+ generate_file_descriptor(dest_dir, file_descriptor=file_descriptor,
+ force_overwrite=options.force)
+
+
+def make_opt_parser():
+ """Create options parser with automatically generated command help.
+
+ Will iterate over all functions in commands and generate an appropriate
+ usage message for them with all their required and optional parameters.
+ """
+ command_descriptions = []
+ for name in sorted(commands.iterkeys()):
+ command = commands[name]
+ params = ' '.join(['<%s>' % param for param in command.required] +
+ ['[<%s>]' % param for param in command.optional])
+ command_descriptions.append('%%prog [options] %s %s' % (name, params))
+ command_usage = 'usage: %s\n' % '\n '.join(command_descriptions)
+
+ parser = optparse.OptionParser(usage=command_usage)
+ parser.add_option('-d', '--dest_dir',
+ dest='dest_dir',
+ default=os.getcwd(),
+ help='Write generated files to DIR',
+ metavar='DIR')
+ parser.add_option('-f', '--force',
+ action='store_true',
+ dest='force',
+ default=False,
+ help='Force overwrite of existing files')
+ return parser
+
+parser = make_opt_parser()
+
+
+def main():
+ # TODO(rafek): Customize verbosity.
+ logging.basicConfig(level=logging.INFO)
+ options, positional = parser.parse_args()
+
+ if not positional:
+ usage()
+
+ command_name = positional[0]
+ command = commands.get(command_name)
+ if not command:
+ sys.stderr.write("Unknown command '%s'\n\n" % command_name)
+ usage()
+ parameters = positional[1:]
+
+ command(options, *parameters)
+
+
+if __name__ == '__main__':
+ main()
« no previous file with comments | « third_party/gsutil/third_party/protorpc/ez_setup.py ('k') | third_party/gsutil/third_party/protorpc/protorpc/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698