Beispiel #1
0
    def _generate_struct_class_repr(self, data_type):
        """
        Generates something like:

            def __repr__(self):
                return 'Employee(first_name={!r}, last_name={!r}, age={!r})'.format(
                    self._first_name_value,
                    self._last_name_value,
                    self._age_value,
                )
        """
        self.emit('def __repr__(self):')
        with self.indent():
            if data_type.all_fields:
                constructor_kwargs_fmt = ', '.join(
                    '{}={{!r}}'.format(fmt_var(f.name, True))
                    for f in data_type.all_fields)
                self.emit("return '{}({})'.format(".format(
                    class_name_for_data_type(data_type),
                    constructor_kwargs_fmt,
                ))
                with self.indent():
                    for f in data_type.all_fields:
                        self.emit("self._{}_value,".format(fmt_var(f.name)))
                self.emit(")")
            else:
                self.emit("return '%s()'" %
                          class_name_for_data_type(data_type))
        self.emit()
Beispiel #2
0
    def _generate_union_class_reflection_attributes(self, ns, data_type):
        """
        Adds a class attribute for each union member assigned to a validator.
        Also adds an attribute that is a map from tag names to validators.
        """
        class_name = fmt_class(data_type.name)

        for field in data_type.fields:
            field_name = fmt_var(field.name)
            validator_name = generate_validator_constructor(
                ns, field.data_type)
            self.emit('{}._{}_validator = {}'.format(class_name, field_name,
                                                     validator_name))

        with self.block('{}._tagmap ='.format(class_name)):
            for field in data_type.fields:
                var_name = fmt_var(field.name)
                validator_name = '{}._{}_validator'.format(
                    class_name, var_name)
                self.emit("'{}': {},".format(var_name, validator_name))

        if data_type.parent_type:
            self.emit('{0}._tagmap.update({1}._tagmap)'.format(
                class_name, class_name_for_data_type(data_type.parent_type,
                                                     ns)))

        self.emit()
Beispiel #3
0
    def _generate_union_class_reflection_attributes(self, ns, data_type):
        """
        Adds a class attribute for each union member assigned to a validator.
        Also adds an attribute that is a map from tag names to validators.
        """
        class_name = fmt_class(data_type.name)

        for field in data_type.fields:
            field_name = fmt_var(field.name)
            validator_name = generate_validator_constructor(
                ns, field.data_type)
            self.emit('{}._{}_validator = {}'.format(
                class_name, field_name, validator_name))

        with self.block('{}._tagmap ='.format(class_name)):
            for field in data_type.fields:
                var_name = fmt_var(field.name)
                validator_name = '{}._{}_validator'.format(
                    class_name, var_name)
                self.emit("'{}': {},".format(var_name, validator_name))

        if data_type.parent_type:
            self.emit('{0}._tagmap.update({1}._tagmap)'.format(
                class_name,
                class_name_for_data_type(data_type.parent_type, ns)))

        self.emit()
Beispiel #4
0
    def _generate_struct_class_repr(self, data_type):
        """
        Generates something like:

            def __repr__(self):
                return 'Employee(first_name={!r}, last_name={!r}, age={!r})'.format(
                    self._first_name_value,
                    self._last_name_value,
                    self._age_value,
                )
        """
        self.emit('def __repr__(self):')
        with self.indent():
            if data_type.all_fields:
                constructor_kwargs_fmt = ', '.join(
                    '{}={{!r}}'.format(fmt_var(f.name, True))
                    for f in data_type.all_fields)
                self.emit("return '{}({})'.format(".format(
                    class_name_for_data_type(data_type),
                    constructor_kwargs_fmt,
                ))
                with self.indent():
                    for f in data_type.all_fields:
                        self.emit("self._{}_value,".format(fmt_var(f.name)))
                self.emit(")")
            else:
                self.emit("return '%s()'" %
                          class_name_for_data_type(data_type))
        self.emit()
Beispiel #5
0
    def _generate_annotation_type_class_init(self, ns, annotation_type):
        # type: (ApiNamespace, AnnotationType) -> None
        args = ['self']
        for param in annotation_type.params:
            param_name = fmt_var(param.name, True)
            default_value = (self._generate_python_value(ns, param.default)
                             if param.has_default else 'None')
            args.append('{}={}'.format(param_name, default_value))
        self.generate_multiline_list(args, before='def __init__', after=':')

        with self.indent():
            for param in annotation_type.params:
                self.emit('self._{0} = {0}'.format(fmt_var(param.name, True)))
        self.emit()
Beispiel #6
0
    def _generate_union_class_reflection_attributes(self, ns, data_type):
        """
        Adds a class attribute for each union member assigned to a validator.
        Also adds an attribute that is a map from tag names to validators.
        """
        class_name = fmt_class(data_type.name)

        for field in data_type.fields:
            field_name = fmt_var(field.name)
            validator_name = generate_validator_constructor(
                ns, field.data_type)
            full_validator_name = '{}._{}_validator'.format(
                class_name, field_name)
            self.emit('{} = {}'.format(full_validator_name, validator_name))

            if field.redactor:
                self._generate_redactor(full_validator_name, field.redactor)

        # generate _all_fields_ for each omitted caller (and public)
        child_omitted_callers = data_type.get_all_omitted_callers()
        parent_omitted_callers = data_type.parent_type.get_all_omitted_callers() if \
            data_type.parent_type else set([])

        all_omitted_callers = child_omitted_callers | parent_omitted_callers
        if len(all_omitted_callers) != 0:
            self.emit('{}._permissioned_tagmaps = {}'.format(
                class_name, all_omitted_callers))
        for omitted_caller in all_omitted_callers | {None}:
            is_public = omitted_caller is None
            tagmap_name = '_tagmap' if is_public else '_{}_tagmap'.format(
                omitted_caller)
            caller_in_parent = data_type.parent_type and (
                is_public or omitted_caller in parent_omitted_callers)

            with self.block('{}.{} ='.format(class_name, tagmap_name)):
                for field in data_type.fields:
                    if field.omitted_caller != omitted_caller:
                        continue
                    var_name = fmt_var(field.name)
                    validator_name = '{}._{}_validator'.format(
                        class_name, var_name)
                    self.emit("'{}': {},".format(var_name, validator_name))

            if caller_in_parent:
                self.emit('{0}.{1}.update({2}.{1})'.format(
                    class_name, tagmap_name,
                    class_name_for_data_type(data_type.parent_type, ns)))

        self.emit()
Beispiel #7
0
    def _generate_union_class(self, ns, data_type):
        # type: (ApiNamespace, Union) -> None
        """Defines a Python class that represents a union in Stone."""
        self.emit(self._class_declaration_for_type(ns, data_type))
        with self.indent():
            self.emit('"""')
            if data_type.doc:
                self.emit_wrapped_text(
                    self.process_doc(data_type.doc, self._docf))
                self.emit()

            self.emit_wrapped_text(
                'This class acts as a tagged union. Only one of the ``is_*`` '
                'methods will return true. To get the associated value of a '
                'tag (if one exists), use the corresponding ``get_*`` method.')

            if data_type.has_documented_fields():
                self.emit()

            for field in data_type.fields:
                if not field.doc:
                    continue
                if is_void_type(field.data_type):
                    ivar_doc = ':ivar {}: {}'.format(
                        fmt_var(field.name),
                        self.process_doc(field.doc, self._docf))
                elif is_user_defined_type(field.data_type):
                    ivar_doc = ':ivar {} {}: {}'.format(
                        fmt_class(field.data_type.name),
                        fmt_var(field.name),
                        self.process_doc(field.doc, self._docf))
                else:
                    ivar_doc = ':ivar {} {}: {}'.format(
                        self._python_type_mapping(ns, field.data_type),
                        fmt_var(field.name), field.doc)
                self.emit_wrapped_text(ivar_doc, subsequent_prefix='    ')
            self.emit('"""')
            self.emit()

            self._generate_union_class_vars(data_type)
            self._generate_union_class_variant_creators(ns, data_type)
            self._generate_union_class_is_set(data_type)
            self._generate_union_class_get_helpers(ns, data_type)
            self._generate_union_class_repr(data_type)
        self.emit('{0}_validator = bv.Union({0})'.format(
            class_name_for_data_type(data_type)
        ))
        self.emit()
Beispiel #8
0
    def _generate_union_class(self, ns, data_type):
        # type: (ApiNamespace, Union) -> None
        """Defines a Python class that represents a union in Stone."""
        self.emit(self._class_declaration_for_type(ns, data_type))
        with self.indent():
            self.emit('"""')
            if data_type.doc:
                self.emit_wrapped_text(
                    self.process_doc(data_type.doc, self._docf))
                self.emit()

            self.emit_wrapped_text(
                'This class acts as a tagged union. Only one of the ``is_*`` '
                'methods will return true. To get the associated value of a '
                'tag (if one exists), use the corresponding ``get_*`` method.')

            if data_type.has_documented_fields():
                self.emit()

            for field in data_type.fields:
                if not field.doc:
                    continue
                if is_void_type(field.data_type):
                    ivar_doc = ':ivar {}: {}'.format(
                        fmt_var(field.name),
                        self.process_doc(field.doc, self._docf))
                elif is_user_defined_type(field.data_type):
                    ivar_doc = ':ivar {} {}: {}'.format(
                        fmt_class(field.data_type.name),
                        fmt_var(field.name),
                        self.process_doc(field.doc, self._docf))
                else:
                    ivar_doc = ':ivar {} {}: {}'.format(
                        self._python_type_mapping(ns, field.data_type),
                        fmt_var(field.name), field.doc)
                self.emit_wrapped_text(ivar_doc, subsequent_prefix='    ')
            self.emit('"""')
            self.emit()

            self._generate_union_class_vars(data_type)
            self._generate_union_class_variant_creators(ns, data_type)
            self._generate_union_class_is_set(data_type)
            self._generate_union_class_get_helpers(ns, data_type)
            self._generate_union_class_repr(data_type)
        self.emit('{0}_validator = bv.Union({0})'.format(
            class_name_for_data_type(data_type)
        ))
        self.emit()
Beispiel #9
0
 def _generate_annotation_type_class_slots(self, annotation_type):
     # type: (AnnotationType) -> None
     with self.block('__slots__ =', delim=('[', ']')):
         for param in annotation_type.params:
             param_name = fmt_var(param.name, True)
             self.emit("'_{}',".format(param_name))
     self.emit()
Beispiel #10
0
    def _generate_struct_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:
                field_name = fmt_var(field.name, check_reserved=True)
                for annotation_type, processor in self._generate_custom_annotation_processors(
                        ns, field.data_type, field.custom_annotations):
                    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.{} = {}'.format(
                            field_name,
                            generate_func_call(
                                processor,
                                args=[
                                    "'{{}}.{}'.format(field_path)".format(
                                        field_name),
                                    'self.{}'.format(field_name),
                                ])))
                    self.emit()
Beispiel #11
0
    def _generate_annotation_type_class(self, ns, annotation_type):
        # type: (ApiNamespace, AnnotationType) -> None
        """Defines a Python class that represents an annotation type in Stone."""
        self.emit('class {}(bb.AnnotationType):'.format(
            class_name_for_annotation_type(annotation_type, ns)))
        with self.indent():
            if annotation_type.has_documented_type_or_params():
                self.emit('"""')
                if annotation_type.doc:
                    self.emit_wrapped_text(
                        self.process_doc(annotation_type.doc, self._docf))
                    if annotation_type.has_documented_params():
                        self.emit()
                for param in annotation_type.params:
                    if not param.doc:
                        continue
                    self.emit_wrapped_text(':ivar {}: {}'.format(
                        fmt_var(param.name, True),
                        self.process_doc(param.doc, self._docf)),
                                           subsequent_prefix='    ')
                self.emit('"""')
            self.emit()

            self._generate_annotation_type_class_slots(annotation_type)
            self._generate_annotation_type_class_init(ns, annotation_type)
            self._generate_annotation_type_class_properties(
                ns, annotation_type)
            self.emit()
Beispiel #12
0
    def _generate_union_class_reflection_attributes(self, ns, data_type):
        """
        Adds a class attribute for each union member assigned to a validator.
        Also adds an attribute that is a map from tag names to validators.
        """
        class_name = fmt_class(data_type.name)

        for field in data_type.fields:
            field_name = fmt_var(field.name)
            validator_name = generate_validator_constructor(
                ns, field.data_type)
            full_validator_name = '{}._{}_validator'.format(class_name, field_name)
            self.emit('{} = {}'.format(full_validator_name, validator_name))

            if field.redactor:
                self._generate_redactor(full_validator_name, field.redactor)

        # generate _all_fields_ for each omitted caller (and public)
        child_omitted_callers = data_type.get_all_omitted_callers()
        parent_omitted_callers = data_type.parent_type.get_all_omitted_callers() if \
            data_type.parent_type else set([])

        all_omitted_callers = child_omitted_callers | parent_omitted_callers
        if len(all_omitted_callers) != 0:
            self.emit('{}._permissioned_tagmaps = {}'.format(class_name, all_omitted_callers))
        for omitted_caller in all_omitted_callers | {None}:
            is_public = omitted_caller is None
            tagmap_name = '_tagmap' if is_public else '_{}_tagmap'.format(omitted_caller)
            caller_in_parent = data_type.parent_type and (is_public or omitted_caller
                                                         in parent_omitted_callers)

            with self.block('{}.{} ='.format(class_name, tagmap_name)):
                for field in data_type.fields:
                    if field.omitted_caller != omitted_caller:
                        continue
                    var_name = fmt_var(field.name)
                    validator_name = '{}._{}_validator'.format(class_name, var_name)
                    self.emit("'{}': {},".format(var_name, validator_name))

            if caller_in_parent:
                self.emit('{0}.{1}.update({2}.{1})'.format(
                    class_name, tagmap_name,
                    class_name_for_data_type(data_type.parent_type, ns))
                )

        self.emit()
Beispiel #13
0
 def _generate_python_value(self, namespace, value):
     if is_tag_ref(value):
         return '{}.{}.{}'.format(
             fmt_namespace(namespace.name),
             class_name_for_data_type(value.union_data_type),
             fmt_var(value.tag_name))
     else:
         return fmt_obj(value)
Beispiel #14
0
 def _generate_struct_attributes_defaults(self, ns, data_type):
     # Default values can cross-reference, so we also set them after classes.
     class_name = class_name_for_data_type(data_type)
     for field in data_type.fields:
         if field.has_default:
             self.emit("{}.{}.default = {}".format(
                 class_name, fmt_var(field.name),
                 self._generate_python_value(ns, field.default)))
Beispiel #15
0
 def _generate_python_value(self, namespace, value):
     if is_tag_ref(value):
         return '{}.{}.{}'.format(
             fmt_namespace(namespace.name),
             class_name_for_data_type(value.union_data_type),
             fmt_var(value.tag_name))
     else:
         return fmt_obj(value)
Beispiel #16
0
 def _generate_python_value(self, ns, value):
     if is_tag_ref(value):
         ref = '{}.{}'.format(
             class_name_for_data_type(value.union_data_type),
             fmt_var(value.tag_name))
         if ns != value.union_data_type.namespace:
             ref = '%s.%s' % (value.union_data_type.namespace.name, ref)
         return ref
     else:
         return fmt_obj(value)
Beispiel #17
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()
Beispiel #18
0
 def _generate_python_value(self, ns, value):
     if is_tag_ref(value):
         ref = '{}.{}'.format(
             class_name_for_data_type(value.union_data_type),
             fmt_var(value.tag_name))
         if ns != value.union_data_type.namespace:
             ref = '%s.%s' % (value.union_data_type.namespace.name, ref)
         return ref
     else:
         return fmt_obj(value)
Beispiel #19
0
 def _generate_custom_annotation_instance(self, ns, annotation):
     """
     Generates code to construct an instance of an annotation type object
     with parameters from the specified annotation.
     """
     annotation_class = class_name_for_annotation_type(
         annotation.annotation_type, ns)
     return generate_func_call(
         annotation_class,
         kwargs=((fmt_var(k, True), self._generate_python_value(ns, v))
                 for k, v in annotation.kwargs.items()))
Beispiel #20
0
    def _generate_struct_class_slots(self, data_type):
        """Creates a slots declaration for struct classes.

        Slots are an optimization in Python. They reduce the memory footprint
        of instances since attributes cannot be added after declaration.
        """
        with self.block('__slots__ =', delim=('[', ']')):
            for field in data_type.fields:
                field_name = fmt_var(field.name)
                self.emit("'_%s_value'," % field_name)
        self.emit()
Beispiel #21
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()
Beispiel #22
0
    def _generate_annotation_type_class_properties(self, ns, annotation_type):
        # type: (ApiNamespace, AnnotationType) -> None
        for param in annotation_type.params:
            prop_name = fmt_var(param.name, True)
            param_type = self.map_stone_type_to_pep484_type(ns, param.data_type)

            self.emit('@property')
            self.emit('def {prop_name}(self) -> {param_type}: ...'.format(
                prop_name=prop_name,
                param_type=param_type,
            ))
            self.emit()
Beispiel #23
0
    def _generate_struct_class_slots(self, data_type):
        """Creates a slots declaration for struct classes.

        Slots are an optimization in Python. They reduce the memory footprint
        of instances since attributes cannot be added after declaration.
        """
        with self.block('__slots__ =', delim=('[', ']')):
            for field in data_type.fields:
                field_name = fmt_var(field.name)
                self.emit("'_%s_value'," % field_name)
                self.emit("'_%s_present'," % field_name)
        self.emit()
Beispiel #24
0
    def _generate_annotation_type_class_properties(self, ns, annotation_type):
        # type: (ApiNamespace, AnnotationType) -> None
        for param in annotation_type.params:
            prop_name = fmt_var(param.name, True)
            param_type = self.map_stone_type_to_pep484_type(ns, param.data_type)

            self.emit('@property')
            self.emit('def {prop_name}(self) -> {param_type}: ...'.format(
                prop_name=prop_name,
                param_type=param_type,
            ))
            self.emit()
Beispiel #25
0
    def _generate_namespace_module(self, namespace):
        for data_type in namespace.linearize_data_types():
            if not is_struct_type(data_type):
                # Only handle user-defined structs (avoid unions and primitives)
                continue

            # Define a class for each struct
            class_def = 'class {}(object):'.format(fmt_class(data_type.name))
            self.emit(class_def)

            with self.indent():
                if data_type.doc:
                    self.emit('"""')
                    self.emit_wrapped_text(data_type.doc)
                    self.emit('"""')

                self.emit()

                # Define constructor to take each field
                args = ['self']
                for field in data_type.fields:
                    args.append(fmt_var(field.name))
                self.generate_multiline_list(args, 'def __init__', ':')

                with self.indent():
                    if data_type.fields:
                        self.emit()
                        # Body of init should assign all init vars
                        for field in data_type.fields:
                            if field.doc:
                                self.emit_wrapped_text(field.doc, '# ', '# ')
                            member_name = fmt_var(field.name)
                            self.emit('self.{0} = {0}'.format(member_name))
                    else:
                        self.emit('pass')
            self.emit()
Beispiel #26
0
    def _generate_namespace_module(self, namespace):
        for data_type in namespace.linearize_data_types():
            if not is_struct_type(data_type):
                # Only handle user-defined structs (avoid unions and primitives)
                continue

            # Define a class for each struct
            class_def = 'class {}(object):'.format(fmt_class(data_type.name))
            self.emit(class_def)

            with self.indent():
                if data_type.doc:
                    self.emit('"""')
                    self.emit_wrapped_text(data_type.doc)
                    self.emit('"""')

                self.emit()

                # Define constructor to take each field
                args = ['self']
                for field in data_type.fields:
                    args.append(fmt_var(field.name))
                self.generate_multiline_list(args, 'def __init__', ':')

                with self.indent():
                    if data_type.fields:
                        self.emit()
                        # Body of init should assign all init vars
                        for field in data_type.fields:
                            if field.doc:
                                self.emit_wrapped_text(field.doc, '# ', '# ')
                            member_name = fmt_var(field.name)
                            self.emit('self.{0} = {0}'.format(member_name))
                    else:
                        self.emit('pass')
            self.emit()
Beispiel #27
0
    def _generate_struct_class_init(self, ns, struct):
        # type: (ApiNamespace, Struct) -> None
        args = []
        for field in struct.all_fields:
            field_name_reserved_check = fmt_var(field.name, True)
            field_type = self.map_stone_type_to_pep484_type(
                ns, field.data_type)
            args.append("{field_name}: {field_type} = ...".format(
                field_name=field_name_reserved_check,
                field_type=field_type,
            ))

        self.generate_multiline_list(before='def __init__',
                                     items=["self"] + args,
                                     after=' -> None: ...')
Beispiel #28
0
    def _generate_struct_class_init(self, ns, struct):
        # type: (ApiNamespace, Struct) -> None
        args = ["self"]
        for field in struct.all_fields:
            field_name_reserved_check = fmt_var(field.name, True)
            field_type = self.map_stone_type_to_pep484_type(ns, field.data_type)

            if field.has_default:
                self.import_tracker._register_typing_import('Optional')
                field_type = 'Optional[{}]'.format(field_type)

            args.append("{field_name}: {field_type} = ...".format(
                field_name=field_name_reserved_check,
                field_type=field_type))

        self.generate_multiline_list(args, before='def __init__', after=' -> None: ...')
Beispiel #29
0
    def _generate_struct_class_init(self, ns, struct):
        # type: (ApiNamespace, Struct) -> None
        args = ["self"]
        for field in struct.all_fields:
            field_name_reserved_check = fmt_var(field.name, True)
            field_type = self.map_stone_type_to_pep484_type(ns, field.data_type)

            if not is_nullable_type(field.data_type):
                self.import_tracker._register_typing_import('Optional')
                field_type = 'Optional[{}]'.format(field_type)

            args.append("{field_name}: {field_type} = ...".format(
                field_name=field_name_reserved_check,
                field_type=field_type))

        self.generate_multiline_list(args, before='def __init__', after=' -> None: ...')
Beispiel #30
0
    def _generate_annotation_type_class_init(self, ns, annotation_type):
        # type: (ApiNamespace, AnnotationType) -> None
        args = []
        for param in annotation_type.params:
            param_name = fmt_var(param.name, True)
            param_type = self.map_stone_type_to_pep484_type(
                ns, param.data_type)
            args.append("{param_name}: {param_type} = ...".format(
                param_name=param_name,
                param_type=param_type,
            ))

        self.generate_multiline_list(before='def __init__',
                                     items=["self"] + args,
                                     after=' -> None: ...')
        self.emit()
Beispiel #31
0
    def _generate_union_class_vars(self, ns, data_type):
        # type: (ApiNamespace, Union) -> None
        lineno = self.lineno

        # Generate stubs for class variables so that IDEs like PyCharms have an
        # easier time detecting their existence.
        for field in data_type.fields:
            if is_void_type(field.data_type):
                field_name = fmt_var(field.name)
                field_type = class_name_for_data_type(data_type, ns)
                self.emit('{field_name} = ...  # type: {field_type}'.format(
                    field_name=field_name,
                    field_type=field_type,
                ))

        if lineno != self.lineno:
            self.emit()
Beispiel #32
0
    def _generate_union_class_vars(self, ns, data_type):
        # type: (ApiNamespace, Union) -> None
        lineno = self.lineno

        # Generate stubs for class variables so that IDEs like PyCharms have an
        # easier time detecting their existence.
        for field in data_type.fields:
            if is_void_type(field.data_type):
                field_name = fmt_var(field.name)
                field_type = class_name_for_data_type(data_type, ns)
                self.emit('{field_name} = ...  # type: {field_type}'.format(
                    field_name=field_name,
                    field_type=field_type,
                ))

        if lineno != self.lineno:
            self.emit()
Beispiel #33
0
    def _generate_struct_class_init(self, ns, struct):
        # type: (ApiNamespace, Struct) -> None
        args = []
        for field in struct.all_fields:
            field_name_reserved_check = fmt_var(field.name, True)
            field_type = self.map_stone_type_to_pep484_type(ns, field.data_type)
            args.append(
                "{field_name}: {field_type} = ...".format(
                    field_name=field_name_reserved_check,
                    field_type=field_type,
                )
            )

        self.generate_multiline_list(
            before='def __init__',
            items=["self"] + args,
            after=' -> None: ...')
Beispiel #34
0
    def _generate_annotation_type_class_init(self, ns, annotation_type):
        # type: (ApiNamespace, AnnotationType) -> None
        args = ['self']
        for param in annotation_type.params:
            param_name = fmt_var(param.name, True)
            param_type = self.map_stone_type_to_pep484_type(ns, param.data_type)

            if not is_nullable_type(param.data_type):
                self.import_tracker._register_typing_import('Optional')
                param_type = 'Optional[{}]'.format(param_type)

            args.append(
                "{param_name}: {param_type} = ...".format(
                    param_name=param_name,
                    param_type=param_type))

        self.generate_multiline_list(args, before='def __init__', after=' -> None: ...')
        self.emit()
Beispiel #35
0
    def _generate_annotation_type_class_init(self, ns, annotation_type):
        # type: (ApiNamespace, AnnotationType) -> None
        args = ['self']
        for param in annotation_type.params:
            param_name = fmt_var(param.name, True)
            param_type = self.map_stone_type_to_pep484_type(ns, param.data_type)

            if not is_nullable_type(param.data_type):
                self.import_tracker._register_typing_import('Optional')
                param_type = 'Optional[{}]'.format(param_type)

            args.append(
                "{param_name}: {param_type} = ...".format(
                    param_name=param_name,
                    param_type=param_type))

        self.generate_multiline_list(args, before='def __init__', after=' -> None: ...')
        self.emit()
Beispiel #36
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()
Beispiel #37
0
    def _generate_union_class_vars(self, data_type):
        """
        Adds a _catch_all_ attribute to each class. Also, adds a placeholder
        attribute for the construction of union members of void type.
        """
        lineno = self.lineno
        if data_type.catch_all_field:
            self.emit("_catch_all = '%s'" % data_type.catch_all_field.name)
        elif not data_type.parent_type:
            self.emit('_catch_all = None')

        # Generate stubs for class variables so that IDEs like PyCharms have an
        # easier time detecting their existence.
        for field in data_type.fields:
            if is_void_type(field.data_type):
                field_name = fmt_var(field.name)
                self.emit('# Attribute is overwritten below the class definition')
                self.emit('{} = None'.format(field_name))

        if lineno != self.lineno:
            self.emit()
Beispiel #38
0
    def _generate_union_class_vars(self, data_type):
        """
        Adds a _catch_all_ attribute to each class. Also, adds a placeholder
        attribute for the construction of union members of void type.
        """
        lineno = self.lineno
        if data_type.catch_all_field:
            self.emit("_catch_all = '%s'" % data_type.catch_all_field.name)
        elif not data_type.parent_type:
            self.emit('_catch_all = None')

        # Generate stubs for class variables so that IDEs like PyCharms have an
        # easier time detecting their existence.
        for field in data_type.fields:
            if is_void_type(field.data_type):
                field_name = fmt_var(field.name)
                self.emit('# Attribute is overwritten below the class definition')
                self.emit('{} = None'.format(field_name))

        if lineno != self.lineno:
            self.emit()
Beispiel #39
0
    def _generate_struct_class_init(self, ns, struct):
        # type: (ApiNamespace, Struct) -> None
        args = []
        for field in struct.all_fields:
            field_name_reserved_check = fmt_var(field.name, True)
            field_type = self.map_stone_type_to_pep484_type(
                ns, field.data_type)

            # The constructor takes all possible fields as optional arguments
            if not is_nullable_type(field.data_type) and not is_void_type(
                    field.data_type):
                self.import_tracker._register_typing_import('Optional')
                field_type = 'Optional[{}]'.format(field_type)

            args.append("{field_name}: {field_type} = ...".format(
                field_name=field_name_reserved_check,
                field_type=field_type,
            ))

        self.generate_multiline_list(before='def __init__',
                                     items=["self"] + args,
                                     after=' -> None: ...')
Beispiel #40
0
    def _generate_struct_class(self, ns, data_type):
        # type: (ApiNamespace, Struct) -> None
        """Defines a Python class that represents a struct in Stone."""
        self.emit(self._class_declaration_for_type(ns, data_type))
        with self.indent():
            if data_type.has_documented_type_or_fields():
                self.emit('"""')
                if data_type.doc:
                    self.emit_wrapped_text(
                        self.process_doc(data_type.doc, self._docf))
                    if data_type.has_documented_fields():
                        self.emit()
                for field in data_type.fields:
                    if not field.doc:
                        continue
                    self.emit_wrapped_text(':ivar {}: {}'.format(
                        fmt_var(field.name),
                        self.process_doc(field.doc, self._docf)),
                                           subsequent_prefix='    ')
                self.emit('"""')
            self.emit()

            self._generate_struct_class_slots(data_type)
            self._generate_struct_class_has_required_fields(data_type)
            self._generate_struct_class_init(data_type)
            self._generate_struct_class_properties(ns, data_type)
            self._generate_struct_class_repr(data_type)
        if data_type.has_enumerated_subtypes():
            validator = 'StructTree'
        else:
            validator = 'Struct'
        self.emit('{0}_validator = bv.{1}({0})'.format(
            class_name_for_data_type(data_type),
            validator,
        ))
        self.emit()
Beispiel #41
0
    def _generate_struct_class(self, ns, data_type):
        # type: (ApiNamespace, Struct) -> None
        """Defines a Python class that represents a struct in Stone."""
        self.emit(self._class_declaration_for_type(ns, data_type))
        with self.indent():
            if data_type.has_documented_type_or_fields():
                self.emit('"""')
                if data_type.doc:
                    self.emit_wrapped_text(
                        self.process_doc(data_type.doc, self._docf))
                    if data_type.has_documented_fields():
                        self.emit()
                for field in data_type.fields:
                    if not field.doc:
                        continue
                    self.emit_wrapped_text(':ivar {}: {}'.format(
                        fmt_var(field.name),
                        self.process_doc(field.doc, self._docf)),
                        subsequent_prefix='    ')
                self.emit('"""')
            self.emit()

            self._generate_struct_class_slots(data_type)
            self._generate_struct_class_has_required_fields(data_type)
            self._generate_struct_class_init(data_type)
            self._generate_struct_class_properties(ns, data_type)
            self._generate_struct_class_repr(data_type)
        if data_type.has_enumerated_subtypes():
            validator = 'StructTree'
        else:
            validator = 'Struct'
        self.emit('{0}_validator = bv.{1}({0})'.format(
            class_name_for_data_type(data_type),
            validator,
        ))
        self.emit()
Beispiel #42
0
    def _generate_struct_class_reflection_attributes(self, ns, data_type):
        """
        Generates two class attributes:
          * _all_field_names_: Set of all field names including inherited fields.
          * _all_fields_: List of tuples, where each tuple is (name, validator).

        If a struct has enumerated subtypes, then two additional attributes are
        generated:
          * _field_names_: Set of all field names excluding inherited fields.
          * _fields: List of tuples, where each tuple is (name, validator), and
            excludes inherited fields.

        These are needed because serializing a struct with enumerated subtypes
        requires knowing the fields defined in each level of the hierarchy.
        """

        class_name = class_name_for_data_type(data_type)
        if data_type.parent_type:
            parent_type_class_name = class_name_for_data_type(
                data_type.parent_type, ns)
        else:
            parent_type_class_name = None

        for field in data_type.fields:
            field_name = fmt_var(field.name)
            validator_name = generate_validator_constructor(ns, field.data_type)
            full_validator_name = '{}._{}_validator'.format(class_name, field_name)
            self.emit('{} = {}'.format(full_validator_name, validator_name))
            if field.redactor:
                self._generate_redactor(full_validator_name, field.redactor)

        # Generate `_all_field_names_` and `_all_fields_` for every omitted caller (and public).
        # As an edge case, we union omitted callers with None in the case when the object has no
        # public fields, as we still need to generate public attributes (`_field_names_` etc)
        child_omitted_callers = data_type.get_all_omitted_callers() | {None}
        parent_omitted_callers = data_type.parent_type.get_all_omitted_callers() if \
            data_type.parent_type else set([])

        for omitted_caller in child_omitted_callers | parent_omitted_callers:
            is_public = omitted_caller is None
            map_name_prefix = '' if is_public else '_{}'.format(omitted_caller)
            caller_in_parent = data_type.parent_type and (is_public or omitted_caller
                                                         in parent_omitted_callers)

            # generate `_all_field_names_`
            names_map_name = '{}_field_names_'.format(map_name_prefix)
            all_names_map_name = '_all{}_field_names_'.format(map_name_prefix)
            if data_type.is_member_of_enumerated_subtypes_tree():
                if is_public or omitted_caller in child_omitted_callers:
                    self.generate_multiline_list(
                        [
                            "'%s'" % field.name
                            for field in data_type.fields
                            if field.omitted_caller == omitted_caller
                        ],
                        before='{}.{} = set('.format(class_name, names_map_name),
                        after=')',
                        delim=('[', ']'),
                        compact=False)
                if caller_in_parent:
                    self.emit('{0}.{3} = {1}.{3}.union({0}.{2})'
                              .format(class_name, parent_type_class_name, names_map_name,
                                      all_names_map_name))
                else:
                    self.emit('{0}.{2} = {0}.{1}'.format(class_name, names_map_name,
                                                         all_names_map_name))
            else:
                if caller_in_parent:
                    before = '{0}.{1} = {2}.{1}.union(set('.format(class_name, all_names_map_name,
                                                                   parent_type_class_name)
                    after = '))'
                else:
                    before = '{}.{} = set('.format(class_name, all_names_map_name)
                    after = ')'
                items = [
                    "'%s'" % field.name
                    for field in data_type.fields
                    if field.omitted_caller == omitted_caller
                ]
                self.generate_multiline_list(
                    items,
                    before=before,
                    after=after,
                    delim=('[', ']'),
                    compact=False)

            # generate `_all_fields_`
            fields_map_name = '{}_fields_'.format(map_name_prefix)
            all_fields_map_name = '_all{}_fields_'.format(map_name_prefix)
            if data_type.is_member_of_enumerated_subtypes_tree():
                items = []
                for field in data_type.fields:
                    if field.omitted_caller != omitted_caller:
                        continue

                    var_name = fmt_var(field.name)
                    validator_name = '{}._{}_validator'.format(class_name,
                                                               var_name)
                    items.append("('{}', {})".format(var_name, validator_name))
                self.generate_multiline_list(
                    items,
                    before='{}.{} = '.format(class_name, fields_map_name),
                    delim=('[', ']'),
                    compact=False,
                )
                if caller_in_parent:
                    self.emit('{0}.{3} = {1}.{3} + {0}.{2}'.format(
                        class_name, parent_type_class_name, fields_map_name, all_fields_map_name))
                else:
                    self.emit('{0}.{2} = {0}.{1}'.format(
                        class_name, fields_map_name, all_fields_map_name))
            else:
                if caller_in_parent:
                    before = '{0}.{2} = {1}.{2} + '.format(
                        class_name, parent_type_class_name, all_fields_map_name)
                else:
                    before = '{}.{} = '.format(class_name, all_fields_map_name)

                items = []
                for field in data_type.fields:
                    if field.omitted_caller != omitted_caller:
                        continue

                    var_name = fmt_var(field.name)
                    validator_name = '{}._{}_validator'.format(
                        class_name, var_name)
                    items.append("('{}', {})".format(var_name, validator_name))
                self.generate_multiline_list(
                    items, before=before, delim=('[', ']'), compact=False)

        self.emit()
Beispiel #43
0
    def _generate_struct_class_reflection_attributes(self, ns, data_type):
        """
        Generates two class attributes:
          * _all_field_names_: Set of all field names including inherited fields.
          * _all_fields_: List of tuples, where each tuple is (name, validator).

        If a struct has enumerated subtypes, then two additional attributes are
        generated:
          * _field_names_: Set of all field names excluding inherited fields.
          * _fields: List of tuples, where each tuple is (name, validator), and
            excludes inherited fields.

        These are needed because serializing a struct with enumerated subtypes
        requires knowing the fields defined in each level of the hierarchy.
        """

        class_name = class_name_for_data_type(data_type)
        if data_type.parent_type:
            parent_type_class_name = class_name_for_data_type(
                data_type.parent_type, ns)
        else:
            parent_type_class_name = None

        for field in data_type.fields:
            field_name = fmt_var(field.name)
            validator_name = generate_validator_constructor(
                ns, field.data_type)
            full_validator_name = '{}._{}_validator'.format(
                class_name, field_name)
            self.emit('{} = {}'.format(full_validator_name, validator_name))
            if field.redactor:
                self._generate_redactor(full_validator_name, field.redactor)

        # Generate `_all_field_names_` and `_all_fields_` for every omitted caller (and public).
        # As an edge case, we union omitted callers with None in the case when the object has no
        # public fields, as we still need to generate public attributes (`_field_names_` etc)
        child_omitted_callers = data_type.get_all_omitted_callers() | {None}
        parent_omitted_callers = data_type.parent_type.get_all_omitted_callers() if \
            data_type.parent_type else set([])

        for omitted_caller in child_omitted_callers | parent_omitted_callers:
            is_public = omitted_caller is None
            map_name_prefix = '' if is_public else '_{}'.format(omitted_caller)
            caller_in_parent = data_type.parent_type and (
                is_public or omitted_caller in parent_omitted_callers)

            # generate `_all_field_names_`
            names_map_name = '{}_field_names_'.format(map_name_prefix)
            all_names_map_name = '_all{}_field_names_'.format(map_name_prefix)
            if data_type.is_member_of_enumerated_subtypes_tree():
                if is_public or omitted_caller in child_omitted_callers:
                    self.generate_multiline_list([
                        "'%s'" % field.name for field in data_type.fields
                        if field.omitted_caller == omitted_caller
                    ],
                                                 before='{}.{} = set('.format(
                                                     class_name,
                                                     names_map_name),
                                                 after=')',
                                                 delim=('[', ']'),
                                                 compact=False)
                if caller_in_parent:
                    self.emit('{0}.{3} = {1}.{3}.union({0}.{2})'.format(
                        class_name, parent_type_class_name, names_map_name,
                        all_names_map_name))
                else:
                    self.emit('{0}.{2} = {0}.{1}'.format(
                        class_name, names_map_name, all_names_map_name))
            else:
                if caller_in_parent:
                    before = '{0}.{1} = {2}.{1}.union(set('.format(
                        class_name, all_names_map_name, parent_type_class_name)
                    after = '))'
                else:
                    before = '{}.{} = set('.format(class_name,
                                                   all_names_map_name)
                    after = ')'
                items = [
                    "'%s'" % field.name for field in data_type.fields
                    if field.omitted_caller == omitted_caller
                ]
                self.generate_multiline_list(items,
                                             before=before,
                                             after=after,
                                             delim=('[', ']'),
                                             compact=False)

            # generate `_all_fields_`
            fields_map_name = '{}_fields_'.format(map_name_prefix)
            all_fields_map_name = '_all{}_fields_'.format(map_name_prefix)
            if data_type.is_member_of_enumerated_subtypes_tree():
                items = []
                for field in data_type.fields:
                    if field.omitted_caller != omitted_caller:
                        continue

                    var_name = fmt_var(field.name)
                    validator_name = '{}._{}_validator'.format(
                        class_name, var_name)
                    items.append("('{}', {})".format(var_name, validator_name))
                self.generate_multiline_list(
                    items,
                    before='{}.{} = '.format(class_name, fields_map_name),
                    delim=('[', ']'),
                    compact=False,
                )
                if caller_in_parent:
                    self.emit('{0}.{3} = {1}.{3} + {0}.{2}'.format(
                        class_name, parent_type_class_name, fields_map_name,
                        all_fields_map_name))
                else:
                    self.emit('{0}.{2} = {0}.{1}'.format(
                        class_name, fields_map_name, all_fields_map_name))
            else:
                if caller_in_parent:
                    before = '{0}.{2} = {1}.{2} + '.format(
                        class_name, parent_type_class_name,
                        all_fields_map_name)
                else:
                    before = '{}.{} = '.format(class_name, all_fields_map_name)

                items = []
                for field in data_type.fields:
                    if field.omitted_caller != omitted_caller:
                        continue

                    var_name = fmt_var(field.name)
                    validator_name = '{}._{}_validator'.format(
                        class_name, var_name)
                    items.append("('{}', {})".format(var_name, validator_name))
                self.generate_multiline_list(items,
                                             before=before,
                                             delim=('[', ']'),
                                             compact=False)

        self.emit()
Beispiel #44
0
    def _generate_struct_class_reflection_attributes(self, ns, data_type):
        """
        Generates two class attributes:
          * _all_field_names_: Set of all field names including inherited fields.
          * _all_fields_: List of tuples, where each tuple is (name, validator).

        If a struct has enumerated subtypes, then two additional attributes are
        generated:
          * _field_names_: Set of all field names excluding inherited fields.
          * _fields: List of tuples, where each tuple is (name, validator), and
            excludes inherited fields.

        These are needed because serializing a struct with enumerated subtypes
        requires knowing the fields defined in each level of the hierarchy.
        """

        class_name = class_name_for_data_type(data_type)
        if data_type.parent_type:
            parent_type_class_name = class_name_for_data_type(
                data_type.parent_type, ns)
        else:
            parent_type_class_name = None

        for field in data_type.fields:
            field_name = fmt_var(field.name)
            validator_name = generate_validator_constructor(
                ns, field.data_type)
            self.emit('{}._{}_validator = {}'.format(class_name, field_name,
                                                     validator_name))

        if data_type.is_member_of_enumerated_subtypes_tree():
            self.generate_multiline_list(
                ["'%s'" % field.name for field in data_type.fields],
                before='{}._field_names_ = set('.format(class_name),
                after=')',
                delim=('[', ']'),
                compact=False)
            if parent_type_class_name:
                self.emit(
                    '{0}._all_field_names_ = '
                    '{1}._all_field_names_.union({0}._field_names_)'.format(
                        class_name, parent_type_class_name))
            else:
                self.emit('{0}._all_field_names_ = {0}._field_names_'.format(
                    class_name))
        else:
            if parent_type_class_name:
                before = ('{}._all_field_names_ = '
                          '{}._all_field_names_.union(set(').format(
                              class_name, parent_type_class_name)
                after = '))'
            else:
                before = '{}._all_field_names_ = set('.format(class_name)
                after = ')'
            self.generate_multiline_list(
                ["'%s'" % field.name for field in data_type.fields],
                before=before,
                after=after,
                delim=('[', ']'),
                compact=False)

        if data_type.is_member_of_enumerated_subtypes_tree():
            items = []
            for field in data_type.fields:
                var_name = fmt_var(field.name)
                validator_name = '{}._{}_validator'.format(
                    class_name, var_name)
                items.append("('{}', {})".format(var_name, validator_name))
            self.generate_multiline_list(
                items,
                before='{}._fields_ = '.format(class_name),
                delim=('[', ']'),
                compact=False,
            )
            if parent_type_class_name:
                self.emit('{0}._all_fields_ = '
                          '{1}._all_fields_ + {0}._fields_'.format(
                              class_name, parent_type_class_name))
            else:
                self.emit('{0}._all_fields_ = {0}._fields_'.format(class_name))
        else:
            if parent_type_class_name:
                before = '{}._all_fields_ = {}._all_fields_ + '.format(
                    class_name, parent_type_class_name)
            else:
                before = '{}._all_fields_ = '.format(class_name)
            items = []
            for field in data_type.fields:
                var_name = fmt_var(field.name)
                validator_name = '{}._{}_validator'.format(
                    class_name, var_name)
                items.append("('{}', {})".format(var_name, validator_name))
            self.generate_multiline_list(items,
                                         before=before,
                                         delim=('[', ']'),
                                         compact=False)

        self.emit()
Beispiel #45
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 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(
                        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(namespace.name, fmt_var(route.name)),
                "'{}'".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()
Beispiel #46
0
    def _generate_struct_class_reflection_attributes(self, ns, data_type):
        """
        Generates two class attributes:
          * _all_field_names_: Set of all field names including inherited fields.
          * _all_fields_: List of tuples, where each tuple is (name, validator).

        If a struct has enumerated subtypes, then two additional attributes are
        generated:
          * _field_names_: Set of all field names excluding inherited fields.
          * _fields: List of tuples, where each tuple is (name, validator), and
            excludes inherited fields.

        These are needed because serializing a struct with enumerated subtypes
        requires knowing the fields defined in each level of the hierarchy.
        """

        class_name = class_name_for_data_type(data_type)
        if data_type.parent_type:
            parent_type_class_name = class_name_for_data_type(
                data_type.parent_type, ns)
        else:
            parent_type_class_name = None

        for field in data_type.fields:
            field_name = fmt_var(field.name)
            validator_name = generate_validator_constructor(ns, field.data_type)
            self.emit('{}._{}_validator = {}'.format(
                class_name, field_name, validator_name))

        if data_type.is_member_of_enumerated_subtypes_tree():
            self.generate_multiline_list(
                ["'%s'" % field.name for field in data_type.fields],
                before='{}._field_names_ = set('.format(class_name),
                after=')',
                delim=('[', ']'),
                compact=False)
            if parent_type_class_name:
                self.emit(
                    '{0}._all_field_names_ = '
                    '{1}._all_field_names_.union({0}._field_names_)'
                    .format(class_name, parent_type_class_name))
            else:
                self.emit('{0}._all_field_names_ = {0}._field_names_'.format(
                    class_name))
        else:
            if parent_type_class_name:
                before = (
                    '{}._all_field_names_ = '
                    '{}._all_field_names_.union(set(').format(
                    class_name, parent_type_class_name)
                after = '))'
            else:
                before = '{}._all_field_names_ = set('.format(class_name)
                after = ')'
            self.generate_multiline_list(
                ["'%s'" % field.name for field in data_type.fields],
                before=before,
                after=after,
                delim=('[', ']'),
                compact=False)

        if data_type.is_member_of_enumerated_subtypes_tree():
            items = []
            for field in data_type.fields:
                var_name = fmt_var(field.name)
                validator_name = '{}._{}_validator'.format(class_name,
                                                           var_name)
                items.append("('{}', {})".format(var_name, validator_name))
            self.generate_multiline_list(
                items,
                before='{}._fields_ = '.format(class_name),
                delim=('[', ']'),
                compact=False,
            )
            if parent_type_class_name:
                self.emit(
                    '{0}._all_fields_ = '
                    '{1}._all_fields_ + {0}._fields_'.format(
                        class_name, parent_type_class_name))
            else:
                self.emit('{0}._all_fields_ = {0}._fields_'.format(class_name))
        else:
            if parent_type_class_name:
                before = '{}._all_fields_ = {}._all_fields_ + '.format(
                    class_name, parent_type_class_name)
            else:
                before = '{}._all_fields_ = '.format(class_name)
            items = []
            for field in data_type.fields:
                var_name = fmt_var(field.name)
                validator_name = '{}._{}_validator'.format(
                    class_name, var_name)
                items.append("('{}', {})".format(var_name, validator_name))
            self.generate_multiline_list(
                items, before=before, delim=('[', ']'), compact=False)

        self.emit()