def _get_route_args(self, namespace, route, tag=False): """Returns a list of name / value string pairs representing the arguments for a particular route.""" data_type, _ = unwrap_nullable(route.arg_data_type) if is_struct_type(data_type): arg_list = [] for field in data_type.all_fields: arg_list.append((fmt_var(field.name), fmt_type(field.data_type, tag=tag, has_default=field.has_default))) doc_list = [(fmt_var(f.name), self.process_doc(f.doc, self._docf)) for f in data_type.fields if f.doc] elif is_union_type(data_type): arg_list = [(fmt_var(data_type.name), fmt_type(route.arg_data_type, tag=tag))] doc_list = [ (fmt_var(data_type.name), self.process_doc(data_type.doc, self._docf) if data_type.doc else 'The {} union'.format(fmt_class(data_type.name))) ] else: arg_list = [] doc_list = [] return arg_list, doc_list
def _get_default_route_args( self, namespace, # pylint: disable=unused-argument route, tag=False): """Returns a list of name / value string pairs representing the default arguments for a particular route.""" data_type, _ = unwrap_nullable(route.arg_data_type) if is_struct_type(data_type): arg_list = [] for field in data_type.all_fields: if not field.has_default and not is_nullable_type( field.data_type): arg_list.append( (fmt_var(field.name), fmt_type(field.data_type, tag=tag))) doc_list = ([(fmt_var(f.name), self.process_doc(f.doc, self._docf)) for f in data_type.fields if f.doc and not f.has_default and not is_nullable_type(f.data_type)]) else: arg_list = [] doc_list = [] return arg_list, doc_list
def _get_route_args(self, namespace, route, tag=False): # pylint: disable=unused-argument """Returns a list of name / value string pairs representing the arguments for a particular route.""" data_type, _ = unwrap_nullable(route.arg_data_type) if is_struct_type(data_type): arg_list = [] for field in data_type.all_fields: arg_list.append((fmt_var(field.name), fmt_type( field.data_type, tag=tag, has_default=field.has_default))) doc_list = [(fmt_var(f.name), self.process_doc(f.doc, self._docf)) for f in data_type.fields if f.doc] elif is_union_type(data_type): arg_list = [(fmt_var(data_type.name), fmt_type( route.arg_data_type, tag=tag))] doc_list = [(fmt_var(data_type.name), self.process_doc(data_type.doc, self._docf) if data_type.doc else 'The {} union'.format( fmt_class(data_type .name)))] else: arg_list = [] doc_list = [] return arg_list, doc_list
def _get_default_route_args( self, namespace, # pylint: disable=unused-argument route, tag=False): """Returns a list of name / value string pairs representing the default arguments for a particular route.""" data_type, _ = unwrap_nullable(route.arg_data_type) if is_struct_type(data_type): arg_list = [] for field in data_type.all_fields: if not field.has_default and not is_nullable_type( field.data_type): arg_list.append((fmt_var(field.name), fmt_type( field.data_type, tag=tag))) doc_list = ([(fmt_var(f.name), self.process_doc(f.doc, self._docf)) for f in data_type.fields if f.doc and not f.has_default and not is_nullable_type(f.data_type)]) else: arg_list = [] doc_list = [] return arg_list, doc_list
def _generate_client_h(self, api): """Generates client base header file. For each namespace, the client will have an object field that encapsulates each route in the particular namespace.""" self.emit_raw(stone_warning) self.emit('#import <Foundation/Foundation.h>') self.emit() import_classes = [ fmt_routes_class(ns.name, self.args.auth_type) for ns in api.namespaces.values() if ns.routes and self.namespace_to_has_routes[ns] ] self._generate_imports_h(import_classes) self.emit() self.emit('@protocol {};'.format(self.args.transport_client_name)) self.emit() self.emit(comment_prefix) description_str = ( 'Base client object that contains an instance field for ' 'each namespace, each of which contains references to all routes within ' 'that namespace. Fully-implemented API clients will inherit this class.' ) self.emit_wrapped_text(description_str, prefix=comment_prefix) self.emit(comment_prefix) with self.block_h(self.args.class_name, protected=[('transportClient', 'id<{}> _Nonnull'.format( self.args.transport_client_name))]): self.emit() for namespace in api.namespaces.values(): if namespace.routes and self.namespace_to_has_routes[namespace]: class_doc = 'Routes within the `{}` namespace.'.format( fmt_var(namespace.name)) self.emit_wrapped_text(class_doc, prefix=comment_prefix) prop = '{}Routes'.format(fmt_var(namespace.name)) typ = '{} * _Nonnull'.format( fmt_routes_class(namespace.name, self.args.auth_type)) self.emit(fmt_property_str(prop=prop, typ=typ)) self.emit() client_args = fmt_func_args_declaration([ ('client', 'id<{}> _Nonnull'.format(self.args.transport_client_name)) ]) description_str = ( 'Initializes the `{}` object with a networking client.') self.emit_wrapped_text(description_str.format( self.args.class_name), prefix=comment_prefix) init_signature = fmt_signature(func='initWithTransportClient', args=client_args, return_type='nonnull instancetype') self.emit('{};'.format(init_signature)) self.emit()
def _docf(self, tag, val): if tag == 'route': return '`{}`'.format(fmt_func(val)) elif tag == 'field': if '.' in val: cls_name, field = val.split('.') return ('`{}` in `{}`'.format(fmt_var(field), self.obj_name_to_namespace[cls_name])) else: return fmt_var(val) elif tag in ('type', 'val', 'link'): return val else: return val
def _docf(self, tag, val): if tag == 'route': return '`{}`'.format(fmt_func(val)) elif tag == 'field': if '.' in val: cls_name, field = val.split('.') return ('`{}` in `{}`'.format( fmt_var(field), self.obj_name_to_namespace[cls_name])) else: return fmt_var(val) elif tag in ('type', 'val', 'link'): return val else: return val
def _generate_client_m(self, api): """Generates client base implementation file. For each namespace, the client will have an object field that encapsulates each route in the particular namespace.""" self.emit_raw(base_file_comment) import_classes = [self.args.module_name] import_classes += [ fmt_routes_class(ns.name) for ns in api.namespaces.values() if ns.routes ] import_classes.append(self.args.transport_client_name) self._generate_imports_m(import_classes) with self.block_m(self.args.class_name): client_args = fmt_func_args_declaration([ ('client', '{} *'.format(self.args.transport_client_name)) ]) with self.block_func(func='initWithTransportClient', args=client_args, return_type='instancetype'): self.emit('self = [super init];') with self.block_init(): for namespace in api.namespaces.values(): if namespace.routes: self.emit( '_{}Routes = [[{} alloc] init:client];'.format( fmt_var(namespace.name), fmt_routes_class(namespace.name)))
def _generate_client_m(self, api): """Generates client base implementation file. For each namespace, the client will have an object field that encapsulates each route in the particular namespace.""" self.emit_raw(base_file_comment) import_classes = [self.args.module_name] import_classes += [ fmt_routes_class(ns.name, self.args.auth_type) for ns in api.namespaces.values() if ns.routes and self.namespace_to_has_routes[ns] ] import_classes.append( '{}Protocol'.format(self.args.transport_client_name)) self._generate_imports_m(import_classes) with self.block_m(self.args.class_name): client_args = fmt_func_args_declaration( [('client', 'id<{}>'.format(self.args.transport_client_name))]) with self.block_func( func='initWithTransportClient', args=client_args, return_type='instancetype'): self.emit('self = [super init];') with self.block_init(): self.emit('_transportClient = client;') for namespace in api.namespaces.values(): if namespace.routes and self.namespace_to_has_routes[namespace]: base_string = '_{}Routes = [[{} alloc] init:client];' self.emit( base_string.format( fmt_var(namespace.name), fmt_routes_class(namespace.name, self.args.auth_type)))
def _generate_client_h(self, api): """Generates client base header file. For each namespace, the client will have an object field that encapsulates each route in the particular namespace.""" self.emit_raw(stone_warning) self.emit('#import <Foundation/Foundation.h>') self.emit() import_classes = [fmt_routes_class( ns.name) for ns in api.namespaces.values() if ns.routes] self._generate_imports_h(import_classes) self.emit() self.emit('@protocol {};'.format(self.args.transport_client_name)) self.emit() self.emit(comment_prefix) description_str = ('Base client object that contains an instance field for ' 'each namespace, each of which contains references to all routes within ' 'that namespace. Fully-implemented API clients will inherit this class.') self.emit_wrapped_text(description_str, prefix=comment_prefix) self.emit(comment_prefix) with self.block_h(self.args.class_name): self.emit(fmt_property_str( 'transportClient', 'id<{}> _Nonnull'.format(self.args.transport_client_name))) self.emit() for namespace in api.namespaces.values(): if namespace.routes: class_doc = 'Routes within the `{}` namespace.'.format( fmt_var(namespace.name)) self.emit_wrapped_text(class_doc, prefix=comment_prefix) prop = '{}Routes'.format(fmt_var(namespace.name)) typ = '{} * _Nonnull'.format(fmt_routes_class(namespace.name)) self.emit(fmt_property_str(prop=prop, typ=typ)) self.emit() client_args = fmt_func_args_declaration( [('client', 'id<{}> _Nonnull'.format(self.args.transport_client_name))]) description_str = ( 'Initializes the `{}` object with a networking client.') self.emit_wrapped_text(description_str.format( self.args.class_name), prefix=comment_prefix) init_signature = fmt_signature(func='initWithTransportClient', args=client_args, return_type='nonnull instancetype') self.emit('{};'.format(init_signature)) self.emit()
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()
def _generate_route_signature( self, route, namespace, # pylint: disable=unused-argument route_args, extra_args, doc_list, task_type_name, func_suffix): """Generates route method signature for the given route.""" for name, _, typ in extra_args: route_args.append((name, typ)) deprecated = 'DEPRECATED: ' if route.deprecated else '' func_name = '{}{}'.format(fmt_var(route.name), func_suffix) self.emit(comment_prefix) if route.doc: route_doc = self.process_doc(route.doc, self._docf) else: route_doc = 'The {} route'.format(func_name) self.emit_wrapped_text(deprecated + route_doc, prefix=comment_prefix, width=120) self.emit(comment_prefix) for name, doc in doc_list: self.emit_wrapped_text('@param {} {}'.format( name, doc if doc else undocumented), prefix=comment_prefix, width=120) self.emit(comment_prefix) output = ( '@return Through the response callback, the caller will ' + 'receive a `{}` object on success or a `{}` object on failure.') output = output.format( fmt_type(route.result_data_type, tag=False, no_ptr=True), fmt_type(route.error_data_type, tag=False, no_ptr=True)) self.emit_wrapped_text(output, prefix=comment_prefix, width=120) self.emit(comment_prefix) result_type_str = fmt_type(route.result_data_type) if not is_void_type( route.result_data_type) else 'DBNilObject *' error_type_str = fmt_type(route.error_data_type) if not is_void_type( route.error_data_type) else 'DBNilObject *' return_type = '{}<{}, {}> *'.format(task_type_name, result_type_str, error_type_str) deprecated = self._get_deprecation_warning(route) route_signature = fmt_signature( func=func_name, args=fmt_func_args_declaration(route_args), return_type='{} _Nonnull'.format(return_type)) self.emit('{}{};'.format(route_signature, deprecated)) self.emit()
def _generate_route_signature( self, route, namespace, # pylint: disable=unused-argument route_args, extra_args, doc_list, task_type_name, func_suffix): """Generates route method signature for the given route.""" for name, _, typ in extra_args: route_args.append((name, typ)) deprecated = 'DEPRECATED: ' if route.deprecated else '' func_name = '{}{}'.format(fmt_var(route.name), func_suffix) self.emit(comment_prefix) if route.doc: route_doc = self.process_doc(route.doc, self._docf) else: route_doc = 'The {} route'.format(func_name) self.emit_wrapped_text( deprecated + route_doc, prefix=comment_prefix, width=120) self.emit(comment_prefix) for name, doc in doc_list: self.emit_wrapped_text( '@param {} {}'.format(name, doc if doc else undocumented), prefix=comment_prefix, width=120) self.emit(comment_prefix) output = ( '@return Through the response callback, the caller will ' + 'receive a `{}` object on success or a `{}` object on failure.') output = output.format( fmt_type(route.result_data_type, tag=False, no_ptr=True), fmt_type(route.error_data_type, tag=False, no_ptr=True)) self.emit_wrapped_text(output, prefix=comment_prefix, width=120) self.emit(comment_prefix) result_type_str = fmt_type(route.result_data_type) if not is_void_type( route.result_data_type) else 'DBNilObject *' error_type_str = fmt_type(route.error_data_type) if not is_void_type( route.error_data_type) else 'DBNilObject *' return_type = '{}<{}, {}> *'.format(task_type_name, result_type_str, error_type_str) deprecated = self._get_deprecation_warning(route) route_signature = fmt_signature( func=func_name, args=fmt_func_args_declaration(route_args), return_type='{}'.format(return_type)) self.emit('{}{};'.format(route_signature, deprecated)) self.emit()
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()
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()
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