Exemple #1
0
    def _get_imports_h(self, data_types):
        """Emits all necessary header file imports for the given Stone data type."""
        if not isinstance(data_types, list):
            data_types = [data_types]

        import_classes = []

        for data_type in data_types:

            if is_user_defined_type(data_type):
                import_classes.append(fmt_class_prefix(data_type))

            for field in data_type.all_fields:
                data_type, _ = unwrap_nullable(field.data_type)

                # unpack list
                while is_list_type(data_type):
                    data_type = data_type.data_type

                if is_user_defined_type(data_type):
                    import_classes.append(fmt_class_prefix(data_type))

        import_classes = list(set(import_classes))
        import_classes.sort()

        return import_classes
Exemple #2
0
    def _get_imports_h(self, data_types):
        """Emits all necessary header file imports for the given Stone data type."""
        if not isinstance(data_types, list):
            data_types = [data_types]

        import_classes = []

        for data_type in data_types:

            if is_user_defined_type(data_type):
                import_classes.append(fmt_class_prefix(data_type))

            for field in data_type.all_fields:
                data_type, _ = unwrap_nullable(field.data_type)

                # unpack list
                while is_list_type(data_type):
                    data_type = data_type.data_type

                if is_user_defined_type(data_type):
                    import_classes.append(fmt_class_prefix(data_type))

        import_classes = list(set(import_classes))
        import_classes.sort()

        return import_classes
Exemple #3
0
    def block_h_from_data_type(self, data_type, protocol=None):
        assert is_user_defined_type(data_type), \
            'Expected user-defined type, got %r' % type(data_type)

        if not protocol:
            extensions = []
            if data_type.parent_type and is_struct_type(data_type):
                extensions.append(fmt_class_prefix(data_type.parent_type))
            else:
                if is_union_type(data_type):
                    # Use a handwritten base class
                    extensions.append('NSObject')
                else:
                    extensions.append('NSObject')

            extend_suffix = ' : {}'.format(
                ', '.join(extensions)) if extensions else ''
        else:
            base = fmt_class_prefix(data_type.parent_type) if (
                data_type.parent_type
                and not is_union_type(data_type)) else 'NSObject'
            extend_suffix = ' : {} <{}>'.format(base, ', '.join(protocol))
        with self.block('@interface {}{}'.format(fmt_class_prefix(data_type),
                                                 extend_suffix),
                        delim=('', '@end'),
                        dent=0):
            self.emit()
            yield
 def _python_type_mapping(self, ns, data_type):
     """Map Stone data types to their most natural equivalent in Python
     for documentation purposes."""
     if is_string_type(data_type):
         return 'str'
     elif is_bytes_type(data_type):
         return 'bytes'
     elif is_boolean_type(data_type):
         return 'bool'
     elif is_float_type(data_type):
         return 'float'
     elif is_integer_type(data_type):
         return 'long'
     elif is_void_type(data_type):
         return 'None'
     elif is_timestamp_type(data_type):
         return 'datetime.datetime'
     elif is_alias(data_type):
         return self._python_type_mapping(ns, data_type.data_type)
     elif is_user_defined_type(data_type):
         class_name = class_name_for_data_type(data_type)
         if data_type.namespace.name != ns.name:
             return '%s.%s_validator' % (
                 data_type.namespace.name, class_name)
         else:
             return class_name
     elif is_list_type(data_type):
         # PyCharm understands this description format for a list
         return 'list of [{}]'.format(self._python_type_mapping(
             ns, data_type.data_type))
     elif is_nullable_type(data_type):
         return 'Optional[{}]'.format(
             self._python_type_mapping(ns, data_type.data_type))
     else:
         raise TypeError('Unknown data type %r' % data_type)
Exemple #5
0
    def _get_imports_m(self, data_types, default_imports):
        """Emits all necessary implementation file imports for the given Stone data type."""
        if not isinstance(data_types, list):
            data_types = [data_types]

        import_classes = default_imports

        for data_type in data_types:
            import_classes.append(fmt_class_prefix(data_type))

            if data_type.parent_type:
                import_classes.append(fmt_class_prefix(data_type.parent_type))

            if is_struct_type(data_type) and data_type.has_enumerated_subtypes():
                for _, subtype in data_type.get_all_subtypes_with_tags():
                    import_classes.append(fmt_class_prefix(subtype))

            for field in data_type.all_fields:
                data_type, _ = unwrap_nullable(field.data_type)

                # unpack list
                while is_list_type(data_type):
                    data_type = data_type.data_type

                if is_user_defined_type(data_type):
                    import_classes.append(fmt_class_prefix(data_type))

        if import_classes:
            import_classes = list(set(import_classes))
            import_classes.sort()

        return import_classes
Exemple #6
0
    def _fmt_default(self, data_type):
        data_type, nullable = unwrap_nullable(data_type)

        result = 'DEFAULT'

        if nullable:
            return 'nil'

        if is_user_defined_type(data_type):
            result = fmt_func_call(fmt_alloc_call(fmt_class_prefix(data_type)),
                                   'init', [])
        elif is_list_type(data_type):
            result = fmt_func_call(fmt_alloc_call('NSArray'), 'init', [])
        elif is_numeric_type(data_type):
            if is_float_type(data_type):
                result = '[NSNumber numberWithDouble:5]'
            else:
                result = '[NSNumber numberWithInt:5]'
        elif is_timestamp_type(data_type):
            result = '[[NSDateFormatter new] setDateFormat:[self convertFormat:@"test"]]'
        elif is_string_type(data_type):
            result = '@"teststring"'
        elif is_boolean_type(data_type):
            result = '@YES'

        return result
Exemple #7
0
    def _get_imports_m(self, data_types, default_imports):
        """Emits all necessary implementation file imports for the given Stone data type."""
        if not isinstance(data_types, list):
            data_types = [data_types]

        import_classes = default_imports

        for data_type in data_types:
            import_classes.append(fmt_class_prefix(data_type))

            if data_type.parent_type:
                import_classes.append(fmt_class_prefix(data_type.parent_type))

            if is_struct_type(
                    data_type) and data_type.has_enumerated_subtypes():
                for tags, subtype in data_type.get_all_subtypes_with_tags():
                    import_classes.append(fmt_class_prefix(subtype))

            for field in data_type.all_fields:
                data_type, _ = unwrap_nullable(field.data_type)

                # unpack list
                while is_list_type(data_type):
                    data_type = data_type.data_type

                if is_user_defined_type(data_type):
                    import_classes.append(fmt_class_prefix(data_type))

        if import_classes:
            import_classes = list(set(import_classes))
            import_classes.sort()

        return import_classes
Exemple #8
0
 def _python_type_mapping(self, ns, data_type):
     """Map Stone data types to their most natural equivalent in Python
     for documentation purposes."""
     if is_string_type(data_type):
         return 'str'
     elif is_bytes_type(data_type):
         return 'bytes'
     elif is_boolean_type(data_type):
         return 'bool'
     elif is_float_type(data_type):
         return 'float'
     elif is_integer_type(data_type):
         return 'long'
     elif is_void_type(data_type):
         return 'None'
     elif is_timestamp_type(data_type):
         return 'datetime.datetime'
     elif is_alias(data_type):
         return self._python_type_mapping(ns, data_type.data_type)
     elif is_user_defined_type(data_type):
         class_name = class_name_for_data_type(data_type)
         if data_type.namespace.name != ns.name:
             return '%s.%s_validator' % (
                 data_type.namespace.name, class_name)
         else:
             return class_name
     elif is_list_type(data_type):
         # PyCharm understands this description format for a list
         return 'list of [{}]'.format(self._python_type_mapping(
             ns, data_type.data_type))
     elif is_nullable_type(data_type):
         return 'Optional[{}]'.format(
             self._python_type_mapping(ns, data_type.data_type))
     else:
         raise TypeError('Unknown data type %r' % data_type)
Exemple #9
0
    def block_h_from_data_type(self, data_type, protocol=None):
        assert is_user_defined_type(data_type), \
            'Expected user-defined type, got %r' % type(data_type)

        if not protocol:
            extensions = []
            if data_type.parent_type and is_struct_type(data_type):
                extensions.append(fmt_class_prefix(data_type.parent_type))
            else:
                if is_union_type(data_type):
                    # Use a handwritten base class
                    extensions.append('NSObject')
                else:
                    extensions.append('NSObject')

            extend_suffix = ' : {}'.format(
                ', '.join(extensions)) if extensions else ''
        else:
            base = fmt_class_prefix(data_type.parent_type) if (
                data_type.parent_type and not is_union_type(data_type)) else 'NSObject'
            extend_suffix = ' : {} <{}>'.format(base, ', '.join(protocol))
        with self.block('@interface {}{}'.format(
                fmt_class_prefix(data_type), extend_suffix), delim=('', '@end'), dent=0):
            self.emit()
            yield
Exemple #10
0
        def _unpack_and_store_data_type(data_type):
            data_type, _ = unwrap_nullable(data_type)
            if is_list_type(data_type):
                while is_list_type(data_type):
                    data_type = data_type.data_type

            if not is_void_type(data_type) and is_user_defined_type(data_type):
                result.append(data_type)
Exemple #11
0
        def _unpack_and_store_data_type(data_type):
            data_type, _ = unwrap_nullable(data_type)
            if is_list_type(data_type):
                while is_list_type(data_type):
                    data_type = data_type.data_type

            if not is_void_type(data_type) and is_user_defined_type(data_type):
                result.append(data_type)
def map_stone_type_to_python_type(ns, data_type, override_dict=None):
    # type: (ApiNamespace, DataType, typing.Optional[OverrideDefaultTypesDict]) -> str
    """
    Args:
        override_dict: lets you override the default behavior for a given type by hooking into
            a callback. (Currently only hooked up for stone's List and Nullable)
    """
    override_dict = override_dict or {}

    if is_string_type(data_type):
        return 'str'
    elif is_bytes_type(data_type):
        return 'bytes'
    elif is_boolean_type(data_type):
        return 'bool'
    elif is_float_type(data_type):
        return 'float'
    elif is_integer_type(data_type):
        return 'long'
    elif is_void_type(data_type):
        return 'None'
    elif is_timestamp_type(data_type):
        timestamp_override = override_dict.get(Timestamp, None)
        if timestamp_override:
            return timestamp_override(ns, data_type, override_dict)
        return 'datetime.datetime'
    elif is_alias(data_type):
        alias_type = cast(Alias, data_type)
        return map_stone_type_to_python_type(ns, alias_type.data_type,
                                             override_dict)
    elif is_user_defined_type(data_type):
        user_defined_type = cast(UserDefined, data_type)
        class_name = class_name_for_data_type(user_defined_type)
        if user_defined_type.namespace.name != ns.name:
            return '%s.%s_validator' % (user_defined_type.namespace.name,
                                        class_name)
        else:
            return class_name
    elif is_list_type(data_type):
        list_type = cast(List, data_type)
        if List in override_dict:
            return override_dict[List](ns, list_type.data_type, override_dict)

        # PyCharm understands this description format for a list
        return 'list of [{}]'.format(
            map_stone_type_to_python_type(ns, list_type.data_type,
                                          override_dict))
    elif is_nullable_type(data_type):
        nullable_type = cast(Nullable, data_type)
        if Nullable in override_dict:
            return override_dict[Nullable](ns, nullable_type.data_type,
                                           override_dict)

        return 'Optional[{}]'.format(
            map_stone_type_to_python_type(ns, nullable_type.data_type,
                                          override_dict))
    else:
        raise TypeError('Unknown data type %r' % data_type)
 def _generate_alias_definition(self, namespace, alias):
     # type: (ApiNamespace, Alias) -> None
     unwrapped_dt, _ = unwrap_aliases(alias)
     if is_user_defined_type(unwrapped_dt):
         # If the alias is to a composite type, we want to alias the
         # generated class as well.
         self.emit('{} = {}'.format(
             alias.name, class_name_for_data_type(alias.data_type,
                                                  namespace)))
 def _generate_alias_definition(self, namespace, alias):
     # type: (ApiNamespace, Alias) -> None
     unwrapped_dt, _ = unwrap_aliases(alias)
     if is_user_defined_type(unwrapped_dt):
         # If the alias is to a composite type, we want to alias the
         # generated class as well.
         self.emit('{} = {}'.format(
             alias.name,
             class_name_for_data_type(alias.data_type, namespace)))
Exemple #15
0
def generate_validator_constructor(ns, data_type):
    """
    Given a Stone data type, returns a string that can be used to construct
    the appropriate validation object in Python.
    """
    dt, nullable_dt = unwrap_nullable(data_type)
    if is_list_type(dt):
        v = generate_func_call(
            'bv.List',
            args=[
                generate_validator_constructor(ns, dt.data_type)],
            kwargs=[
                ('min_items', dt.min_items),
                ('max_items', dt.max_items)],
        )
    elif is_numeric_type(dt):
        v = generate_func_call(
            'bv.{}'.format(dt.name),
            kwargs=[
                ('min_value', dt.min_value),
                ('max_value', dt.max_value)],
        )
    elif is_string_type(dt):
        pattern = None
        if dt.pattern is not None:
            pattern = repr(dt.pattern)
        v = generate_func_call(
            'bv.String',
            kwargs=[
                ('min_length', dt.min_length),
                ('max_length', dt.max_length),
                ('pattern', pattern)],
        )
    elif is_timestamp_type(dt):
        v = generate_func_call(
            'bv.Timestamp',
            args=[repr(dt.format)],
        )
    elif is_user_defined_type(dt):
        v = fmt_class(dt.name) + '_validator'
        if ns.name != dt.namespace.name:
            v = '{}.{}'.format(dt.namespace.name, v)
    elif is_alias(dt):
        # Assume that the alias has already been declared elsewhere.
        name = fmt_class(dt.name) + '_validator'
        if ns.name != dt.namespace.name:
            name = '{}.{}'.format(dt.namespace.name, name)
        v = name
    elif is_boolean_type(dt) or is_bytes_type(dt) or is_void_type(dt):
        v = generate_func_call('bv.{}'.format(dt.name))
    else:
        raise AssertionError('Unsupported data type: %r' % dt)

    if nullable_dt:
        return generate_func_call('bv.Nullable', args=[v])
    else:
        return v
def generate_validator_constructor(ns, data_type):
    """
    Given a Stone data type, returns a string that can be used to construct
    the appropriate validation object in Python.
    """
    dt, nullable_dt = unwrap_nullable(data_type)
    if is_list_type(dt):
        v = generate_func_call(
            'bv.List',
            args=[
                generate_validator_constructor(ns, dt.data_type)],
            kwargs=[
                ('min_items', dt.min_items),
                ('max_items', dt.max_items)],
        )
    elif is_numeric_type(dt):
        v = generate_func_call(
            'bv.{}'.format(dt.name),
            kwargs=[
                ('min_value', dt.min_value),
                ('max_value', dt.max_value)],
        )
    elif is_string_type(dt):
        pattern = None
        if dt.pattern is not None:
            pattern = repr(dt.pattern)
        v = generate_func_call(
            'bv.String',
            kwargs=[
                ('min_length', dt.min_length),
                ('max_length', dt.max_length),
                ('pattern', pattern)],
        )
    elif is_timestamp_type(dt):
        v = generate_func_call(
            'bv.Timestamp',
            args=[repr(dt.format)],
        )
    elif is_user_defined_type(dt):
        v = fmt_class(dt.name) + '_validator'
        if ns.name != dt.namespace.name:
            v = '{}.{}'.format(dt.namespace.name, v)
    elif is_alias(dt):
        # Assume that the alias has already been declared elsewhere.
        name = fmt_class(dt.name) + '_validator'
        if ns.name != dt.namespace.name:
            name = '{}.{}'.format(dt.namespace.name, name)
        v = name
    elif is_boolean_type(dt) or is_bytes_type(dt) or is_void_type(dt):
        v = generate_func_call('bv.{}'.format(dt.name))
    else:
        raise AssertionError('Unsupported data type: %r' % dt)

    if nullable_dt:
        return generate_func_call('bv.Nullable', args=[v])
    else:
        return v
Exemple #17
0
def fmt_serial_obj(data_type):
    data_type, nullable = unwrap_nullable(data_type)

    if is_user_defined_type(data_type):
        result = fmt_serial_class(fmt_class_prefix(data_type))
    else:
        result = _serial_table.get(data_type.__class__,
                                   fmt_class(data_type.name))

    return result
def fmt_serial_obj(data_type):
    data_type, _ = unwrap_nullable(data_type)

    if is_user_defined_type(data_type):
        result = fmt_serial_class(fmt_class_prefix(data_type))
    else:
        result = _serial_table.get(
            data_type.__class__, fmt_class(data_type.name))

    return result
Exemple #19
0
def fmt_route_type(data_type, tag=False, has_default=False):
    data_type, nullable = unwrap_nullable(data_type)

    if is_user_defined_type(data_type):
        result = '{} *'.format(fmt_class_prefix(data_type))
    else:
        result = _primitive_table_user_interface.get(data_type.__class__,
                                                     fmt_class(data_type.name))

        if is_list_type(data_type):
            data_type, _ = unwrap_nullable(data_type.data_type)
            result = result + '<{}> *'.format(fmt_type(data_type))

    if is_user_defined_type(data_type) and tag:
        if nullable or has_default:
            result += ' _Nullable'
        elif not is_void_type(data_type):
            result += ' _Nonnull'

    return result
def fmt_route_type(data_type, tag=False, has_default=False):
    data_type, nullable = unwrap_nullable(data_type)

    if is_user_defined_type(data_type):
        result = '{} *'.format(fmt_class_prefix(data_type))
    else:
        result = _primitive_table_user_interface.get(
            data_type.__class__, fmt_class(data_type.name))

        if is_list_type(data_type):
            data_type, _ = unwrap_nullable(data_type.data_type)
            result = result + '<{}> *'.format(fmt_type(data_type))

    if is_user_defined_type(data_type) and tag:
        if nullable or has_default:
            result += ' _Nullable'
        elif not is_void_type(data_type):
            result += ' _Nonnull'

    return result
Exemple #21
0
def fmt_type_name(data_type):
    """
    Returns the JSDoc name for the given data type.
    (Does not attempt to enumerate subtypes.)
    """
    if is_user_defined_type(data_type):
        return fmt_pascal('%s%s' % (data_type.namespace.name, data_type.name))
    else:
        fmted_type = _base_type_table.get(data_type.__class__, 'Object')
        if is_list_type(data_type):
            fmted_type += '.<' + fmt_type(data_type.data_type) + '>'
        return fmted_type
Exemple #22
0
    def _generate_route(self, route_schema, namespace, route, extra_args):
        function_name = fmt_func(namespace.name + '_' + route.name)
        self.emit()
        self.emit('/**')
        if route.doc:
            self.emit_wrapped_text(self.process_doc(route.doc, self._docf), prefix=' * ')
        if self.args.class_name:
            self.emit(' * @function {}#{}'.format(self.args.class_name,
                                                  function_name))
        if route.deprecated:
            self.emit(' * @deprecated')

        self.emit(' * @arg {%s} arg - The request parameters.' %
                  fmt_type(route.arg_data_type))
        if is_user_defined_type(route.arg_data_type):
            for attr_key in route.attrs:
                if attr_key not in extra_args:
                    continue
                attr_val = route.attrs[attr_key]
                if attr_val in extra_args[attr_key]:
                    arg_name, arg_type, arg_docstring = extra_args[attr_key][attr_val]
                    field_docstring = '@arg {%s} arg.%s' % (arg_type, arg_name)
                    if arg_docstring:
                        field_docstring += ' - %s' % arg_docstring
                    self.emit_wrapped_text(field_docstring, prefix=' * ')

            for field in route.arg_data_type.all_fields:
                field_doc = ' - ' + field.doc if field.doc else ''
                field_type, nullable, _ = unwrap(field.data_type)
                field_js_type = fmt_type(field_type)
                if nullable:
                    field_js_type += '|null'
                self.emit_wrapped_text(
                    '@arg {%s} arg.%s%s' %
                        (field_js_type, field.name,
                         self.process_doc(field_doc, self._docf)),
                    prefix=' * ')
        self.emit(' * @returns {%s}' % fmt_type(route.result_data_type))
        self.emit(' */')
        self.emit('routes.%s = function (arg) {' % function_name)
        with self.indent(dent=2):
            url = '{}/{}'.format(namespace.name, route.name)
            if route_schema.fields:
                additional_args = []
                for field in route_schema.fields:
                    additional_args.append(fmt_obj(route.attrs[field.name]))
                self.emit(
                    "return this.request('{}', arg, {});".format(
                        url, ', '.join(additional_args)))
            else:
                self.emit(
                    'return this.request("%s", arg);' % url)
        self.emit('};')
 def _format_type_in_doc(self, namespace, data_type):
     """
     Returns a string that can be recognized by Sphinx as a type reference
     in a docstring.
     """
     if is_void_type(data_type):
         return 'None'
     elif is_user_defined_type(data_type):
         return ':class:`{}.{}.{}`'.format(
             self.args.types_package, namespace.name, fmt_type(data_type))
     else:
         return fmt_type(data_type)
Exemple #24
0
def fmt_type_name(data_type):
    """
    Returns the JSDoc name for the given data type.
    (Does not attempt to enumerate subtypes.)
    """
    if is_user_defined_type(data_type):
        return fmt_pascal('%s%s' % (data_type.namespace.name, data_type.name))
    else:
        fmted_type = _base_type_table.get(data_type.__class__, 'Object')
        if is_list_type(data_type):
            fmted_type += '.<' + fmt_type(data_type.data_type) + '>'
        return fmted_type
Exemple #25
0
def fmt_type(data_type):
    data_type, nullable = unwrap_nullable(data_type)

    if is_user_defined_type(data_type):
        result = '{}.{}'.format(fmt_class(data_type.namespace.name),
                                fmt_class(data_type.name))
    else:
        result = _type_table.get(data_type.__class__, fmt_class(data_type.name))

        if is_list_type(data_type):
            result = result + '<{}>'.format(fmt_type(data_type.data_type))

    return result if not nullable else result + '?'
 def _generate_alias_definition(self, namespace, alias):
     v = generate_validator_constructor(namespace, alias.data_type)
     if alias.doc:
         self.emit_wrapped_text(
             self.process_doc(alias.doc, self._docf), prefix='# ')
     self.emit('{}_validator = {}'.format(alias.name, v))
     unwrapped_dt, _ = unwrap_aliases(alias)
     if is_user_defined_type(unwrapped_dt):
         # If the alias is to a composite type, we want to alias the
         # generated class as well.
         self.emit('{} = {}'.format(
             alias.name,
             class_name_for_data_type(alias.data_type, namespace)))
 def _class_declaration_for_type(self, ns, data_type):
     assert is_user_defined_type(data_type), \
         'Expected struct, got %r' % type(data_type)
     if data_type.parent_type:
         extends = class_name_for_data_type(data_type.parent_type, ns)
     else:
         if is_union_type(data_type):
             # Use a handwritten base class
             extends = 'bb.Union'
         else:
             extends = 'object'
     return 'class {}({}):'.format(
         class_name_for_data_type(data_type), extends)
Exemple #28
0
def fmt_type(data_type):
    data_type, nullable = unwrap_nullable(data_type)

    if is_user_defined_type(data_type):
        result = '{}.{}'.format(fmt_class(data_type.namespace.name),
                                fmt_class(data_type.name))
    else:
        result = _type_table.get(data_type.__class__, fmt_class(data_type.name))
        
        if is_list_type(data_type):
            result = result + '<{}>'.format(fmt_type(data_type.data_type))            
    
    return result if not nullable else result + '?'
Exemple #29
0
 def _format_type_in_doc(self, namespace, data_type):
     """
     Returns a string that can be recognized by Sphinx as a type reference
     in a docstring.
     """
     if is_void_type(data_type):
         return 'None'
     elif is_user_defined_type(data_type):
         return ':class:`{}.{}.{}`'.format(self.args.types_package,
                                           namespace.name,
                                           fmt_type(data_type))
     else:
         return fmt_type(data_type)
Exemple #30
0
 def _generate_alias_definition(self, namespace, alias):
     v = generate_validator_constructor(namespace, alias.data_type)
     if alias.doc:
         self.emit_wrapped_text(
             self.process_doc(alias.doc, self._docf), prefix='# ')
     self.emit('{}_validator = {}'.format(alias.name, v))
     unwrapped_dt, _ = unwrap_aliases(alias)
     if is_user_defined_type(unwrapped_dt):
         # If the alias is to a composite type, we want to alias the
         # generated class as well.
         self.emit('{} = {}'.format(
             alias.name,
             class_name_for_data_type(alias.data_type, namespace)))
Exemple #31
0
 def _class_declaration_for_type(self, ns, data_type):
     assert is_user_defined_type(data_type), \
         'Expected struct, got %r' % type(data_type)
     if data_type.parent_type:
         extends = class_name_for_data_type(data_type.parent_type, ns)
     else:
         if is_union_type(data_type):
             # Use a handwritten base class
             extends = 'bb.Union'
         else:
             extends = 'object'
     return 'class {}({}):'.format(
         class_name_for_data_type(data_type), extends)
Exemple #32
0
def fmt_class_type(data_type):
    data_type, nullable = unwrap_nullable(data_type)

    if is_user_defined_type(data_type):
        result = '{}'.format(fmt_class_prefix(data_type))
    else:
        result = _primitive_table.get(data_type.__class__,
                                      fmt_class(data_type.name))

        if is_list_type(data_type):
            data_type, _ = unwrap_nullable(data_type.data_type)
            result = result + '<{}>'.format(fmt_type(data_type))

    return result
    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()
Exemple #34
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()
Exemple #35
0
def fmt_type_name(data_type, inside_namespace=None):
    """
    Produces a TypeScript type name for the given data type.
    inside_namespace should be set to the namespace that the reference
    occurs in, or None if this parameter is not relevant.
    """
    if is_user_defined_type(data_type) or is_alias(data_type):
        if data_type.namespace == inside_namespace:
            return data_type.name
        else:
            return '%s.%s' % (data_type.namespace.name, data_type.name)
    else:
        fmted_type = _base_type_table.get(data_type.__class__, 'Object')
        if is_list_type(data_type):
            fmted_type += '<' + fmt_type(data_type.data_type, inside_namespace) + '>'
        return fmted_type
def class_name_for_data_type(data_type, ns=None):
    """
    Returns the name of the Python class that maps to a user-defined type.
    The name is identical to the name in the spec.

    If ``ns`` is set to a Namespace and the namespace of `data_type` does
    not match, then a namespace prefix is added to the returned name.
    For example, ``foreign_ns.TypeName``.
    """
    assert is_user_defined_type(data_type) or is_alias(data_type), \
        'Expected composite type, got %r' % type(data_type)
    name = fmt_class(data_type.name)
    if ns and data_type.namespace != ns:
        # If from an imported namespace, add a namespace prefix.
        name = '{}.{}'.format(data_type.namespace.name, name)
    return name
Exemple #37
0
def class_name_for_data_type(data_type, ns=None):
    """
    Returns the name of the Python class that maps to a user-defined type.
    The name is identical to the name in the spec.

    If ``ns`` is set to a Namespace and the namespace of `data_type` does
    not match, then a namespace prefix is added to the returned name.
    For example, ``foreign_ns.TypeName``.
    """
    assert is_user_defined_type(data_type) or is_alias(data_type), \
        'Expected composite type, got %r' % type(data_type)
    name = fmt_class(data_type.name)
    if ns and data_type.namespace != ns:
        # If from an imported namespace, add a namespace prefix.
        name = '{}.{}'.format(data_type.namespace.name, name)
    return name
Exemple #38
0
def fmt_type_name(data_type, inside_namespace=None):
    """
    Produces a TypeScript type name for the given data type.
    inside_namespace should be set to the namespace that the reference
    occurs in, or None if this parameter is not relevant.
    """
    if is_user_defined_type(data_type) or is_alias(data_type):
        if data_type.namespace == inside_namespace:
            return data_type.name
        else:
            return '%s.%s' % (data_type.namespace.name, data_type.name)
    else:
        fmted_type = _base_type_table.get(data_type.__class__, 'Object')
        if is_list_type(data_type):
            fmted_type += '<' + fmt_type(data_type.data_type,
                                         inside_namespace) + '>'
        return fmted_type
Exemple #39
0
    def _swift_type_mapping(self, data_type, serializer=False):
        suffix = 'Serializer' if serializer else ''
        if is_nullable_type(data_type):
            data_type = data_type.data_type
            nullable = True
        else:
            nullable = False
        if is_list_type(data_type):
            ret = 'Array{}<{}>'.format(
                suffix,
                self._swift_type_mapping(data_type.data_type, serializer)
            )
            suffix = ''
        elif is_string_type(data_type):
            ret = 'String'
        elif is_timestamp_type(data_type):
            ret = 'NSDate'
        elif is_boolean_type(data_type):
            ret = 'Bool'
        elif is_bytes_type(data_type):
            ret = 'NSData'
        elif is_void_type(data_type):
            ret = 'Void'
        elif isinstance(data_type, Int32):
            ret = 'Int32'
        elif isinstance(data_type, Int64):
            ret = 'Int64'
        elif isinstance(data_type, UInt32):
            ret = 'UInt32'
        elif isinstance(data_type, UInt64):
            ret = 'UInt64'
        elif isinstance(data_type, Float32):
            ret = 'Float'
        elif isinstance(data_type, Float64):
            ret = 'Double'
        elif is_user_defined_type(data_type):
            ret = '{}.{}'.format(fmt_class(data_type.namespace.name),
                                 self.class_data_type(data_type))
        ret += suffix
        if nullable:
            if serializer:
                ret = 'NullableSerializer<{}>'.format(ret)
            else:
                ret += '?'

        return ret
def fmt_class_type(data_type, suppress_ptr=False):
    data_type, _ = unwrap_nullable(data_type)

    if is_user_defined_type(data_type):
        result = '{}'.format(fmt_class_prefix(data_type))
    else:
        result = _primitive_table.get(
            data_type.__class__, fmt_class(data_type.name))

        if suppress_ptr:
            result = result.replace(' *', '')
            result = result.replace('*', '')

        if is_list_type(data_type):
            data_type, _ = unwrap_nullable(data_type.data_type)
            result = result + '<{}>'.format(fmt_type(data_type))
    return result
Exemple #41
0
def fmt_serial_obj(data_type):
    data_type, nullable = unwrap_nullable(data_type)

    if is_user_defined_type(data_type):
        result = '{}.{}Serializer()'
        result = result.format(fmt_class(data_type.namespace.name),
                                fmt_class(data_type.name))
    else:
        result = _serial_type_table.get(data_type.__class__, fmt_class(data_type.name))

        if is_list_type(data_type):
            result = result + '({})'.format(fmt_serial_obj(data_type.data_type))
        elif is_timestamp_type(data_type):
            result = result + '("{}")'.format(data_type.format)
        else:
            result = 'Serialization._{}'.format(result)

    return result if not nullable else 'NullableSerializer({})'.format(result)
Exemple #42
0
def fmt_serial_obj(data_type):
    data_type, nullable = unwrap_nullable(data_type)

    if is_user_defined_type(data_type):
        result = '{}.{}Serializer()'
        result = result.format(fmt_class(data_type.namespace.name),
            fmt_class(data_type.name))
    else:
        result = _serial_type_table.get(data_type.__class__, fmt_class(data_type.name))

        if is_list_type(data_type):
            result = result + '({})'.format(fmt_serial_obj(data_type.data_type))
        elif is_timestamp_type(data_type):
            result = result + '("{}")'.format(data_type.format)
        else:
            result = 'Serialization._{}'.format(result)

    return result if not nullable else 'NullableSerializer({})'.format(result)
Exemple #43
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), ':')
def fmt_type(data_type, tag=False, has_default=False, no_ptr=False, is_prop=False):
    data_type, nullable = unwrap_nullable(data_type)

    if is_user_defined_type(data_type):
        base = '{}' if no_ptr else '{} *'
        result = base.format(fmt_class_prefix(data_type))
    else:
        result = _primitive_table.get(data_type.__class__,
                                      fmt_class(data_type.name))

        if is_list_type(data_type):
            data_type, _ = unwrap_nullable(data_type.data_type)
            base = '<{}>' if no_ptr else '<{}> *'
            result = result + base.format(fmt_type(data_type))

    if tag:
        if (nullable or has_default) and not is_prop:
            result = 'nullable ' + result

    return result
 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), ':')
Exemple #46
0
    def _serializer_obj(self, data_type):
        if is_nullable_type(data_type):
            data_type = data_type.data_type
            nullable = True
        else:
            nullable = False
        if is_list_type(data_type):
            ret = 'ArraySerializer({})'.format(
                self._serializer_obj(data_type.data_type))
        elif is_string_type(data_type):
            ret = 'Serialization._StringSerializer'
        elif is_timestamp_type(data_type):
            ret = 'NSDateSerializer("{}")'.format(data_type.format)
        elif is_boolean_type(data_type):
            ret = 'Serialization._BoolSerializer'
        elif is_bytes_type(data_type):
            ret = 'Serialization._NSDataSerializer'
        elif is_void_type(data_type):
            ret = 'Serialization._VoidSerializer'
        elif isinstance(data_type, Int32):
            ret = 'Serialization._Int32Serializer'
        elif isinstance(data_type, Int64):
            ret = 'Serialization._Int64Serializer'
        elif isinstance(data_type, UInt32):
            ret = 'Serialization._UInt32Serializer'
        elif isinstance(data_type, UInt64):
            ret = 'Serialization._UInt64Serializer'
        elif isinstance(data_type, Float32):
            ret = 'Serialization._FloatSerializer'
        elif isinstance(data_type, Float64):
            ret = 'Serialization._DoubleSerializer'
        elif is_user_defined_type(data_type):
            ret = "{}.{}Serializer()".format(fmt_class(data_type.namespace.name),
                                             self.class_data_type(data_type))

        if nullable:
            ret = 'NullableSerializer({})'.format(ret)

        return ret
Exemple #47
0
def fmt_type(data_type, tag=False, has_default=False, no_ptr=False):
    data_type, nullable = unwrap_nullable(data_type)

    if is_user_defined_type(data_type):
        base = '{}' if no_ptr else '{} *'
        result = base.format(fmt_class_prefix(data_type))
    else:
        result = _primitive_table.get(data_type.__class__,
                                      fmt_class(data_type.name))

        if is_list_type(data_type):
            data_type, _ = unwrap_nullable(data_type.data_type)
            base = '<{}>' if no_ptr else '<{}> *'
            result = result + base.format(fmt_type(data_type))

    if tag:
        if nullable or has_default:
            result += ' _Nullable'
        elif not is_void_type(data_type):
            result += ' _Nonnull'

    return result
Exemple #48
0
    def _parse_extra_args(self, api, extra_args_raw):
        """
        Parses extra arguments into a map keyed on particular data types.
        """
        extra_args = {}

        def invalid(msg, extra_arg_raw):
            print('Invalid --extra-arg:%s: %s' % (msg, extra_arg_raw),
                  file=sys.stderr)
            sys.exit(1)

        for extra_arg_raw in extra_args_raw:
            try:
                extra_arg = json.loads(extra_arg_raw)
            except ValueError as e:
                invalid(str(e), extra_arg_raw)

            # Validate extra_arg JSON blob
            if 'match' not in extra_arg:
                invalid('No match key', extra_arg_raw)
            elif (not isinstance(extra_arg['match'], list) or
                  len(extra_arg['match']) != 2):
                invalid('match key is not a list of two strings', extra_arg_raw)
            elif (not isinstance(extra_arg['match'][0], six.text_type) or
                  not isinstance(extra_arg['match'][1], six.text_type)):
                print(type(extra_arg['match'][0]))
                invalid('match values are not strings', extra_arg_raw)
            elif 'arg_name' not in extra_arg:
                invalid('No arg_name key', extra_arg_raw)
            elif not isinstance(extra_arg['arg_name'], six.text_type):
                invalid('arg_name is not a string', extra_arg_raw)
            elif 'arg_type' not in extra_arg:
                invalid('No arg_type key', extra_arg_raw)
            elif not isinstance(extra_arg['arg_type'], six.text_type):
                invalid('arg_type is not a string', extra_arg_raw)
            elif ('arg_docstring' in extra_arg and
                  not isinstance(extra_arg['arg_docstring'], six.text_type)):
                invalid('arg_docstring is not a string', extra_arg_raw)

            attr_key, attr_val = extra_arg['match'][0], extra_arg['match'][1]
            extra_args.setdefault(attr_key, {})[attr_val] = \
                (extra_arg['arg_name'], extra_arg['arg_type'],
                 extra_arg.get('arg_docstring'))

        # Extra arguments, keyed on data type objects.
        extra_args_for_types = {}
        # Locate data types that contain extra arguments
        for namespace in api.namespaces.values():
            for route in namespace.routes:
                extra_parameters = []
                if is_user_defined_type(route.arg_data_type):
                    for attr_key in route.attrs:
                        if attr_key not in extra_args:
                            continue
                        attr_val = route.attrs[attr_key]
                        if attr_val in extra_args[attr_key]:
                            extra_parameters.append(extra_args[attr_key][attr_val])
                if len(extra_parameters) > 0:
                    extra_args_for_types[route.arg_data_type] = extra_parameters

        return extra_args_for_types
    def _generate_docstring_for_func(self, namespace, arg_data_type,
                                     result_data_type=None, error_data_type=None,
                                     overview=None, extra_request_args=None,
                                     extra_return_arg=None, footer=None):
        """
        Generates a docstring for a function or method.

        This function is versatile. It will create a docstring using all the
        data that is provided.

        :param arg_data_type: The data type describing the argument to the
            route. The data type should be a struct, and each field will be
            treated as an input parameter of the method.
        :param result_data_type: The data type of the route result.
        :param error_data_type: The data type of the route result in the case
            of an error.
        :param str overview: A description of the route that will be located
            at the top of the docstring.
        :param extra_request_args: [(field name, field type, field doc), ...]
            Describes any additional parameters for the method that aren't a
            field in arg_data_type.
        :param str extra_return_arg: Name of an additional return type that. If
            this is specified, it is assumed that the return of the function
            will be a tuple of return_data_type and extra_return-arg.
        :param str footer: Additional notes at the end of the docstring.
        """
        fields = [] if is_void_type(arg_data_type) else arg_data_type.fields
        if not fields and not overview:
            # If we don't have an overview or any input parameters, we skip the
            # docstring altogether.
            return

        self.emit('"""')
        if overview:
            self.emit_wrapped_text(overview)

        # Description of all input parameters
        if extra_request_args or fields:
            if overview:
                # Add a blank line if we had an overview
                self.emit()

            if extra_request_args:
                for name, data_type_name, doc in extra_request_args:
                    if data_type_name:
                        field_doc = ':param {} {}: {}'.format(data_type_name,
                                                              name, doc)
                        self.emit_wrapped_text(field_doc,
                                               subsequent_prefix='    ')
                    else:
                        self.emit_wrapped_text(
                            ':param {}: {}'.format(name, doc),
                            subsequent_prefix='    ')

            if is_struct_type(arg_data_type):
                for field in fields:
                    if field.doc:
                        if is_user_defined_type(field.data_type):
                            field_doc = ':param {}: {}'.format(
                                field.name, self.process_doc(field.doc, self._docf))
                        else:
                            field_doc = ':param {} {}: {}'.format(
                                self._format_type_in_doc(namespace, field.data_type),
                                field.name,
                                self.process_doc(field.doc, self._docf),
                            )
                        self.emit_wrapped_text(
                            field_doc, subsequent_prefix='    ')
                        if is_user_defined_type(field.data_type):
                            # It's clearer to declare the type of a composite on
                            # a separate line since it references a class in
                            # another module
                            self.emit(':type {}: {}'.format(
                                field.name,
                                self._format_type_in_doc(namespace, field.data_type),
                            ))
                    else:
                        # If the field has no docstring, then just document its
                        # type.
                        field_doc = ':type {}: {}'.format(
                            field.name,
                            self._format_type_in_doc(namespace, field.data_type),
                        )
                        self.emit_wrapped_text(field_doc)

            elif is_union_type(arg_data_type):
                if arg_data_type.doc:
                    self.emit_wrapped_text(':param arg: {}'.format(
                        self.process_doc(arg_data_type.doc, self._docf)),
                        subsequent_prefix='    ')
                self.emit(':type arg: {}'.format(
                    self._format_type_in_doc(namespace, arg_data_type)))

        if overview and not (extra_request_args or fields):
            # Only output an empty line if we had an overview and haven't
            # started a section on declaring types.
            self.emit()

        if extra_return_arg:
            # Special case where the function returns a tuple. The first
            # element is the JSON response. The second element is the
            # the extra_return_arg param.
            args = []
            if is_void_type(result_data_type):
                args.append('None')
            else:
                rtype = self._format_type_in_doc(namespace,
                                                 result_data_type)
                args.append(rtype)
            args.append(extra_return_arg)
            self.generate_multiline_list(args, ':rtype: ')
        else:
            if is_void_type(result_data_type):
                self.emit(':rtype: None')
            else:
                rtype = self._format_type_in_doc(namespace, result_data_type)
                self.emit(':rtype: {}'.format(rtype))

        if not is_void_type(error_data_type) and error_data_type.fields:
            self.emit(':raises: :class:`dropbox.exceptions.ApiError`')
            self.emit()
            # To provide more clarity to a dev who reads the docstring, state
            # the error class that will be returned in the reason field of an
            # ApiError object.
            self.emit('If this raises, ApiError.reason is of type:')
            with self.indent():
                self.emit(self._format_type_in_doc(namespace, error_data_type))

        if footer:
            self.emit()
            self.emit_wrapped_text(footer)
        self.emit('"""')
Exemple #50
0
    def _generate_docstring_for_func(self,
                                     namespace,
                                     arg_data_type,
                                     result_data_type=None,
                                     error_data_type=None,
                                     overview=None,
                                     extra_request_args=None,
                                     extra_return_arg=None,
                                     footer=None):
        """
        Generates a docstring for a function or method.

        This function is versatile. It will create a docstring using all the
        data that is provided.

        :param arg_data_type: The data type describing the argument to the
            route. The data type should be a struct, and each field will be
            treated as an input parameter of the method.
        :param result_data_type: The data type of the route result.
        :param error_data_type: The data type of the route result in the case
            of an error.
        :param str overview: A description of the route that will be located
            at the top of the docstring.
        :param extra_request_args: [(field name, field type, field doc), ...]
            Describes any additional parameters for the method that aren't a
            field in arg_data_type.
        :param str extra_return_arg: Name of an additional return type that. If
            this is specified, it is assumed that the return of the function
            will be a tuple of return_data_type and extra_return-arg.
        :param str footer: Additional notes at the end of the docstring.
        """
        fields = [] if is_void_type(arg_data_type) else arg_data_type.fields
        if not fields and not overview:
            # If we don't have an overview or any input parameters, we skip the
            # docstring altogether.
            return

        self.emit('"""')
        if overview:
            self.emit_wrapped_text(overview)

        # Description of all input parameters
        if extra_request_args or fields:
            if overview:
                # Add a blank line if we had an overview
                self.emit()

            if extra_request_args:
                for name, data_type_name, doc in extra_request_args:
                    if data_type_name:
                        field_doc = ':param {} {}: {}'.format(
                            data_type_name, name, doc)
                        self.emit_wrapped_text(field_doc,
                                               subsequent_prefix='    ')
                    else:
                        self.emit_wrapped_text(':param {}: {}'.format(
                            name, doc),
                                               subsequent_prefix='    ')

            if is_struct_type(arg_data_type):
                for field in fields:
                    if field.doc:
                        if is_user_defined_type(field.data_type):
                            field_doc = ':param {}: {}'.format(
                                field.name,
                                self.process_doc(field.doc, self._docf))
                        else:
                            field_doc = ':param {} {}: {}'.format(
                                self._format_type_in_doc(
                                    namespace, field.data_type),
                                field.name,
                                self.process_doc(field.doc, self._docf),
                            )
                        self.emit_wrapped_text(field_doc,
                                               subsequent_prefix='    ')
                        if is_user_defined_type(field.data_type):
                            # It's clearer to declare the type of a composite on
                            # a separate line since it references a class in
                            # another module
                            self.emit(':type {}: {}'.format(
                                field.name,
                                self._format_type_in_doc(
                                    namespace, field.data_type),
                            ))
                    else:
                        # If the field has no docstring, then just document its
                        # type.
                        field_doc = ':type {}: {}'.format(
                            field.name,
                            self._format_type_in_doc(namespace,
                                                     field.data_type),
                        )
                        self.emit_wrapped_text(field_doc)

            elif is_union_type(arg_data_type):
                if arg_data_type.doc:
                    self.emit_wrapped_text(':param arg: {}'.format(
                        self.process_doc(arg_data_type.doc, self._docf)),
                                           subsequent_prefix='    ')
                self.emit(':type arg: {}'.format(
                    self._format_type_in_doc(namespace, arg_data_type)))

        if overview and not (extra_request_args or fields):
            # Only output an empty line if we had an overview and haven't
            # started a section on declaring types.
            self.emit()

        if extra_return_arg:
            # Special case where the function returns a tuple. The first
            # element is the JSON response. The second element is the
            # the extra_return_arg param.
            args = []
            if is_void_type(result_data_type):
                args.append('None')
            else:
                rtype = self._format_type_in_doc(namespace, result_data_type)
                args.append(rtype)
            args.append(extra_return_arg)
            self.generate_multiline_list(args, ':rtype: ')
        else:
            if is_void_type(result_data_type):
                self.emit(':rtype: None')
            else:
                rtype = self._format_type_in_doc(namespace, result_data_type)
                self.emit(':rtype: {}'.format(rtype))

        if not is_void_type(error_data_type) and error_data_type.fields:
            self.emit(':raises: :class:`dropbox.exceptions.ApiError`')
            self.emit()
            # To provide more clarity to a dev who reads the docstring, state
            # the error class that will be returned in the reason field of an
            # ApiError object.
            self.emit('If this raises, ApiError.reason is of type:')
            with self.indent():
                self.emit(self._format_type_in_doc(namespace, error_data_type))

        if footer:
            self.emit()
            self.emit_wrapped_text(footer)
        self.emit('"""')
    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()
Exemple #52
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()
Exemple #53
0
    def _generate_namespace_tests(self, namespace):
        ns_name = fmt_public_name(namespace.name)

        self.emit()
        self.emit(
            '/// Serialization tests for the {} namespace.'.format(ns_name))
        self.emit()
        self.emit()
        for data_type in namespace.linearize_data_types():
            class_name = fmt_public_name(data_type.name)
            if is_user_defined_type(data_type):
                examples = data_type.get_examples()
                for example_type in examples:
                    test_name = 'testSerialize{}{}{}'.format(
                        ns_name, class_name,
                        fmt_camel_upper(example_type, reserved=False))
                    with self.block_func(func=test_name, args=[]):
                        self.emit('/// Data from the "{}" example'.format(
                            example_type))
                        example_data = examples[example_type].value
                        result_args = []

                        for field in data_type.all_fields:
                            if field.name in example_data:
                                result_args += self._get_example_data(
                                    example_data[field.name], field)
                            else:
                                if not is_void_type(field.data_type):
                                    result_args.append(
                                        (fmt_var(field.name),
                                         self._fmt_default(field.data_type)))

                        args_str = fmt_func_args(result_args)

                        if '\n' not in args_str:
                            if is_struct_type(
                                    data_type
                            ) and data_type.has_enumerated_subtypes():
                                for tags, subtype in data_type.get_all_subtypes_with_tags(
                                ):
                                    assert len(tags) == 1, tags
                                    tag = tags[0]
                                    if tag == example_data['.tag']:
                                        self.emit('{} *obj = {};'.format(
                                            fmt_class_prefix(subtype),
                                            self._get_example_data(
                                                example_data, subtype)))
                                        self.emit(
                                            'NSData *serializedData = [DropboxTransportClient jsonDataWithDictionary:[{} serialize:obj]];'
                                            .format(fmt_class_prefix(subtype)))
                                        self.emit(
                                            'id jsonObj = [NSJSONSerialization JSONObjectWithData:serializedData options:NSJSONReadingMutableContainers error:nil];'
                                        )
                                        self.emit(
                                            '{} *outputObj = [{} deserialize:jsonObj];'
                                            .format(fmt_class_prefix(subtype),
                                                    fmt_class_prefix(subtype)))
                                        self.emit(
                                            '[self checkError:obj outputObj:outputObj];'
                                        )
                            else:
                                self.emit('{} *obj = {};'.format(
                                    fmt_class_prefix(data_type),
                                    fmt_func_call(
                                        fmt_alloc_call(
                                            fmt_class_prefix(data_type)),
                                        self._cstor_name_from_fields_names(
                                            result_args), args_str)))
                                self.emit(
                                    'NSData *serializedData = [DropboxTransportClient jsonDataWithDictionary:[{} serialize:obj]];'
                                    .format(fmt_class_prefix(data_type)))
                                self.emit(
                                    'id jsonObj = [NSJSONSerialization JSONObjectWithData:serializedData options:NSJSONReadingMutableContainers error:nil];'
                                )
                                self.emit(
                                    '{} *outputObj = [{} deserialize:jsonObj];'
                                    .format(fmt_class_prefix(data_type),
                                            fmt_class_prefix(data_type)))
                                self.emit(
                                    '[self checkError:obj outputObj:outputObj];'
                                )
                    self.emit()
Exemple #54
0
    def _get_example_data(self, example_value, field):
        data_type, nullable = unwrap_nullable(field.data_type)
        field_name = fmt_var(field.name)

        result_args = []

        if is_user_defined_type(data_type):
            obj_args = []

            if is_union_type(data_type):
                for field in data_type.all_fields:
                    if field.name == example_value['.tag']:
                        if not is_void_type(field.data_type):
                            if field.name in example_value:
                                self._get_example_data(
                                    example_value[field.name], field)
                            else:
                                self._get_example_data(example_value, field)
                            obj_args.append(
                                (fmt_var(field.name), fmt_var(field.name)))

                field_value = fmt_func_call(
                    caller=fmt_alloc_call(fmt_class_prefix(data_type)),
                    callee='initWith{}'.format(
                        fmt_camel_upper(example_value['.tag'])),
                    args=fmt_func_args(obj_args))
                self.emit('{} *{} = {};'.format(fmt_class_prefix(data_type),
                                                field_name, field_value))
            else:
                if data_type.has_enumerated_subtypes():
                    for tags, subtype in data_type.get_all_subtypes_with_tags(
                    ):
                        assert len(tags) == 1, tags
                        tag = tags[0]
                        if tag == example_value['.tag']:
                            self._get_example_data(example_value, subtype)
                else:
                    for field in data_type.all_fields:
                        if field.name in example_value:
                            obj_args.append((fmt_var(field.name),
                                             self._get_example_data(
                                                 example_value[field.name],
                                                 field.data_type)))
                        else:
                            if not is_void_type(field.data_type):
                                obj_args.append(
                                    (fmt_var(field.name),
                                     self._fmt_default(field.data_type)))
                    field_value = fmt_func_call(
                        fmt_alloc_call(fmt_class_prefix(data_type)),
                        'initWith{}'.format(
                            fmt_camel_upper(data_type.all_fields[0].name)),
                        fmt_func_args(obj_args))

                    self.emit('{} *{} = {};'.format(
                        fmt_class_prefix(data_type), field_name, field_value))

            result_args.append((field_name, field_name))
        elif is_list_type(data_type):
            if example_value:
                field_value = '@[{}]'.format(
                    self._get_example_data(example_value[0], field))
            else:
                field_value = 'nil'
            self.emit('NSArray *{} = {};'.format(field_name, field_value))
            result_args.append((field_name, field_name))
        elif is_numeric_type(data_type):
            if is_float_type(data_type):
                field_value = '[NSNumber numberWithDouble:{}]'.format(
                    example_value)
            elif isinstance(data_type, (UInt64, Int64)):
                field_value = '[NSNumber numberWithLong:{}]'.format(
                    example_value)
            else:
                field_value = '[NSNumber numberWithInt:{}]'.format(
                    example_value)
            result_args.append((field_name, field_value))
        elif is_timestamp_type(data_type):
            field_value = '[DbxNSDateSerializer deserialize:@"{}" dateFormat:@"{}"]'.format(
                example_value, data_type.format)
            self.emit('NSDate *{} = {};'.format(field_name, field_value))
            result_args.append((field_name, field_name))
        elif is_string_type(data_type):
            field_value = '@"{}"'.format(example_value)
            result_args.append((field_name, field_value))
        elif is_boolean_type(data_type):
            field_value = '@YES' if bool(example_value) else '@NO'
            result_args.append((field_name, field_value))

        return result_args