def emit_assert(self, codegen, expression_path):
        extra = ('.' + self.name) if self.name else ''
        if self.option:
            expression = '(*' + expression_path + extra + '.as_ref().unwrap())'
        else:
            expression = expression_path + extra

        if isinstance(self.test_value, TestValue):
            self.test_value.emit_asserts(codegen, expression)
        elif ir.is_string_type(self.typ):
            codegen.emit(u'assert_eq!({}.as_str(), r#"{}"#);'.format(
                expression, self.value))
        elif ir.is_numeric_type(self.typ):
            codegen.emit(u'assert_eq!({}, {});'.format(expression, self.value))
        elif ir.is_boolean_type(self.typ):
            codegen.emit(u'assert_eq!({}, {});'.format(
                expression, 'true' if self.value else 'false'))
        elif ir.is_timestamp_type(self.typ):
            codegen.emit(u'assert_eq!({}.as_str(), "{}");'.format(
                expression, self.value.strftime(self.typ.format)))
        elif ir.is_bytes_type(self.typ):
            codegen.emit(u'assert_eq!(&{}, &[{}]);'.format(
                expression, ",".join(str(x) for x in self.value)))
        else:
            raise RuntimeError(
                u'Error: assetion unhandled for type {} of field {} with value {}'
                .format(self.typ, self.name, self.value))
示例#2
0
    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()
示例#3
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_map_type(dt):
        v = generate_func_call(
            'bv.Map',
            args=[
                generate_validator_constructor(ns, dt.key_data_type),
                generate_validator_constructor(ns, dt.value_data_type),
            ])
    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 make_test_field(field_name, stone_type, rust_generator, reference_impls):
    rust_name = rust_generator.field_name_raw(
        field_name) if field_name is not None else None
    typ, option = ir.unwrap_nullable(stone_type)

    inner = None
    value = None
    if ir.is_struct_type(typ):
        if typ.has_enumerated_subtypes():
            variant = typ.get_enumerated_subtypes()[0]
            inner = TestPolymorphicStruct(rust_generator, typ, reference_impls,
                                          variant)
        else:
            inner = TestStruct(rust_generator, typ, reference_impls)
        value = inner.value
    elif ir.is_union_type(typ):
        # Pick the first tag.
        # We could generate tests for them all, but it would lead to a huge explosion of tests, and
        # the types themselves are tested elsewhere.
        if len(typ.fields) == 0:
            # there must be a parent type; go for it
            variant = typ.all_fields[0]
        else:
            variant = typ.fields[0]
        inner = TestUnion(rust_generator, typ, reference_impls, variant)
        value = inner.value
    elif ir.is_list_type(typ):
        inner = TestList(rust_generator, typ.data_type, reference_impls)
        value = [inner.value]
    elif ir.is_map_type(typ):
        inner = TestMap(rust_generator, typ, reference_impls)
        value = inner.value
    elif ir.is_string_type(typ):
        if typ.pattern:
            value = Unregex(typ.pattern, typ.min_length).generate()
        elif typ.min_length:
            value = 'a' * typ.min_length
        else:
            value = 'something'
    elif ir.is_numeric_type(typ):
        value = typ.max_value or typ.maximum or 1e307
    elif ir.is_boolean_type(typ):
        value = True
    elif ir.is_timestamp_type(typ):
        value = datetime.datetime.utcfromtimestamp(2**33 - 1)
    elif ir.is_bytes_type(typ):
        value = bytes([0, 1, 2, 3, 4, 5])
    elif not ir.is_void_type(typ):
        raise RuntimeError(u'Error: unhandled field type of {}: {}'.format(
            field_name, typ))
    return TestField(rust_name, value, inner, typ, option)
示例#5
0
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
示例#6
0
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))
示例#7
0
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
示例#8
0
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))
示例#9
0
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))
示例#10
0
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))
示例#11
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_map_type(dt):
        v = generate_func_call(
            'bv.Map',
            args=[
                generate_validator_constructor(ns, dt.key_data_type),
                generate_validator_constructor(ns, dt.value_data_type),
            ]
        )
    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
示例#12
0
def map_stone_type_to_python_type(ns, data_type, override_dict=None):
    # type: (ApiNamespace, DataType, typing.Optional[OverrideDefaultTypesDict]) -> typing.Text
    """
    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):
        string_override = override_dict.get(String, None)
        if string_override:
            return string_override(ns, data_type, override_dict)
        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_map_type(data_type):
        map_type = cast(Map, data_type)
        if Map in override_dict:
            return override_dict[Map](ns, data_type, override_dict)

        return 'dict of [{}:{}]'.format(
            map_stone_type_to_python_type(ns, map_type.key_data_type,
                                          override_dict),
            map_stone_type_to_python_type(ns, map_type.value_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 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_map_type(data_type):
        map_type = cast(Map, data_type)
        if Map in override_dict:
            return override_dict[Map](
                ns,
                data_type,
                override_dict
            )

        return 'dict of [{}:{}]'.format(
            map_stone_type_to_python_type(ns, map_type.key_data_type, override_dict),
            map_stone_type_to_python_type(ns, map_type.value_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)