Beispiel #1
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
Beispiel #2
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
Beispiel #3
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
Beispiel #4
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
Beispiel #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
Beispiel #6
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
Beispiel #7
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
Beispiel #8
0
    def _generate_route_m(self, route, namespace, route_args, extra_args,
                          task_type_name, func_suffix):
        """Generates route method implementation for the given route."""
        user_args = list(route_args)

        transport_args = [
            ('route', 'route'),
            ('arg', 'arg' if not is_void_type(route.arg_data_type) else 'nil'),
        ]

        for name, value, typ in extra_args:
            user_args.append((name, typ.replace(' _Nonnull',
                                                '').replace(' _Nullable', '')))
            transport_args.append((name, value))

        route_result_type = fmt_type(
            route.result_data_type,
            tag=False) if not is_void_type(route.result_data_type) else ''

        with self.block_func(func='{}{}'.format(fmt_var(route.name),
                                                func_suffix),
                             args=fmt_func_args_declaration(user_args),
                             return_type='{} *'.format(task_type_name)):
            self.emit('DBRoute *route = {}.{};'.format(
                fmt_route_obj_class(namespace.name),
                fmt_route_var(namespace.name, route.name)))
            if is_union_type(route.arg_data_type):
                self.emit('{} *arg = {};'.format(
                    fmt_class_prefix(route.arg_data_type),
                    fmt_var(route.arg_data_type.name)))
            elif not is_void_type(route.arg_data_type):
                init_call = fmt_func_call(
                    caller=fmt_alloc_call(
                        caller=fmt_class_prefix(route.arg_data_type)),
                    callee=self._cstor_name_from_fields_names(route_args),
                    args=fmt_func_args([(f[0], f[0]) for f in route_args]))
                self.emit('{} *arg = {};'.format(
                    fmt_class_prefix(route.arg_data_type), init_call))
            request_call = fmt_func_call(caller='self.client',
                                         callee='request{}'.format(
                                             fmt_camel_upper(
                                                 route.attrs.get('style'))),
                                         args=fmt_func_args(transport_args))
            self.emit('return {};'.format(request_call))
        self.emit()
Beispiel #9
0
    def _generate_init_imports_h(self, data_type):
        self.emit('#import <Foundation/Foundation.h>')
        self.emit()
        self.emit('#import "DBSerializableProtocol.h"')

        if data_type.parent_type and not is_union_type(data_type):
            self.emit(fmt_import(fmt_class_prefix(data_type.parent_type)))

        self.emit()
Beispiel #10
0
    def _generate_init_imports_h(self, data_type):
        self.emit('#import <Foundation/Foundation.h>')
        self.emit()
        self.emit('#import "DBSerializableProtocol.h"')

        if data_type.parent_type and not is_union_type(data_type):
            self.emit(fmt_import(fmt_class_prefix(data_type.parent_type)))

        self.emit()
Beispiel #11
0
    def generate(self, api):
        for namespace in api.namespaces.values():
            for data_type in namespace.linearize_data_types():
                obj_name_to_namespace[data_type.name] = fmt_class_prefix(
                    data_type)

        for namespace in api.namespaces.values():
            if namespace.routes:
                import_classes = [
                    fmt_routes_class(namespace.name),
                    fmt_route_obj_class(namespace.name),
                    self.args.transport_client_name,
                    'DBStoneBase',
                    'DBErrors',
                ]

                with self.output_to_relative_path('Routes/{}.m'.format(
                        fmt_routes_class(namespace.name))):
                    self.emit_raw(stone_warning)

                    imports_classes_m = import_classes + \
                        self._get_imports_m(
                            self._get_namespace_route_imports(namespace), [])
                    self._generate_imports_m(imports_classes_m)

                    self._generate_routes_m(namespace)

                with self.output_to_relative_path('Routes/{}.h'.format(
                        fmt_routes_class(namespace.name))):
                    self.emit_raw(base_file_comment)
                    self.emit('#import <Foundation/Foundation.h>')
                    self.emit()
                    self.emit(fmt_import('DBTasks'))
                    self.emit()
                    import_classes_h = [
                        self.args.transport_client_name,
                        'DBNilObject',
                    ]
                    import_classes_h = import_classes_h + self._get_imports_h(
                        self._get_namespace_route_imports(
                            namespace,
                            include_route_args=False,
                            include_route_deep_args=True))
                    self._generate_imports_h(import_classes_h)

                    self._generate_routes_h(namespace)

        with self.output_to_relative_path('Client/{}.m'.format(
                self.args.module_name)):
            self._generate_client_m(api)

        with self.output_to_relative_path('Client/{}.h'.format(
                self.args.module_name)):
            self._generate_client_h(api)
Beispiel #12
0
    def _generate_route_m(self, route, namespace, route_args, extra_args,
                          task_type_name, func_suffix):
        """Generates route method implementation for the given route."""
        user_args = list(route_args)

        transport_args = [
            ('route', 'route'),
            ('arg', 'arg' if not is_void_type(route.arg_data_type) else 'nil'),
        ]

        for name, value, typ in extra_args:
            user_args.append((name, typ))
            transport_args.append((name, value))

        with self.block_func(
                func='{}{}'.format(fmt_var(route.name), func_suffix),
                args=fmt_func_args_declaration(user_args),
                return_type='{} *'.format(task_type_name)):
            self.emit('DBRoute *route = {}.{};'.format(
                fmt_route_obj_class(namespace.name),
                fmt_route_var(namespace.name, route.name)))
            if is_union_type(route.arg_data_type):
                self.emit('{} *arg = {};'.format(
                    fmt_class_prefix(route.arg_data_type),
                    fmt_var(route.arg_data_type.name)))
            elif not is_void_type(route.arg_data_type):
                init_call = fmt_func_call(
                    caller=fmt_alloc_call(
                        caller=fmt_class_prefix(route.arg_data_type)),
                    callee=self._cstor_name_from_fields_names(route_args),
                    args=fmt_func_args([(f[0], f[0]) for f in route_args]))
                self.emit('{} *arg = {};'.format(
                    fmt_class_prefix(route.arg_data_type), init_call))
            request_call = fmt_func_call(
                caller='self.client',
                callee='request{}'.format(
                    fmt_camel_upper(route.attrs.get('style'))),
                args=fmt_func_args(transport_args))
            self.emit('return {};'.format(request_call))
        self.emit()
Beispiel #13
0
    def generate(self, api):
        for namespace in api.namespaces.values():
            for data_type in namespace.linearize_data_types():
                self.obj_name_to_namespace[
                    data_type.name] = fmt_class_prefix(data_type)

        for namespace in api.namespaces.values():
            if namespace.routes:
                import_classes = [
                    fmt_routes_class(namespace.name),
                    fmt_route_obj_class(namespace.name),
                    '{}Protocol'.format(self.args.transport_client_name),
                    'DBStoneBase',
                    'DBRequestErrors',
                ]

                with self.output_to_relative_path(
                        'Routes/{}.m'.format(fmt_routes_class(namespace.name))):
                    self.emit_raw(stone_warning)

                    imports_classes_m = import_classes + \
                        self._get_imports_m(
                            self._get_namespace_route_imports(namespace), [])
                    self._generate_imports_m(imports_classes_m)

                    self._generate_routes_m(namespace)

                with self.output_to_relative_path(
                        'Routes/{}.h'.format(fmt_routes_class(namespace.name))):
                    self.emit_raw(base_file_comment)
                    self.emit('#import <Foundation/Foundation.h>')
                    self.emit()
                    self.emit(fmt_import('DBTasks'))
                    self.emit()
                    import_classes_h = [
                        'DBNilObject',
                    ]
                    import_classes_h = (import_classes_h +
                        self._get_imports_h(self._get_namespace_route_imports(
                            namespace, include_route_args=False, include_route_deep_args=True)))
                    self._generate_imports_h(import_classes_h)
                    self.emit('@protocol {};'.format(self.args.transport_client_name),)
                    self.emit()
                    self._generate_routes_h(namespace)

        with self.output_to_relative_path('Client/{}.m'.format(self.args.module_name)):
            self._generate_client_m(api)

        with self.output_to_relative_path('Client/{}.h'.format(self.args.module_name)):
            self._generate_client_h(api)
Beispiel #14
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
Beispiel #15
0
 def _generate_testing_imports(self, api):
     import_classes = ['DbxStoneSerializers', 'DropboxTransportClient']
     for namespace in api.namespaces.values():
         for data_type in namespace.linearize_data_types():
             import_classes.append(fmt_class_prefix(data_type))
     self._generate_imports_m(import_classes)
Beispiel #16
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()
Beispiel #17
0
    def generate(self, api):

        for namespace in api.namespaces.values():
            self.namespace_to_has_routes[namespace] = False
            if namespace.routes:
                for route in namespace.routes:
                    if route.attrs.get(
                            'auth') == self.args.auth_type or route.attrs.get(
                                'auth'
                            ) == 'noauth' and self.args.auth_type == 'user':
                        self.namespace_to_has_routes[namespace] = True
                        break

        for namespace in api.namespaces.values():
            for data_type in namespace.linearize_data_types():
                self.obj_name_to_namespace[data_type.name] = fmt_class_prefix(
                    data_type)

        for namespace in api.namespaces.values():
            if namespace.routes and self.namespace_to_has_routes[namespace]:
                import_classes = [
                    fmt_routes_class(namespace.name, self.args.auth_type),
                    fmt_route_obj_class(namespace.name),
                    '{}Protocol'.format(self.args.transport_client_name),
                    'DBStoneBase',
                    'DBRequestErrors',
                ]

                with self.output_to_relative_path('Routes/{}.m'.format(
                        fmt_routes_class(namespace.name,
                                         self.args.auth_type))):
                    self.emit_raw(stone_warning)

                    imports_classes_m = import_classes + \
                        self._get_imports_m(
                            self._get_namespace_route_imports(namespace), [])
                    self._generate_imports_m(imports_classes_m)

                    self._generate_routes_m(namespace)

                with self.output_to_relative_path('Routes/{}.h'.format(
                        fmt_routes_class(namespace.name,
                                         self.args.auth_type))):
                    self.emit_raw(base_file_comment)
                    self.emit('#import <Foundation/Foundation.h>')
                    self.emit()
                    self.emit(fmt_import('DBTasks'))
                    self.emit()
                    import_classes_h = [
                        'DBNilObject',
                    ]
                    import_classes_h = (import_classes_h + self._get_imports_h(
                        self._get_namespace_route_imports(
                            namespace,
                            include_route_args=False,
                            include_route_deep_args=True)))
                    self._generate_imports_h(import_classes_h)
                    self.emit(
                        '@protocol {};'.format(
                            self.args.transport_client_name), )
                    self.emit()
                    self._generate_routes_h(namespace)

        with self.output_to_relative_path('Client/{}.m'.format(
                self.args.module_name)):
            self._generate_client_m(api)

        with self.output_to_relative_path('Client/{}.h'.format(
                self.args.module_name)):
            self._generate_client_h(api)