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))
def _default_value(self, field): if isinstance(field.data_type, ir.Nullable): return u'None' elif ir.is_numeric_type(ir.unwrap_aliases(field.data_type)[0]): return field.default elif isinstance(field.default, ir.TagRef): default_variant = None for variant in field.default.union_data_type.all_fields: if variant.name == field.default.tag_name: default_variant = variant if default_variant is None: raise RuntimeError( 'ERROR: didn\'t find matching variant of {}: {}'.format( field.data_type.name, field.default.tag_name)) return u'{}::{}'.format( self._rust_type(field.default.union_data_type), self.enum_variant_name(default_variant)) elif isinstance(field.data_type, ir.Boolean): if field.default: return u'true' else: return u'false' elif isinstance(field.data_type, ir.String): if not field.default: return u'String::new()' else: return u'"{}".to_owned()'.format(field.default) else: print(u'WARNING: unhandled default value {}'.format(field.default)) print(u' in field: {}'.format(field)) if isinstance(field.data_type, ir.Alias): print(u' unwrapped alias: {}'.format( ir.unwrap_aliases(field.data_type)[0])) return field.default
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)
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(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 _determine_validator_type(self, data_type, value): data_type, nullable = unwrap_nullable(data_type) if is_list_type(data_type): item_validator = self._determine_validator_type( data_type.data_type, value) if item_validator: v = "arrayValidator({})".format( self._func_args([ ("minItems", data_type.min_items), ("maxItems", data_type.max_items), ("itemValidator", item_validator), ])) else: return None elif is_numeric_type(data_type): v = "comparableValidator({})".format( self._func_args([ ("minValue", data_type.min_value), ("maxValue", data_type.max_value), ])) elif is_string_type(data_type): pat = data_type.pattern if data_type.pattern else None pat = pat.encode('unicode_escape').replace( six.ensure_binary("\""), six.ensure_binary("\\\"")) if pat else pat v = "stringValidator({})".format( self._func_args([ ("minLength", data_type.min_length), ("maxLength", data_type.max_length), ("pattern", '"{}"'.format(six.ensure_str(pat)) if pat else None), ])) else: return None if nullable: v = "nullableValidator({})".format(v) return v
def _determine_validator_type(self, data_type, value): data_type, nullable = unwrap_nullable(data_type) if is_list_type(data_type): item_validator = self._determine_validator_type(data_type.data_type, value) if item_validator: v = "arrayValidator({})".format( self._func_args([ ("minItems", data_type.min_items), ("maxItems", data_type.max_items), ("itemValidator", item_validator), ]) ) else: return None elif is_numeric_type(data_type): v = "comparableValidator({})".format( self._func_args([ ("minValue", data_type.min_value), ("maxValue", data_type.max_value), ]) ) elif is_string_type(data_type): pat = data_type.pattern if data_type.pattern else None pat = pat.encode('unicode_escape').replace("\"", "\\\"") if pat else pat v = "stringValidator({})".format( self._func_args([ ("minLength", data_type.min_length), ("maxLength", data_type.max_length), ("pattern", '"{}"'.format(pat) if pat else None), ]) ) else: return None if nullable: v = "nullableValidator({})".format(v) 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_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