def _generate_struct_builder(self, struct): fields = [ "%s %s" % (fmt_var(field.name), fmt_type(field.data_type, struct.namespace, use_interface=True)) for field in struct.all_required_fields ] self.emit('// New{0} returns a new {0} instance'.format(struct.name)) signature = "func New{0}({1}) *{0}".format(struct.name, ', '.join(fields)) with self.block(signature): self.emit('s := new({0})'.format(struct.name)) for field in struct.all_required_fields: field_name = fmt_var(field.name) self.emit("s.{0} = {0}".format(field_name)) for field in struct.all_optional_fields: if field.has_default: if is_primitive_type(field.data_type): default = field.default if is_boolean_type(field.data_type): default = str(default).lower() self.emit('s.{0} = {1}'.format(fmt_var(field.name), default)) elif is_union_type(field.data_type): self.emit('s.%s = &%s{Tagged:dropbox.Tagged{"%s"}}' % (fmt_var(field.name), fmt_type(field.data_type, struct.namespace).lstrip('*'), field.default.tag_name)) self.emit('return s') self.emit()
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)
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
def _generate_struct_builder(self, struct): fields = ["%s %s" % (fmt_var(field.name), fmt_type(field.data_type, struct.namespace, use_interface=True)) for field in struct.all_required_fields] self.emit('// New{0} returns a new {0} instance'.format(struct.name)) signature = "func New{0}({1}) *{0}".format(struct.name, ', '.join(fields)) with self.block(signature): self.emit('s := new({0})'.format(struct.name)) for field in struct.all_required_fields: field_name = fmt_var(field.name) self.emit("s.{0} = {0}".format(field_name)) for field in struct.all_optional_fields: if field.has_default: if is_primitive_type(field.data_type): default = field.default if is_boolean_type(field.data_type): default = str(default).lower() self.emit('s.{0} = {1}'.format(fmt_var(field.name), default)) elif is_union_type(field.data_type): self.emit('s.%s = &%s{Tagged:dropbox.Tagged{"%s"}}' % (fmt_var(field.name), fmt_type(field.data_type, struct.namespace).lstrip('*'), field.default.tag_name)) self.emit('return s') self.emit()
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_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 fmt_default_value(field): if is_tag_ref(field.default): return '[[{} alloc] initWith{}]'.format( fmt_class_prefix(field.default.union_data_type), fmt_class(field.default.tag_name)) elif is_numeric_type(field.data_type): return '@({})'.format(field.default) elif is_boolean_type(field.data_type): if field.default: bool_str = 'YES' else: bool_str = 'NO' return '@{}'.format(bool_str) else: raise TypeError('Can\'t handle default value type %r' % type(field.data_type))
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_ns_number_call(data_type): result = '' if is_numeric_type(data_type): if isinstance(data_type, UInt32): result = 'numberWithUnsignedInt' elif isinstance(data_type, UInt64): result = 'numberWithUnsignedLong' elif isinstance(data_type, Int32): result = 'numberWithInt' elif isinstance(data_type, Int64): result = 'numberWithLong' elif isinstance(data_type, Float32): result = 'numberWithDouble' elif isinstance(data_type, Float64): result = 'numberWithDouble' elif is_boolean_type(data_type): result = 'numberWithBool' return result
def fmt_default_value(field): if is_tag_ref(field.default): return '[[{} alloc] initWith{}]'.format( fmt_class_prefix(field.default.union_data_type), fmt_class(field.default.tag_name)) elif is_numeric_type(field.data_type): return '@({})'.format(field.default) elif is_boolean_type(field.data_type): if field.default: bool_str = 'YES' else: bool_str = 'NO' return '@{}'.format(bool_str) elif is_string_type(field.data_type): return '@"{}"'.format(field.default) else: raise TypeError('Can\'t handle default value type %r' % type(field.data_type))
def fmt_default_value(namespace, field): if is_tag_ref(field.default): return '{}.{}Serializer().serialize(.{})'.format( fmt_class(namespace.name), fmt_class(field.default.union_data_type.name), fmt_var(field.default.tag_name)) elif is_list_type(field.data_type): return '.array({})'.format(field.default) elif is_numeric_type(field.data_type): return '.number({})'.format(field.default) elif is_string_type(field.data_type): return '.str({})'.format(field.default) elif is_boolean_type(field.data_type): if field.default: bool_str = '1' else: bool_str = '0' return '.number({})'.format(bool_str) else: raise TypeError('Can\'t handle default value type %r' % type(field.data_type))
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
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