示例#1
0
    def _generate_routes(self, route_schema, namespace):

        for route in namespace.routes:
            var_name = fmt_func(route.name)
            data_types = [
                route.arg_data_type, route.result_data_type,
                route.error_data_type
            ]
            with self.block('%s = bb.Route(' % var_name,
                            delim=(None, None),
                            after=')'):
                self.emit("'%s'," % route.name)
                self.emit("%r," % (route.deprecated is not None))
                for data_type in data_types:
                    self.emit(
                        generate_validator_constructor(namespace, data_type) +
                        ',')
                attrs = []
                for field in route_schema.fields:
                    attr_key = field.name
                    attrs.append("'%s': %r" %
                                 (attr_key, route.attrs.get(attr_key)))
                self.generate_multiline_list(attrs,
                                             delim=('{', '}'),
                                             after=',',
                                             compact=True)

        if namespace.routes:
            self.emit()

        with self.block('ROUTES =', delim=('{', '}')):
            for route in namespace.routes:
                var_name = fmt_func(route.name)
                self.emit("'{}': {},".format(route.name, var_name))
        self.emit()
示例#2
0
    def _generate_routes(self, route_schema, namespace):

        for route in namespace.routes:
            var_name = fmt_func(route.name)
            data_types = [route.arg_data_type, route.result_data_type,
                          route.error_data_type]
            with self.block('%s = bb.Route(' % var_name, delim=(None, None), after=')'):
                self.emit("'%s'," % route.name)
                self.emit("%r," % (route.deprecated is not None))
                for data_type in data_types:
                    self.emit(
                        generate_validator_constructor(namespace, data_type) + ',')
                attrs = []
                for field in route_schema.fields:
                    attr_key = field.name
                    attrs.append("'%s': %r" % (attr_key, route.attrs.get(attr_key)))
                self.generate_multiline_list(
                    attrs, delim=('{', '}'), after=',', compact=True)

        if namespace.routes:
            self.emit()

        with self.block('ROUTES =', delim=('{', '}')):
            for route in namespace.routes:
                var_name = fmt_func(route.name)
                self.emit("'{}': {},".format(route.name, var_name))
        self.emit()
示例#3
0
 def _docf(self, tag, val):
     """
     Callback used as the handler argument to process_docs(). This converts
     Babel doc references to Sphinx-friendly annotations.
     """
     if tag == 'type':
         fq_val = val
         if '.' not in val:
             fq_val = self.cur_namespace.name + '.' + fq_val
         return ':class:`{}.{}`'.format(self.args.types_package, fq_val)
     elif tag == 'route':
         if ':' in val:
             val, version = val.split(':', 1)
             version = int(version)
         else:
             version = 1
         if '.' in val:
             return ':meth:`{}`'.format(fmt_func(val, version=version))
         else:
             return ':meth:`{}_{}`'.format(
                 self.cur_namespace.name, fmt_func(val, version=version))
     elif tag == 'link':
         anchor, link = val.rsplit(' ', 1)
         return '`{} <{}>`_'.format(anchor, link)
     elif tag == 'val':
         if val == 'null':
             return 'None'
         elif val == 'true' or val == 'false':
             return '``{}``'.format(val.capitalize())
         else:
             return val
     elif tag == 'field':
         return '``{}``'.format(val)
     else:
         raise RuntimeError('Unknown doc ref tag %r' % tag)
示例#4
0
 def _generate_union_class_variant_creators(self, ns, data_type):
     """
     Each non-symbol, non-any variant has a corresponding class method that
     can be used to construct a union with that variant selected.
     """
     for field in data_type.fields:
         if not is_void_type(field.data_type):
             field_name = fmt_func(field.name)
             field_name_reserved_check = fmt_func(field.name, True)
             if is_nullable_type(field.data_type):
                 field_dt = field.data_type.data_type
             else:
                 field_dt = field.data_type
             self.emit('@classmethod')
             self.emit(
                 'def {}(cls, val):'.format(field_name_reserved_check))
             with self.indent():
                 self.emit('"""')
                 self.emit_wrapped_text(
                     'Create an instance of this class set to the ``%s`` '
                     'tag with value ``val``.' % field_name)
                 self.emit()
                 self.emit(':param {} val:'.format(
                     self._python_type_mapping(ns, field_dt)))
                 self.emit(':rtype: {}'.format(fmt_class(data_type.name)))
                 self.emit('"""')
                 self.emit("return cls('{}', val)".format(field_name))
             self.emit()
示例#5
0
 def _docf(self, tag, val):
     """
     Callback used as the handler argument to process_docs(). This converts
     Babel doc references to Sphinx-friendly annotations.
     """
     if tag == 'type':
         fq_val = val
         if '.' not in val:
             fq_val = self.cur_namespace.name + '.' + fq_val
         return ':class:`{}.{}`'.format(self.args.types_package, fq_val)
     elif tag == 'route':
         if ':' in val:
             val, version = val.split(':', 1)
             version = int(version)
         else:
             version = 1
         if '.' in val:
             return ':meth:`{}`'.format(fmt_func(val, version=version))
         else:
             return ':meth:`{}_{}`'.format(
                 self.cur_namespace.name, fmt_func(val, version=version))
     elif tag == 'link':
         anchor, link = val.rsplit(' ', 1)
         return '`{} <{}>`_'.format(anchor, link)
     elif tag == 'val':
         if val == 'null':
             return 'None'
         elif val == 'true' or val == 'false':
             return '``{}``'.format(val.capitalize())
         else:
             return val
     elif tag == 'field':
         return '``{}``'.format(val)
     else:
         raise RuntimeError('Unknown doc ref tag %r' % tag)
示例#6
0
 def _generate_union_class_variant_creators(self, ns, data_type):
     """
     Each non-symbol, non-any variant has a corresponding class method that
     can be used to construct a union with that variant selected.
     """
     for field in data_type.fields:
         if not is_void_type(field.data_type):
             field_name = fmt_func(field.name)
             field_name_reserved_check = fmt_func(field.name, True)
             if is_nullable_type(field.data_type):
                 field_dt = field.data_type.data_type
             else:
                 field_dt = field.data_type
             self.emit('@classmethod')
             self.emit('def {}(cls, val):'.format(field_name_reserved_check))
             with self.indent():
                 self.emit('"""')
                 self.emit_wrapped_text(
                     'Create an instance of this class set to the ``%s`` '
                     'tag with value ``val``.' % field_name)
                 self.emit()
                 self.emit(':param {} val:'.format(
                     self._python_type_mapping(ns, field_dt)))
                 self.emit(':rtype: {}'.format(
                     fmt_class(data_type.name)))
                 self.emit('"""')
                 self.emit("return cls('{}', val)".format(field_name))
             self.emit()
示例#7
0
    def _generate_routes(self, route_schema, namespace):

        check_route_name_conflict(namespace)

        for route in namespace.routes:
            data_types = [route.arg_data_type, route.result_data_type,
                          route.error_data_type]
            with self.block(
                    '{} = bb.Route('.format(fmt_func(route.name, version=route.version)),
                    delim=(None, None),
                    after=')'):
                self.emit("'{}',".format(route.name))
                self.emit('{},'.format(route.version))
                self.emit('{!r},'.format(route.deprecated is not None))
                for data_type in data_types:
                    self.emit(
                        generate_validator_constructor(namespace, data_type) + ',')
                attrs = []
                for field in route_schema.fields:
                    attr_key = field.name
                    attrs.append("'{}': {!r}".format(attr_key, route.attrs.get(attr_key)))
                self.generate_multiline_list(
                    attrs, delim=('{', '}'), after=',', compact=True)

        if namespace.routes:
            self.emit()

        with self.block('ROUTES =', delim=('{', '}')):
            for route in namespace.routes:
                self.emit("'{}': {},".format(
                    route.name_with_version(), fmt_func(route.name, version=route.version)))
        self.emit()
示例#8
0
 def _docf(self, tag, val):
     """
     Callback used as the handler argument to process_docs(). This converts
     Stone doc references to Sphinx-friendly annotations.
     """
     if tag == 'type':
         return ':class:`{}`'.format(val)
     elif tag == 'route':
         if self.args.route_method:
             return ':meth:`%s`' % self.args.route_method.format(
                 ns=self.cur_namespace.name, route=fmt_func(val))
         else:
             return val
     elif tag == 'link':
         anchor, link = val.rsplit(' ', 1)
         return '`{} <{}>`_'.format(anchor, link)
     elif tag == 'val':
         if val == 'null':
             return 'None'
         elif val == 'true' or val == 'false':
             return '``{}``'.format(val.capitalize())
         else:
             return val
     elif tag == 'field':
         return '``{}``'.format(val)
     else:
         raise RuntimeError('Unknown doc ref tag %r' % tag)
示例#9
0
 def _docf(self, tag, val):
     """
     Callback used as the handler argument to process_docs(). This converts
     Stone doc references to Sphinx-friendly annotations.
     """
     if tag == 'type':
         return ':class:`{}`'.format(val)
     elif tag == 'route':
         if self.args.route_method:
             return ':meth:`%s`' % self.args.route_method.format(
                 ns=self.cur_namespace.name, route=fmt_func(val))
         else:
             return val
     elif tag == 'link':
         anchor, link = val.rsplit(' ', 1)
         return '`{} <{}>`_'.format(anchor, link)
     elif tag == 'val':
         if val == 'null':
             return 'None'
         elif val == 'true' or val == 'false':
             return '``{}``'.format(val.capitalize())
         else:
             return val
     elif tag == 'field':
         return '``{}``'.format(val)
     else:
         raise RuntimeError('Unknown doc ref tag %r' % tag)
示例#10
0
    def _generate_union_class_variant_creators(self, ns, data_type):
        # type: (ApiNamespace, Union) -> None
        """
        Generate the following section in the 'union Shape' example:
        @classmethod
        def circle(cls, val: float) -> Shape: ...
        """
        union_type = class_name_for_data_type(data_type)

        for field in data_type.fields:
            if not is_void_type(field.data_type):
                field_name_reserved_check = fmt_func(field.name,
                                                     check_reserved=True)
                val_type = self.map_stone_type_to_pep484_type(
                    ns, field.data_type)

                self.emit('@classmethod')
                self.emit(
                    'def {field_name}(cls, val: {val_type}) -> {union_type}: ...'
                    .format(
                        field_name=field_name_reserved_check,
                        val_type=val_type,
                        union_type=union_type,
                    ))
                self.emit()
示例#11
0
 def _generate_route_method_decl(self,
                                 namespace,
                                 route,
                                 arg_data_type,
                                 request_binary_body,
                                 method_name_suffix=None,
                                 extra_args=None):
     """Generates the method prototype for a route."""
     method_name = fmt_func(route.name)
     namespace_name = fmt_func(namespace.name)
     if method_name_suffix:
         method_name += method_name_suffix
     args = ['self']
     if extra_args:
         args += extra_args
     if request_binary_body:
         args.append('f')
     if is_struct_type(arg_data_type):
         for field in arg_data_type.all_fields:
             if is_nullable_type(field.data_type):
                 args.append('{}=None'.format(field.name))
             elif field.has_default:
                 # TODO(kelkabany): Decide whether we really want to set the
                 # default in the argument list. This will send the default
                 # over the wire even if it isn't overridden. The benefit is
                 # it locks in a default even if it is changed server-side.
                 if is_user_defined_type(field.data_type):
                     ns = field.data_type.namespace
                 else:
                     ns = None
                 arg = '{}={}'.format(
                     field.name,
                     self._generate_python_value(ns, field.default))
                 args.append(arg)
             else:
                 args.append(field.name)
     elif is_union_type(arg_data_type):
         args.append('arg')
     elif not is_void_type(arg_data_type):
         raise AssertionError('Unhandled request type: %r' % arg_data_type)
     self.generate_multiline_list(
         args, 'def {}_{}'.format(namespace_name, method_name), ':')
示例#12
0
    def _generate_routes(
            self,
            namespace,  # type: ApiNamespace
    ):
        # type: (...) -> None
        for route in namespace.routes:
            var_name = fmt_func(route.name)
            self.emit("{var_name}: bb.Route = ...".format(var_name=var_name))

        if namespace.routes:
            self.emit()
示例#13
0
 def _generate_union_class_is_set(self, data_type):
     for field in data_type.fields:
         field_name = fmt_func(field.name)
         self.emit('def is_{}(self):'.format(field_name))
         with self.indent():
             self.emit('"""')
             self.emit('Check if the union tag is ``%s``.' % field_name)
             self.emit()
             self.emit(':rtype: bool')
             self.emit('"""')
             self.emit("return self._tag == '{}'".format(field_name))
         self.emit()
示例#14
0
 def _generate_union_class_is_set(self, data_type):
     for field in data_type.fields:
         field_name = fmt_func(field.name)
         self.emit('def is_{}(self):'.format(field_name))
         with self.indent():
             self.emit('"""')
             self.emit('Check if the union tag is ``%s``.' % field_name)
             self.emit()
             self.emit(':rtype: bool')
             self.emit('"""')
             self.emit("return self._tag == '{}'".format(field_name))
         self.emit()
示例#15
0
 def _generate_route_method_decl(
         self, namespace, route, arg_data_type, request_binary_body,
         method_name_suffix=None, extra_args=None):
     """Generates the method prototype for a route."""
     method_name = fmt_func(route.name)
     namespace_name = fmt_func(namespace.name)
     if method_name_suffix:
         method_name += method_name_suffix
     args = ['self']
     if extra_args:
         args += extra_args
     if request_binary_body:
         args.append('f')
     if is_struct_type(arg_data_type):
         for field in arg_data_type.all_fields:
             if is_nullable_type(field.data_type):
                 args.append('{}=None'.format(field.name))
             elif field.has_default:
                 # TODO(kelkabany): Decide whether we really want to set the
                 # default in the argument list. This will send the default
                 # over the wire even if it isn't overridden. The benefit is
                 # it locks in a default even if it is changed server-side.
                 if is_user_defined_type(field.data_type):
                     ns = field.data_type.namespace
                 else:
                     ns = None
                 arg = '{}={}'.format(
                     field.name,
                     self._generate_python_value(ns, field.default))
                 args.append(arg)
             else:
                 args.append(field.name)
     elif is_union_type(arg_data_type):
         args.append('arg')
     elif not is_void_type(arg_data_type):
         raise AssertionError('Unhandled request type: %r' %
                              arg_data_type)
     self.generate_multiline_list(
         args, 'def {}_{}'.format(namespace_name, method_name), ':')
示例#16
0
 def _generate_union_class_symbol_creators(self, data_type):
     """
     Class attributes that represent a symbol are set after the union class
     definition.
     """
     class_name = fmt_class(data_type.name)
     lineno = self.lineno
     for field in data_type.fields:
         if is_void_type(field.data_type):
             field_name = fmt_func(field.name)
             self.emit("{0}.{1} = {0}('{1}')".format(class_name, field_name))
     if lineno != self.lineno:
         self.emit()
示例#17
0
 def _generate_union_class_symbol_creators(self, data_type):
     """
     Class attributes that represent a symbol are set after the union class
     definition.
     """
     class_name = fmt_class(data_type.name)
     lineno = self.lineno
     for field in data_type.fields:
         if is_void_type(field.data_type):
             field_name = fmt_func(field.name)
             self.emit("{0}.{1} = {0}('{1}')".format(class_name, field_name))
     if lineno != self.lineno:
         self.emit()
示例#18
0
    def _generate_struct_class_properties(self, ns, struct):
        # type: (ApiNamespace, Struct) -> None
        to_emit = []  # type: typing.List[typing.Text]
        for field in struct.all_fields:
            field_name_reserved_check = fmt_func(field.name,
                                                 check_reserved=True)
            field_type = self.map_stone_type_to_pep484_type(
                ns, field.data_type)

            to_emit.append("{}: bb.Attribute[{}] = ...".format(
                field_name_reserved_check, field_type))

        for s in to_emit:
            self.emit(s)
示例#19
0
    def _generate_routes(
            self,
            namespace,  # type: ApiNamespace
    ):
        # type: (...) -> None

        check_route_name_conflict(namespace)

        for route in namespace.routes:
            self.emit("{method_name}: bb.Route = ...".format(
                method_name=fmt_func(route.name, version=route.version)))

        if namespace.routes:
            self.emit()
示例#20
0
    def _generate_routes(
            self,
            namespace,  # type: ApiNamespace
    ):
        # type: (...) -> None

        check_route_name_conflict(namespace)

        for route in namespace.routes:
            self.emit(
                "{method_name}: bb.Route = ...".format(
                    method_name=fmt_func(route.name, version=route.version)))

        if namespace.routes:
            self.emit()
示例#21
0
    def _generate_struct_class_properties(self, ns, struct):
        # type: (ApiNamespace, Struct) -> None
        to_emit = []  # type: typing.List[typing.Text]
        for field in struct.all_fields:
            field_name_reserved_check = fmt_func(field.name,
                                                 check_reserved=True)
            field_type = self.map_stone_type_to_pep484_type(
                ns, field.data_type)

            to_emit.extend(
                self.property_template.format(
                    field_name=field_name_reserved_check,
                    field_type=field_type).split("\n"))

        for s in to_emit:
            self.emit(s)
示例#22
0
    def _generate_struct_class_properties(self, ns, struct):
        # type: (ApiNamespace, Struct) -> None
        to_emit = []  # type: typing.List[typing.Text]
        for field in struct.all_fields:
            field_name_reserved_check = fmt_func(field.name, check_reserved=True)
            field_type = self.map_stone_type_to_pep484_type(ns, field.data_type)

            to_emit.extend(
                self.property_template.format(
                    field_name=field_name_reserved_check,
                    field_type=field_type,
                ).split("\n")
            )

        for s in to_emit:
            self.emit(s)
示例#23
0
    def _generate_union_class_get_helpers(self, ns, data_type):
        # type: (ApiNamespace, Union) -> None
        """
        Generates the following section in the 'union Shape' example:
        def get_circle(self) -> float: ...
        """
        for field in data_type.fields:
            field_name = fmt_func(field.name)

            if not is_void_type(field.data_type):
                # generate getter for field
                val_type = self.map_stone_type_to_pep484_type(ns, field.data_type)

                self.emit('def get_{field_name}(self) -> {val_type}: ...'.format(
                    field_name=field_name,
                    val_type=val_type,
                ))
                self.emit()
示例#24
0
    def _generate_union_class_get_helpers(self, ns, data_type):
        # type: (ApiNamespace, Union) -> None
        """
        Generates the following section in the 'union Shape' example:
        def get_circle(self) -> float: ...
        """
        for field in data_type.fields:
            field_name = fmt_func(field.name)

            if not is_void_type(field.data_type):
                # generate getter for field
                val_type = self.map_stone_type_to_pep484_type(ns, field.data_type)

                self.emit('def get_{field_name}(self) -> {val_type}: ...'.format(
                    field_name=field_name,
                    val_type=val_type,
                ))
                self.emit()
示例#25
0
    def _generate_struct_class_init(self, data_type):
        """
        Generates constructor. The constructor takes all possible fields as
        optional arguments. Any argument that is set on construction sets the
        corresponding field for the instance.
        """

        args = ['self']
        for field in data_type.all_fields:
            field_name_reserved_check = fmt_var(field.name, True)
            args.append('%s=None' % field_name_reserved_check)
        self.generate_multiline_list(args, before='def __init__', after=':')

        with self.indent():
            lineno = self.lineno

            # Call the parent constructor if a super type exists
            if data_type.parent_type:
                class_name = class_name_for_data_type(data_type)
                all_parent_fields = [
                    fmt_func(f.name, True)
                    for f in data_type.parent_type.all_fields
                ]
                self.generate_multiline_list(
                    all_parent_fields,
                    before='super({}, self).__init__'.format(class_name))

            # initialize each field
            for field in data_type.fields:
                field_var_name = fmt_var(field.name)
                self.emit('self._{}_value = None'.format(field_var_name))
                self.emit('self._{}_present = False'.format(field_var_name))

            # handle arguments that were set
            for field in data_type.fields:
                field_var_name = fmt_var(field.name, True)
                self.emit('if {} is not None:'.format(field_var_name))
                with self.indent():
                    self.emit('self.{0} = {0}'.format(field_var_name))

            if lineno == self.lineno:
                self.emit('pass')
            self.emit()
示例#26
0
    def _generate_union_class_custom_annotations(self, ns, data_type):
        """
        The _process_custom_annotations function allows client code to access
        custom annotations defined in the spec.
        """
        self.emit(
            'def _process_custom_annotations(self, annotation_type, field_path, processor):'
        )
        with self.indent(), emit_pass_if_nothing_emitted(self):
            self.emit((
                'super({}, self)._process_custom_annotations(annotation_type, field_path, '
                'processor)').format(class_name_for_data_type(data_type)))
            self.emit()

            for field in data_type.fields:
                recursive_processors = list(
                    self._generate_custom_annotation_processors(
                        ns, field.data_type, field.custom_annotations))

                # check if we have any annotations that apply to this field at all
                if len(recursive_processors) == 0:
                    continue

                field_name = fmt_func(field.name)
                self.emit('if self.is_{}():'.format(field_name))

                with self.indent():
                    for annotation_type, processor in recursive_processors:
                        annotation_class = class_name_for_annotation_type(
                            annotation_type, ns)
                        self.emit('if annotation_type is {}:'.format(
                            annotation_class))
                        with self.indent():
                            self.emit('self._value = {}'.format(
                                generate_func_call(
                                    processor,
                                    args=[
                                        "'{{}}.{}'.format(field_path)".format(
                                            field_name),
                                        'self._value',
                                    ])))
                        self.emit()
示例#27
0
 def _generate_annotation_type_class_properties(self, ns, annotation_type):
     # type: (ApiNamespace, AnnotationType) -> None
     for param in annotation_type.params:
         param_name = fmt_var(param.name, True)
         prop_name = fmt_func(param.name, True)
         self.emit('@property')
         self.emit('def {}(self):'.format(prop_name))
         with self.indent():
             self.emit('"""')
             if param.doc:
                 self.emit_wrapped_text(
                     self.process_doc(param.doc, self._docf))
                 # Sphinx wants an extra line between the text and the
                 # rtype declaration.
                 self.emit()
             self.emit(':rtype: {}'.format(
                 self._python_type_mapping(ns, param.data_type)))
             self.emit('"""')
             self.emit('return self._{}'.format(param_name))
         self.emit()
示例#28
0
    def _generate_struct_class_init(self, data_type):
        """
        Generates constructor. The constructor takes all possible fields as
        optional arguments. Any argument that is set on construction sets the
        corresponding field for the instance.
        """

        args = ['self']
        for field in data_type.all_fields:
            field_name_reserved_check = fmt_var(field.name, True)
            args.append('%s=None' % field_name_reserved_check)
        self.generate_multiline_list(args, before='def __init__', after=':')

        with self.indent():
            lineno = self.lineno

            # Call the parent constructor if a super type exists
            if data_type.parent_type:
                class_name = class_name_for_data_type(data_type)
                all_parent_fields = [fmt_func(f.name, True)
                              for f in data_type.parent_type.all_fields]
                self.generate_multiline_list(
                    all_parent_fields,
                    before='super({}, self).__init__'.format(class_name))

            # initialize each field
            for field in data_type.fields:
                field_var_name = fmt_var(field.name)
                self.emit('self._{}_value = None'.format(field_var_name))
                self.emit('self._{}_present = False'.format(field_var_name))

            # handle arguments that were set
            for field in data_type.fields:
                field_var_name = fmt_var(field.name, True)
                self.emit('if {} is not None:'.format(field_var_name))
                with self.indent():
                    self.emit('self.{0} = {0}'.format(field_var_name))

            if lineno == self.lineno:
                self.emit('pass')
            self.emit()
示例#29
0
    def _generate_union_class_variant_creators(self, ns, data_type):
        # type: (ApiNamespace, Union) -> None
        """
        Generate the following section in the 'union Shape' example:
        @classmethod
        def circle(cls, val: float) -> Shape: ...
        """
        union_type = class_name_for_data_type(data_type)

        for field in data_type.fields:
            if not is_void_type(field.data_type):
                field_name_reserved_check = fmt_func(field.name, check_reserved=True)
                val_type = self.map_stone_type_to_pep484_type(ns, field.data_type)

                self.emit('@classmethod')
                self.emit('def {field_name}(cls, val: {val_type}) -> {union_type}: ...'.format(
                    field_name=field_name_reserved_check,
                    val_type=val_type,
                    union_type=union_type,
                ))
                self.emit()
示例#30
0
    def _generate_struct_class_properties(self, ns, struct):
        # type: (ApiNamespace, Struct) -> None
        to_emit = []  # type: typing.List[typing.Text]
        for field in struct.all_fields:
            field_name_reserved_check = fmt_func(field.name, check_reserved=True)
            setter_field_type = self.map_stone_type_to_pep484_type(ns, field.data_type)

            # The field might not have been set since it is optional in the constructor.
            getter_field_type = setter_field_type
            if not is_nullable_type(field.data_type) and not is_void_type(field.data_type):
                self.import_tracker._register_typing_import('Optional')
                getter_field_type = 'Optional[{}]'.format(setter_field_type)

            to_emit.extend(
                self.property_template.format(
                    field_name=field_name_reserved_check,
                    getter_field_type=getter_field_type,
                    setter_field_type=setter_field_type
                ).split("\n")
            )

        for s in to_emit:
            self.emit(s)
示例#31
0
    def _generate_union_class_get_helpers(self, ns, data_type):
        """
        These are the getters used to access the value of a variant, once
        the tag has been switched on.
        """
        for field in data_type.fields:
            field_name = fmt_func(field.name)

            if not is_void_type(field.data_type):
                # generate getter for field
                self.emit('def get_{}(self):'.format(field_name))
                with self.indent():
                    if is_nullable_type(field.data_type):
                        field_dt = field.data_type.data_type
                    else:
                        field_dt = field.data_type
                    self.emit('"""')
                    if field.doc:
                        self.emit_wrapped_text(
                            self.process_doc(field.doc, self._docf))
                        self.emit()
                    self.emit("Only call this if :meth:`is_%s` is true." %
                              field_name)
                    # Sphinx wants an extra line between the text and the
                    # rtype declaration.
                    self.emit()
                    self.emit(':rtype: {}'.format(
                        self._python_type_mapping(ns, field_dt)))
                    self.emit('"""')

                    self.emit('if not self.is_{}():'.format(field_name))
                    with self.indent():
                        self.emit(
                            'raise AttributeError("tag \'{}\' not set")'.format(
                                field_name))
                    self.emit('return self._value')
                self.emit()
示例#32
0
    def _generate_union_class_get_helpers(self, ns, data_type):
        """
        These are the getters used to access the value of a variant, once
        the tag has been switched on.
        """
        for field in data_type.fields:
            field_name = fmt_func(field.name)

            if not is_void_type(field.data_type):
                # generate getter for field
                self.emit('def get_{}(self):'.format(field_name))
                with self.indent():
                    if is_nullable_type(field.data_type):
                        field_dt = field.data_type.data_type
                    else:
                        field_dt = field.data_type
                    self.emit('"""')
                    if field.doc:
                        self.emit_wrapped_text(
                            self.process_doc(field.doc, self._docf))
                        self.emit()
                    self.emit("Only call this if :meth:`is_%s` is true." %
                              field_name)
                    # Sphinx wants an extra line between the text and the
                    # rtype declaration.
                    self.emit()
                    self.emit(':rtype: {}'.format(
                        self._python_type_mapping(ns, field_dt)))
                    self.emit('"""')

                    self.emit('if not self.is_{}():'.format(field_name))
                    with self.indent():
                        self.emit(
                            'raise AttributeError("tag \'{}\' not set")'.format(
                                field_name))
                    self.emit('return self._value')
                self.emit()
示例#33
0
    def _generate_struct_class_properties(self, ns, data_type):
        """
        Each field of the struct has a corresponding setter and getter.
        The setter validates the value being set.
        """
        for field in data_type.fields:
            field_name = fmt_func(field.name, check_reserved=True)
            if is_nullable_type(field.data_type):
                field_dt = field.data_type.data_type
                dt_nullable = True
            else:
                field_dt = field.data_type
                dt_nullable = False

            # generate getter for field
            args = '"{}"'.format(field_name)
            if dt_nullable:
                args += ", nullable=True"
            if is_user_defined_type(field_dt):
                args += ", user_defined=True"
            self.emit('# Instance attribute type: {} (validator is set below)'.
                      format(self._python_type_mapping(ns, field_dt)))
            self.emit("{} = bb.Attribute({})".format(field_name, args))
            self.emit()
示例#34
0
    def _generate_route_helper(self, namespace, route, download_to_file=False):
        """Generate a Python method that corresponds to a route.

        :param namespace: Namespace that the route belongs to.
        :param stone.ir.ApiRoute route: IR node for the route.
        :param bool download_to_file: Whether a special version of the route
            that downloads the response body to a file should be generated.
            This can only be used for download-style routes.
        """
        arg_data_type = route.arg_data_type
        result_data_type = route.result_data_type

        request_binary_body = route.attrs.get('style') == 'upload'
        response_binary_body = route.attrs.get('style') == 'download'

        if download_to_file:
            assert response_binary_body, 'download_to_file can only be set ' \
                'for download-style routes.'
            self._generate_route_method_decl(namespace,
                                             route,
                                             arg_data_type,
                                             request_binary_body,
                                             method_name_suffix='_to_file',
                                             extra_args=['download_path'])
        else:
            self._generate_route_method_decl(namespace,
                                             route,
                                             arg_data_type,
                                             request_binary_body)

        with self.indent():
            extra_request_args = None
            extra_return_arg = None
            footer = None
            if request_binary_body:
                extra_request_args = [('f',
                                       'bytes',
                                       'Contents to upload.')]
            elif download_to_file:
                extra_request_args = [('download_path',
                                       'str',
                                       'Path on local machine to save file.')]
            if response_binary_body and not download_to_file:
                extra_return_arg = ':class:`requests.models.Response`'
                footer = DOCSTRING_CLOSE_RESPONSE

            if route.doc:
                func_docstring = self.process_doc(route.doc, self._docf)
            else:
                func_docstring = None

            self._generate_docstring_for_func(
                namespace,
                arg_data_type,
                result_data_type,
                route.error_data_type,
                overview=func_docstring,
                extra_request_args=extra_request_args,
                extra_return_arg=extra_return_arg,
                footer=footer,
            )

            self._maybe_generate_deprecation_warning(route)

            # Code to instantiate a class for the request data type
            if is_void_type(arg_data_type):
                self.emit('arg = None')
            elif is_struct_type(arg_data_type):
                self.generate_multiline_list(
                    [f.name for f in arg_data_type.all_fields],
                    before='arg = {}.{}'.format(
                        fmt_namespace(arg_data_type.namespace.name),
                        fmt_class(arg_data_type.name)),
                )
            elif not is_union_type(arg_data_type):
                raise AssertionError('Unhandled request type %r' %
                                     arg_data_type)

            # Code to make the request
            args = [
                '{}.{}'.format(fmt_namespace(namespace.name),
                               fmt_func(route.name, version=route.version)),
                "'{}'".format(namespace.name),
                'arg']
            if request_binary_body:
                args.append('f')
            else:
                args.append('None')
            self.generate_multiline_list(args, 'r = self.request', compact=False)

            if download_to_file:
                self.emit('self._save_body_to_file(download_path, r[1])')
                if is_void_type(result_data_type):
                    self.emit('return None')
                else:
                    self.emit('return r[0]')
            else:
                if is_void_type(result_data_type):
                    self.emit('return None')
                else:
                    self.emit('return r')
        self.emit()
示例#35
0
 def _generate_union_class_is_set(self, union):
     # type: (Union) -> None
     for field in union.fields:
         field_name = fmt_func(field.name)
         self.emit('def is_{}(self) -> bool: ...'.format(field_name))
         self.emit()
示例#36
0
 def _generate_union_class_is_set(self, union):
     # type: (Union) -> None
     for field in union.fields:
         field_name = fmt_func(field.name)
         self.emit('def is_{}(self) -> bool: ...'.format(field_name))
         self.emit()
示例#37
0
    def _generate_struct_class_properties(self, ns, data_type):
        """
        Each field of the struct has a corresponding setter and getter.
        The setter validates the value being set.
        """
        for field in data_type.fields:
            field_name = fmt_func(field.name)
            field_name_reserved_check = fmt_func(field.name, True)
            if is_nullable_type(field.data_type):
                field_dt = field.data_type.data_type
                dt_nullable = True
            else:
                field_dt = field.data_type
                dt_nullable = False

            # generate getter for field
            self.emit('@property')
            self.emit('def {}(self):'.format(field_name_reserved_check))
            with self.indent():
                self.emit('"""')
                if field.doc:
                    self.emit_wrapped_text(
                        self.process_doc(field.doc, self._docf))
                    # Sphinx wants an extra line between the text and the
                    # rtype declaration.
                    self.emit()
                self.emit(':rtype: {}'.format(
                    self._python_type_mapping(ns, field_dt)))
                self.emit('"""')
                self.emit('if self._{}_present:'.format(field_name))
                with self.indent():
                    self.emit('return self._{}_value'.format(field_name))

                self.emit('else:')
                with self.indent():
                    if dt_nullable:
                        self.emit('return None')
                    elif field.has_default:
                        self.emit('return {}'.format(
                            self._generate_python_value(ns, field.default)))
                    else:
                        self.emit(
                            "raise AttributeError(\"missing required field '%s'\")"
                            % field_name)
            self.emit()

            # generate setter for field
            self.emit('@{}.setter'.format(field_name_reserved_check))
            self.emit('def {}(self, val):'.format(field_name_reserved_check))
            with self.indent():
                if dt_nullable:
                    self.emit('if val is None:')
                    with self.indent():
                        self.emit(
                            'del self.{}'.format(field_name_reserved_check))
                        self.emit('return')
                if is_user_defined_type(field_dt):
                    self.emit('self._%s_validator.validate_type_only(val)' %
                              field_name)
                else:
                    self.emit('val = self._{}_validator.validate(val)'.format(
                        field_name))
                self.emit('self._{}_value = val'.format(field_name))
                self.emit('self._{}_present = True'.format(field_name))
            self.emit()

            # generate deleter for field
            self.emit('@{}.deleter'.format(field_name_reserved_check))
            self.emit('def {}(self):'.format(field_name_reserved_check))
            with self.indent():
                self.emit('self._{}_value = None'.format(field_name))
                self.emit('self._{}_present = False'.format(field_name))
            self.emit()
示例#38
0
    def _generate_struct_class_properties(self, ns, data_type):
        """
        Each field of the struct has a corresponding setter and getter.
        The setter validates the value being set.
        """
        for field in data_type.fields:
            field_name = fmt_func(field.name)
            field_name_reserved_check = fmt_func(field.name, True)
            if is_nullable_type(field.data_type):
                field_dt = field.data_type.data_type
                dt_nullable = True
            else:
                field_dt = field.data_type
                dt_nullable = False

            # generate getter for field
            self.emit('@property')
            self.emit('def {}(self):'.format(field_name_reserved_check))
            with self.indent():
                self.emit('"""')
                if field.doc:
                    self.emit_wrapped_text(
                        self.process_doc(field.doc, self._docf))
                    # Sphinx wants an extra line between the text and the
                    # rtype declaration.
                    self.emit()
                self.emit(':rtype: {}'.format(
                    self._python_type_mapping(ns, field_dt)))
                self.emit('"""')
                self.emit('if self._{}_present:'.format(field_name))
                with self.indent():
                    self.emit('return self._{}_value'.format(field_name))

                self.emit('else:')
                with self.indent():
                    if dt_nullable:
                        self.emit('return None')
                    elif field.has_default:
                        self.emit('return {}'.format(
                            self._generate_python_value(ns, field.default)))
                    else:
                        self.emit(
                            "raise AttributeError(\"missing required field '%s'\")"
                            % field_name
                        )
            self.emit()

            # generate setter for field
            self.emit('@{}.setter'.format(field_name_reserved_check))
            self.emit('def {}(self, val):'.format(field_name_reserved_check))
            with self.indent():
                if dt_nullable:
                    self.emit('if val is None:')
                    with self.indent():
                        self.emit('del self.{}'.format(field_name_reserved_check))
                        self.emit('return')
                if is_user_defined_type(field_dt):
                    self.emit('self._%s_validator.validate_type_only(val)' %
                              field_name)
                else:
                    self.emit('val = self._{}_validator.validate(val)'.format(field_name))
                self.emit('self._{}_value = val'.format(field_name))
                self.emit('self._{}_present = True'.format(field_name))
            self.emit()

            # generate deleter for field
            self.emit('@{}.deleter'.format(field_name_reserved_check))
            self.emit('def {}(self):'.format(field_name_reserved_check))
            with self.indent():
                self.emit('self._{}_value = None'.format(field_name))
                self.emit('self._{}_present = False'.format(field_name))
            self.emit()
示例#39
0
    def _generate_route_helper(self, namespace, route, download_to_file=False):
        """Generate a Python method that corresponds to a route.

        :param namespace: Namespace that the route belongs to.
        :param stone.ir.ApiRoute route: IR node for the route.
        :param bool download_to_file: Whether a special version of the route
            that downloads the response body to a file should be generated.
            This can only be used for download-style routes.
        """
        arg_data_type = route.arg_data_type
        result_data_type = route.result_data_type

        request_binary_body = route.attrs.get('style') == 'upload'
        response_binary_body = route.attrs.get('style') == 'download'

        if download_to_file:
            assert response_binary_body, 'download_to_file can only be set ' \
                'for download-style routes.'
            self._generate_route_method_decl(namespace,
                                             route,
                                             arg_data_type,
                                             request_binary_body,
                                             method_name_suffix='_to_file',
                                             extra_args=['download_path'])
        else:
            self._generate_route_method_decl(namespace,
                                             route,
                                             arg_data_type,
                                             request_binary_body)

        with self.indent():
            extra_request_args = None
            extra_return_arg = None
            footer = None
            if request_binary_body:
                extra_request_args = [('f',
                                       'bytes',
                                       'Contents to upload.')]
            elif download_to_file:
                extra_request_args = [('download_path',
                                       'str',
                                       'Path on local machine to save file.')]
            if response_binary_body and not download_to_file:
                extra_return_arg = ':class:`requests.models.Response`'
                footer = DOCSTRING_CLOSE_RESPONSE

            if route.doc:
                func_docstring = self.process_doc(route.doc, self._docf)
            else:
                func_docstring = None

            self._generate_docstring_for_func(
                namespace,
                arg_data_type,
                result_data_type,
                route.error_data_type,
                overview=func_docstring,
                extra_request_args=extra_request_args,
                extra_return_arg=extra_return_arg,
                footer=footer,
            )

            self._maybe_generate_deprecation_warning(route)

            # Code to instantiate a class for the request data type
            if is_void_type(arg_data_type):
                self.emit('arg = None')
            elif is_struct_type(arg_data_type):
                self.generate_multiline_list(
                    [f.name for f in arg_data_type.all_fields],
                    before='arg = {}.{}'.format(
                        fmt_namespace(arg_data_type.namespace.name),
                        fmt_class(arg_data_type.name)),
                )
            elif not is_union_type(arg_data_type):
                raise AssertionError('Unhandled request type %r' %
                                     arg_data_type)

            # Code to make the request
            args = [
                '{}.{}'.format(fmt_namespace(namespace.name),
                               fmt_func(route.name, version=route.version)),
                "'{}'".format(namespace.name),
                'arg']
            if request_binary_body:
                args.append('f')
            else:
                args.append('None')
            self.generate_multiline_list(args, 'r = self.request', compact=False)

            if download_to_file:
                self.emit('self._save_body_to_file(download_path, r[1])')
                if is_void_type(result_data_type):
                    self.emit('return None')
                else:
                    self.emit('return r[0]')
            else:
                if is_void_type(result_data_type):
                    self.emit('return None')
                else:
                    self.emit('return r')
        self.emit()