Source code for typerighter.types.composites

from . import primitives
from . import domains
from .. import exceptions


[docs]class SumType(primitives.Primitive): """ Some languages call this a *Union Type*. The idea is to allow validation to pass if just one validator, from a list of two or more types, accepts it. """ def __init__(self, *types, **kwargs): super(SumType, self).__init__(**kwargs) self.types = types def _find_variant(self, value): for t in self.types: try: t.validate(value) return t except exceptions.ValidationException: pass else: err_msg = "No matching variant for value: {}" raise exceptions.TypeException(err_msg.format(value))
[docs] def is_type_match(self, value): for t in self.types: print(t.is_type_match(value)) print(isinstance(value, t.NATIVE)) if t.is_type_match(value): return True else: return False
[docs] def to_schematic(self): variant_schematics = list() for t in self.types: schematic = t.to_schematic() variant_schematics.append(schematic) return (self.__class__.__name__, variant_schematics)
[docs] def to_primitive(self, value, **kw): t = self._find_variant(value) return t.to_primitive(value, **kw)
[docs] def to_native(self, value, **kw): t = self._find_variant(value) return t.to_native(value, **kw)
def validate_by_variant_match(self, value): t = self._find_variant(value) if not t: e_msg = "Value did not pass any type checks: {}" raise exceptions.ValidationException(e_msg.format(value))
[docs]class Container(primitives.Primitive): """ A `Container` is a foundational type, like `Primitive`, that allows some number of things to be held in a group, with no additional type checking past what a `Primitive` does. New composite types should subclass this base type. It is not meant to be used directly. """ def __init__(self, type, max_length=None, min_length=None, **kw): super().__init__(**kw) self.type = type domains.LengthDomain(self, max_length, min_length)
[docs] def is_falsy(self, value): if value is None or super().is_falsy(value): return True # If calling len works, it's iterable try: if len(value) > 0: return False except Exception: pass return True
def validate_items(self, value): err_msg = "Container is an abstract type %s" raise exceptions.ValidationException(err_msg % (self.type))
[docs]class ListType(Container): """ A `ListType` is a `Container` implemented with a `list`. """ NATIVE = list
[docs] def to_schematic(self): variant_schematics = list() for t in self.types: schematic = t.to_schematic() variant_schematics.append(schematic) return (self.__class__.__name__, variant_schematics)
[docs] def to_primitive(self, value, **kw): if self.is_falsy(value): return value return [self.type.to_primitive(v, **kw) for v in value]
[docs] def to_native(self, value, **kw): if self.is_falsy(value): return value return [self.type.to_native(v, **kw) for v in value]
def validate_items(self, value): if self.is_falsy(value): return for v in value: try: self.type.validate(v) break except exceptions.ValidationException: pass else: e_msg = "No types in list match for item {}" raise exceptions.ValidationException(e_msg.format(value))