def test_bad_argument(self): # type: () -> None with pytest.raises(TypeError): attr_is_instance_or_instance_tuple('not a type') # type: ignore with pytest.raises(TypeError): attr_is_instance_or_instance_tuple( (int, 'also not a type')) # type: ignore
class ForTest(object): foo = attr.ib(default=1, validator=attr_is_instance_or_instance_tuple(int)) bar = attr.ib( default='hello', validator=attr_is_instance_or_instance_tuple( (six.text_type, six.binary_type)), )
class ObjectInstance(Base): """ Accepts only instances of a given class or type """ introspect_type = 'object_instance' valid_type = attr.ib(validator=attr_is_instance_or_instance_tuple( type)) # type: Union[Type, TupleType[Type, ...]] description = attr.ib( default=None, validator=attr_is_optional( attr_is_string())) # type: Optional[six.text_type] def errors(self, value): if not isinstance(value, self.valid_type): return [ Error('Not an instance of {}'.format(self.valid_type.__name__)) ] return [] def introspect(self): return strip_none({ 'type': self.introspect_type, 'description': self.description, # Unfortunately, this is the one sort of thing we can't represent # super well. Maybe add some dotted path stuff in here. 'valid_type': repr(self.valid_type), })
class ObjectInstance(Base): """ Conformity field that ensures that the value is an instance of the given `valid_type`. """ introspect_type = 'object_instance' valid_type = attr.ib(validator=attr_is_instance_or_instance_tuple( type)) # type: Union[Type, TupleType[Type, ...]] description = attr.ib( default=None, validator=attr_is_optional( attr_is_string())) # type: Optional[six.text_type] def errors(self, value): # type: (AnyType) -> ListType[Error] if not isinstance(value, self.valid_type): return [ Error('Not an instance of {}'.format( getattr(self.valid_type, '__name__', repr(self.valid_type)))) ] return [] def introspect(self): # type: () -> Introspection return strip_none({ 'type': self.introspect_type, 'description': self.description, # Unfortunately, this is the one sort of thing we can't represent # super well. Maybe add some dotted path stuff in here. 'valid_type': repr(self.valid_type), })
class TypeReference(Base): """ Conformity field that ensures that the value is an instance of `type` and, optionally, that the value is a subclass of the type or types specified by `base_classes`. """ introspect_type = 'type_reference' base_classes = attr.ib( default=None, validator=attr_is_optional(attr_is_instance_or_instance_tuple(type)), ) # type: Optional[Union[Type, TupleType[Type, ...]]] description = attr.ib( default=None, validator=attr_is_optional( attr_is_string())) # type: Optional[six.text_type] def errors(self, value): # type: (AnyType) -> ListType[Error] if not isinstance(value, type): return [Error('Not a type')] if self.base_classes and not issubclass(value, self.base_classes): return [ Error( 'Type {} is not one of or a subclass of one of: {}'.format( value, self.base_classes)) ] return [] def introspect(self): # type: () -> Introspection base_classes = None if self.base_classes: if isinstance(self.base_classes, type): base_classes = [six.text_type(self.base_classes)] else: base_classes = [six.text_type(c) for c in self.base_classes] return strip_none({ 'type': self.introspect_type, 'description': self.description, 'base_classes': base_classes, })
class TypeReference(Base): """ Accepts only type references, optionally types that must be a subclass of a given type or types. """ introspect_type = 'type_reference' base_classes = attr.ib( default=None, validator=attr_is_optional(attr_is_instance_or_instance_tuple(type)), ) # type: Optional[Union[Type, TupleType[Type, ...]]] description = attr.ib( default=None, validator=attr_is_optional( attr_is_string())) # type: Optional[six.text_type] def errors(self, value): if not isinstance(value, type): return [Error('Not a type')] if self.base_classes and not issubclass(value, self.base_classes): return [ Error( 'Type {} is not one of or a subclass of one of: {}'.format( value, self.base_classes)) ] return [] def introspect(self): base_classes = None if self.base_classes: if isinstance(self.base_classes, type): base_classes = [six.text_type(self.base_classes)] else: base_classes = [six.text_type(c) for c in self.base_classes] return strip_none({ 'type': self.introspect_type, 'description': self.description, 'base_classes': base_classes, })