예제 #1
0
    def _validate(self,
                  val: list,
                  log: Optional[Logger] = None) -> Tuple[bool, List[str]]:
        """ Determine whether val is a valid instance of this array

        :returns: Success indicator and error list """
        errors = []
        if not isinstance(val, list):
            errors.append(
                f"{self._variable_name}: {repr(val)} is not an array")
        else:
            for i in range(0, len(val)):
                v = val[i]
                if not conforms(v, self._type, self._context.NAMESPACE):
                    errors.append(
                        f"{self._variable_name} element {i}: {v} is not a {self._type.__name__}"
                    )

            if len(val) < self._min:
                errors.append(
                    f"{self._variable_name}: at least {self._min} value{'s' if self._min > 1 else ''} required - "
                    f"element has {len(val) if len(val) else 'none'}")
            if self._max is not None and len(val) > self._max:
                errors.append(
                    f"{self._variable_name}: no more than {self._max} values permitted - element has {len(val)}"
                )

        if log:
            for error in errors:
                log.log(error)
        return not bool(errors), errors
예제 #2
0
    def _map_jsg_type(
            self, name: str, element: Any,
            poss_types: Union[type, Tuple[type]]) -> Optional[JSGValidateable]:
        def _wrap(ty, el):
            # The first option is when we are assigning already loaded types
            # The second option addresses the optional situation
            return el if isinstance(
                el, JSGValidateable) or ty is type(None) else ty(el)

        for typ in poss_types if isinstance(poss_types,
                                            tuple) else (poss_types, ):
            if isinstance(typ, str):
                if typ in self._context.NAMESPACE:
                    typ = self._context.NAMESPACE[typ]
                else:
                    #raise ValueError(f"Unknown type: {typ}")
                    raise ValueError("Unknown typr: " + typ)
            typ = proc_forward(typ, self._context.NAMESPACE)
            if is_union(typ):
                for t in typ.__args__:
                    et = self._map_jsg_type(name, element, t)
                    if et is not None:
                        return et
            elif conforms(element, typ, self._context.NAMESPACE):
                return _wrap(typ, element)
        return None
예제 #3
0
 def _is_valid_element(self, log: Logger, name: str,
                       val: Type[JSGValidateable]) -> bool:
     if name not in self._members:
         return any(e._is_valid_element for e in self._reference_types)
     else:
         etype = self._members[name]
         if etype is JSGNull:
             return val is JSGNull or val is None
         if val is None and type(etype) is type(AnyType):
             return False
         if val is not None and val is not Empty and isinstance(
                 val, JSGArray):
             if not val._validate(cast(list, val),
                                  log)[0] and not log.logging:
                 return False
         elif not conforms(val, etype, self._context.NAMESPACE
                           ):  # Note: None and absent are equivalent
             if val is None or val is Empty:
                 if log.log("{}: Missing required field: '{}'".format(
                         self.__class__.__name__, name)):
                     return False
             else:
                 if log.log(
                         "{}: Type mismatch for {}. Expecting: {} Got: {}".
                         format(self.__class__.__name__, name, etype,
                                type(val))):
                     return False
         elif val is not None and not self._test(
                 val, log):  # Make sure that entry conforms to its own type
             return False
     return True
예제 #4
0
 def __instancecheck__(self, instance: list) -> bool:
     if not isinstance(instance, list):
         return False
     for element in instance:
         if not conforms(element, self.typ, self.context.NAMESPACE):
             return False
     return len(instance) >= self.min and (not self.max or len(instance) <= self.max)
예제 #5
0
    def __setattr__(self, key: str, value: Any):
        """
        Screen attributes for name and type.  Anything starting with underscore ('_') goes, anything in the IGNORE list
        and anything declared in the __init_ signature
        :param key:
        :param value:
        :return:
        """

        if not key.startswith("_") and not self._context.unvalidated_parm(key):
            if self._name_filter is not None:
                if not isinstance(key, self._name_filter):
                    raise ValueError(f"Illegal Object Map key: {key}={value}")
            if not conforms(value, self._value_type, self._context.NAMESPACE):
                raise ValueError("Illegal value type {} = {}".format(key, value))
            if not isinstance(value, JSGValidateable):
                value = self._value_type('', self._context, value) \
                    if self._value_type is AnyType else self._value_type(value)
        self[key] = value
예제 #6
0
 def __instancecheck__(self, element: object) -> bool:
     return conforms(element, JSGObject, self.context.NAMESPACE)