def clean(self, value): """Cleans an input value for an AMQP composite type field.""" # If the field is mandatory, `value` may not be None or NOT_PROVIDED if value in (None, NOT_PROVIDED): if self.mandatory: raise ValidationError("required", self, value) # If the field is not mandatory, bail out early with a basetypes.Null # instance. return Null() # If the field specified its type name as "*", `value` is assumed to be # either a tuple of (type name, value) or a Provider which satisfied # the requirements of the field. if self.type_name == "*": if not isinstance(value, Provider): # Restricted types are provided as (type_name, value) assert len(value) == 2 type_name, value = value meta = get_by_type_name(type_name) value = meta.create(value) if not self.multiple else self.clean_multiple(meta, value) self.clean_provider(value) else: meta = get_by_type_name(self.type_name) # If the field allows multiple values, the input value must be an a list # or an Array holding the members. Note that at this point, polymorphic # field types have already been casted to a Provider instance, for which # validation has already been done. if self.multiple and self.type_name != "*": members = value assert isinstance(value, list) # Array instances must be monomorphic, polymorphic collecions # are a validation error. if len(set(map(type, members))) > 1: raise ValidationError("polymorphic", self, members) value = Array.create("array", [meta.create(x) for x in members]) elif not isinstance(value, Encodable): value = meta.create(value) # At this point, value MUST be an Encodable. assert isinstance(value, Encodable) return value
def create(self, *args): """Create an instance of the AMQP type specified by :attr:`type_name`. """ meta = get_by_type_name(self.type_name) if meta.is_restricted(): # Restricted types are always scalar, so the first # argument is the desired input value. args = args[0] if args else None if not args: args = [None] instance = meta.create(*args) self._run_validators(instance) return instance
def create(self, value): """Create a new instance of the defined AMQP type. Return an :class:`.Encodable` instance representing the cleaned and validated input. """ value = self.clean(value) if self.type_class == 'primitive': # If the Meta represents a primitive type, simple clean and validate # and return the appropriate Encodable implementation. return basetypes.encodable_factory(self.type_name, value) elif self.type_class == 'restricted': source = get_by_type_name(self.source) return Restricted.frommeta(self, source.create(value)) else: assert self.type_class == 'composite' return Composite.frommeta(self, value)
def encodable(type_name, value): """Create a new :class:`.Composite` or :class:`.Restricted` instance.""" meta = registry.get_by_type_name(type_name) return meta.create(value)