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 as 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)
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)
def DoPythonTest(self, file_descriptor): """Execute python test based on a FileDescriptor object. The full test of the Python code generation is to generate a Python source code file, import the module and regenerate the FileDescriptor from it. If the generated FileDescriptor is the same as the original, it means that the generated source code correctly implements the actual FileDescriptor. """ file_name = os.path.join( self.temp_dir, '%s.py' % (file_descriptor.package or 'blank', )) source_file = open(file_name, 'wt') try: generate_python.format_python_file(file_descriptor, source_file) finally: source_file.close() module_to_import = file_descriptor.package or 'blank' module = __import__(module_to_import) if not file_descriptor.package: self.assertFalse(hasattr(module, 'package')) module.package = '' # Create package name so that comparison will work. reloaded_descriptor = descriptor.describe_file(module) # Need to sort both message_types fields because document order is never # Ensured. # TODO(rafek): Ensure document order. if reloaded_descriptor.message_types: reloaded_descriptor.message_types = sorted( reloaded_descriptor.message_types, key=lambda v: v.name) if file_descriptor.message_types: file_descriptor.message_types = sorted( file_descriptor.message_types, key=lambda v: v.name) self.assertEquals(file_descriptor, reloaded_descriptor)
def DoPythonTest(self, file_descriptor): """Execute python test based on a FileDescriptor object. The full test of the Python code generation is to generate a Python source code file, import the module and regenerate the FileDescriptor from it. If the generated FileDescriptor is the same as the original, it means that the generated source code correctly implements the actual FileDescriptor. """ file_name = os.path.join(self.temp_dir, '%s.py' % (file_descriptor.package or 'blank',)) source_file = open(file_name, 'wt') try: generate_python.format_python_file(file_descriptor, source_file) finally: source_file.close() module_to_import = file_descriptor.package or 'blank' module = __import__(module_to_import) if not file_descriptor.package: self.assertFalse(hasattr(module, 'package')) module.package = '' # Create package name so that comparison will work. reloaded_descriptor = descriptor.describe_file(module) # Need to sort both message_types fields because document order is never # Ensured. # TODO(rafek): Ensure document order. if reloaded_descriptor.message_types: reloaded_descriptor.message_types = sorted( reloaded_descriptor.message_types, key=lambda v: v.name) if file_descriptor.message_types: file_descriptor.message_types = sorted( file_descriptor.message_types, key=lambda v: v.name) self.assertEquals(file_descriptor, reloaded_descriptor)
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.
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 output_file = open(output_file_name, 'w') logging.info('Writing package %s to %s', file_descriptor.package, output_file_name) # TODO(rafek): Option to prevent overwriting. 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.