def AddDescriptorFromSchema(self, schema_name, schema):
     """Add a new MessageDescriptor named schema_name based on schema."""
     # TODO(craigcitro): Is schema_name redundant?
     if self.__GetDescriptor(schema_name):
         return
     if schema.get('enum'):
         self.__DeclareEnum(schema_name, schema)
         return
     if schema.get('type') == 'any':
         self.__DeclareMessageAlias(schema, 'extra_types.JsonValue')
         return
     if schema.get('type') != 'object':
         raise ValueError('Cannot create message descriptors for type %s',
                          schema.get('type'))
     message = extended_descriptor.ExtendedMessageDescriptor()
     message.name = self.__names.ClassName(schema['id'])
     message.description = util.CleanDescription(
         schema.get('description', 'A %s object.' % message.name))
     self.__DeclareDescriptor(message.name)
     with self.__DescriptorEnv(message):
         properties = schema.get('properties', {})
         for index, (name, attrs) in enumerate(sorted(properties.items())):
             field = self.__FieldDescriptorFromProperties(
                 name, index + 1, attrs)
             message.fields.append(field)
             if field.name != name:
                 message.field_mappings.append(
                     extended_descriptor.ExtendedMessageDescriptor.
                     JsonFieldMapping(python_name=field.name,
                                      json_name=name))
                 self.__AddImport('from %s import encoding' %
                                  self.__base_files_package)
         if 'additionalProperties' in schema:
             self.__AddAdditionalProperties(message, schema, properties)
     self.__RegisterDescriptor(message)
 def __init__(self, client_info, names, description, root_package_dir,
              base_files_package):
     self.__names = names
     self.__client_info = client_info
     self.__package = client_info.package
     self.__description = util.CleanDescription(description)
     self.__root_package_dir = root_package_dir
     self.__base_files_package = base_files_package
     self.__file_descriptor = extended_descriptor.ExtendedFileDescriptor(
         package=self.__package, description=self.__description)
     # Add required imports
     self.__file_descriptor.additional_imports = [
         'from protorpc import messages',
     ]
     # Map from scoped names (i.e. Foo.Bar) to MessageDescriptors.
     self.__message_registry = collections.OrderedDict()
     # A set of types that we're currently adding (for cycle detection).
     self.__nascent_types = set()
     # A set of types for which we've seen a reference but no
     # definition; if this set is nonempty, validation fails.
     self.__unknown_types = set()
     # Used for tracking paths during message creation
     self.__current_path = []
     # Where to register created messages
     self.__current_env = self.__file_descriptor
 def __FieldDescriptorFromProperties(self, name, index, attrs):
     """Create a field descriptor for these attrs."""
     field = descriptor.FieldDescriptor()
     field.name = self.__names.CleanName(name)
     field.number = index
     field.label = self.__ComputeLabel(attrs)
     new_type_name_hint = self.__names.ClassName(
         '%sValue' % self.__names.ClassName(name))
     type_info = self.__GetTypeInfo(attrs, new_type_name_hint)
     field.type_name = type_info.type_name
     field.variant = type_info.variant
     if 'default' in attrs:
         # TODO(craigcitro): Correctly handle non-primitive default values.
         default = attrs['default']
         if field.type_name != 'string' and field.variant != messages.Variant.ENUM:
             default = str(json.loads(default))
         if field.variant == messages.Variant.ENUM:
             default = self.__names.NormalizeEnumName(default)
         field.default_value = default
     extended_field = extended_descriptor.ExtendedFieldDescriptor()
     extended_field.name = field.name
     extended_field.description = util.CleanDescription(
         attrs.get('description', 'A %s attribute.' % field.type_name))
     extended_field.field_descriptor = field
     return extended_field
Beispiel #4
0
 def __PrintDocstring(self, printer, method_info, method_name, name):
     """Print a docstring for a service method."""
     if method_info.description:
         description = util.CleanDescription(method_info.description)
         first_line, newline, remaining = method_info.description.partition(
             '\n')
         if not first_line.endswith('.'):
             first_line = '%s.' % first_line
         description = '%s%s%s' % (first_line, newline, remaining)
     else:
         description = '%s method for the %s service.' % (method_name, name)
     with printer.CommentContext():
         printer('"""%s' % description)
     printer()
     printer('Args:')
     printer('  request: (%s) input message', method_info.request_type_name)
     printer('  global_params: (StandardQueryParameters, default: None) '
             'global arguments')
     if method_info.upload_config:
         printer('  upload: (Upload, default: None) If present, upload')
         printer('      this stream with the request.')
     if method_info.supports_download:
         printer(
             '  download: (Download, default: None) If present, download')
         printer('      data from the request via this stream.')
     printer('Returns:')
     printer('  (%s) The response message.', method_info.response_type_name)
     printer('"""')
 def __DeclareEnum(self, enum_name, attrs):
     description = util.CleanDescription(attrs.get('description', ''))
     enum_values = attrs['enum']
     enum_descriptions = attrs.get('enumDescriptions',
                                   [''] * len(enum_values))
     self.AddEnumDescriptor(enum_name, description, enum_values,
                            enum_descriptions)
     self.__AddIfUnknown(enum_name)
     return TypeInfo(type_name=enum_name, variant=messages.Variant.ENUM)
 def AddEnumDescriptor(self, name, description, enum_values,
                       enum_descriptions):
     """Add a new EnumDescriptor named name with the given enum values."""
     message = extended_descriptor.ExtendedEnumDescriptor()
     message.name = self.__names.ClassName(name)
     message.description = util.CleanDescription(description)
     self.__DeclareDescriptor(message.name)
     for index, (enum_name, enum_description) in enumerate(
             zip(enum_values, enum_descriptions)):
         enum_value = extended_descriptor.ExtendedEnumValueDescriptor()
         enum_value.name = self.__names.NormalizeEnumName(enum_name)
         if enum_value.name != enum_name:
             message.enum_mappings.append(
                 extended_descriptor.ExtendedEnumDescriptor.JsonEnumMapping(
                     python_name=enum_value.name, json_name=enum_name))
             self.__AddImport('from %s import encoding' %
                              self.__base_files_package)
         enum_value.number = index
         enum_value.description = util.CleanDescription(
             enum_description or '<no description>')
         message.values.append(enum_value)
     self.__RegisterDescriptor(message)
Beispiel #7
0
 def __ComputeMethodInfo(self, method_description, request, response,
                         request_field):
     """Compute the base_api.ApiMethodInfo for this method."""
     relative_path = self.__names.NormalizeRelativePath(
         ''.join((self.__client_info.base_path,
                  method_description['path'])))
     method_id = method_description['id']
     ordered_params = []
     for param_name in method_description.get('parameterOrder', []):
         param_info = method_description['parameters'][param_name]
         if param_info.get('required', False):
             ordered_params.append(param_name)
     method_info = base_api.ApiMethodInfo(
         relative_path=relative_path,
         method_id=method_id,
         http_method=method_description['httpMethod'],
         description=util.CleanDescription(
             method_description.get('description', '')),
         query_params=[],
         path_params=[],
         ordered_params=ordered_params,
         request_type_name=self.__names.ClassName(request),
         response_type_name=self.__names.ClassName(response),
         request_field=request_field,
     )
     flat_path = method_description.get('flatPath', None)
     if flat_path is not None:
         flat_path = self.__names.NormalizeRelativePath(
             self.__client_info.base_path + flat_path)
         if flat_path != relative_path:
             method_info.flat_path = flat_path
     if method_description.get('supportsMediaUpload', False):
         method_info.upload_config = self.__ComputeUploadConfig(
             method_description.get('mediaUpload'), method_id)
     method_info.supports_download = method_description.get(
         'supportsMediaDownload', False)
     self.__all_scopes.update(method_description.get('scopes', ()))
     for param, desc in method_description.get('parameters', {}).items():
         param = self.__names.CleanName(param)
         location = desc['location']
         if location == 'query':
             method_info.query_params.append(param)
         elif location == 'path':
             method_info.path_params.append(param)
         else:
             raise ValueError(
                 'Unknown parameter location %s for parameter %s' % (
                     location, param))
     method_info.path_params.sort()
     method_info.query_params.sort()
     return method_info
 def __AddAdditionalProperties(self, message, schema, properties):
     """Add an additionalProperties field to message."""
     additional_properties_info = schema['additionalProperties']
     entries_type_name = self.__AddAdditionalPropertyType(
         message.name, additional_properties_info)
     description = util.CleanDescription(
         additional_properties_info.get('description'))
     if description is None:
         description = 'Additional properties of type %s' % message.name
     attrs = {
         'items': {
             '$ref': entries_type_name,
         },
         'description': description,
         'type': 'array',
     }
     field_name = 'additionalProperties'
     message.fields.append(self.__FieldDescriptorFromProperties(
         field_name, len(properties) + 1, attrs))
     self.__AddImport('from %s import encoding' % self.__base_files_package)
     message.decorators.append(
         'encoding.MapUnrecognizedFields(%r)' % field_name)
Beispiel #9
0
    def __init__(self,
                 discovery_doc,
                 client_info,
                 names,
                 root_package,
                 outdir,
                 base_package,
                 protorpc_package,
                 generate_cli=False,
                 init_wildcards_file=True,
                 use_proto2=False,
                 unelidable_request_methods=None,
                 apitools_version=''):
        self.__discovery_doc = discovery_doc
        self.__client_info = client_info
        self.__outdir = outdir
        self.__use_proto2 = use_proto2
        self.__description = util.CleanDescription(
            self.__discovery_doc.get('description', ''))
        self.__package = self.__client_info.package
        self.__version = self.__client_info.version
        self.__revision = discovery_doc.get('revision', '1')
        self.__generate_cli = generate_cli
        self.__init_wildcards_file = init_wildcards_file
        self.__root_package = root_package
        self.__base_files_package = base_package
        self.__protorpc_package = protorpc_package
        self.__names = names

        # Order is important here: we need the schemas before we can
        # define the services.
        self.__message_registry = message_registry.MessageRegistry(
            self.__client_info, self.__names, self.__description,
            self.__root_package, self.__base_files_package,
            self.__protorpc_package)
        schemas = self.__discovery_doc.get('schemas', {})
        for schema_name, schema in schemas.items():
            self.__message_registry.AddDescriptorFromSchema(
                schema_name, schema)

        # We need to add one more message type for the global parameters.
        standard_query_schema = _StandardQueryParametersSchema(
            self.__discovery_doc)
        self.__message_registry.AddDescriptorFromSchema(
            standard_query_schema['id'], standard_query_schema)

        # Now that we know all the messages, we need to correct some
        # fields from MessageFields to EnumFields.
        self.__message_registry.FixupMessageFields()

        self.__command_registry = command_registry.CommandRegistry(
            self.__package, self.__version, self.__client_info,
            self.__message_registry, self.__root_package,
            self.__base_files_package, self.__protorpc_package, self.__names)
        self.__command_registry.AddGlobalParameters(
            self.__message_registry.LookupDescriptorOrDie(
                'StandardQueryParameters'))

        self.__services_registry = service_registry.ServiceRegistry(
            self.__client_info, self.__message_registry,
            self.__command_registry, self.__names, self.__root_package,
            self.__base_files_package, unelidable_request_methods or [])
        services = self.__discovery_doc.get('resources', {})
        for service_name, methods in sorted(services.items()):
            self.__services_registry.AddServiceFromResource(
                service_name, methods)
        # We might also have top-level methods.
        api_methods = self.__discovery_doc.get('methods', [])
        if api_methods:
            self.__services_registry.AddServiceFromResource(
                'api', {'methods': api_methods})
        # pylint: disable=protected-access
        self.__client_info = self.__client_info._replace(
            scopes=self.__services_registry.scopes)

        # The apitools version that will be used in prerequisites for the
        # generated packages.
        self.__apitools_version = (apitools_version
                                   if apitools_version else _ApitoolsVersion())
Beispiel #10
0
    def __init__(self, discovery_doc, client_info, names, root_package, outdir,
                 base_package, generate_cli=False, use_proto2=False,
                 unelidable_request_methods=None):
        self.__discovery_doc = discovery_doc
        self.__client_info = client_info
        self.__outdir = outdir
        self.__use_proto2 = use_proto2
        self.__description = util.CleanDescription(
            self.__discovery_doc.get('description', ''))
        self.__package = self.__client_info.package
        self.__version = self.__client_info.version
        self.__generate_cli = generate_cli
        self.__root_package = root_package
        self.__base_files_package = base_package
        self.__base_files_target = (
            '//cloud/bigscience/apitools/base/py:apitools_base')
        self.__names = names
        self.__base_url, self.__base_path = _ComputePaths(
            self.__package, self.__client_info.url_version,
            self.__discovery_doc)

        # Order is important here: we need the schemas before we can
        # define the services.
        self.__message_registry = message_registry.MessageRegistry(
            self.__client_info, self.__names, self.__description,
            self.__root_package, self.__base_files_package)
        schemas = self.__discovery_doc.get('schemas', {})
        for schema_name, schema in schemas.items():
            self.__message_registry.AddDescriptorFromSchema(
                schema_name, schema)

        # We need to add one more message type for the global parameters.
        standard_query_schema = _StandardQueryParametersSchema(
            self.__discovery_doc)
        self.__message_registry.AddDescriptorFromSchema(
            standard_query_schema['id'], standard_query_schema)

        # Now that we know all the messages, we need to correct some
        # fields from MessageFields to EnumFields.
        self.__message_registry.FixupMessageFields()

        self.__command_registry = command_registry.CommandRegistry(
            self.__package, self.__version, self.__client_info,
            self.__message_registry, self.__root_package,
            self.__base_files_package, self.__base_url, self.__names)
        self.__command_registry.AddGlobalParameters(
            self.__message_registry.LookupDescriptorOrDie(
                'StandardQueryParameters'))

        self.__services_registry = service_registry.ServiceRegistry(
            self.__client_info,
            self.__message_registry,
            self.__command_registry,
            self.__base_url,
            self.__base_path,
            self.__names,
            self.__root_package,
            self.__base_files_package,
            unelidable_request_methods or [])
        services = self.__discovery_doc.get('resources', {})
        for service_name, methods in sorted(services.items()):
            self.__services_registry.AddServiceFromResource(
                service_name, methods)
        # We might also have top-level methods.
        api_methods = self.__discovery_doc.get('methods', [])
        if api_methods:
            self.__services_registry.AddServiceFromResource(
                'api', {'methods': api_methods})
        self.__client_info = self.__client_info._replace(
            scopes=self.__services_registry.scopes)