Пример #1
0
    def __init__(self, *args: Union[FunOwlBase, IRI.types()],
                 **kwargs: Dict[str, FunOwlBase]) -> None:
        args = list(args)
        if args and isinstance(args[0],
                               IRI) and not isinstance_(args[0], Axiom):
            self.iri = args.pop(0)
        if args and isinstance(args[0],
                               IRI) and not isinstance_(args[0], Axiom):
            self.version = args.pop(0)
        self.directlyImportsDocuments = cast(List[Import], [])
        while args and isinstance(args[0], Import):
            self.directlyImportsDocuments.append(args.pop(0))
        self.axioms = cast(List[Axiom], [])
        while args and isinstance_(args[0], Axiom):
            self.axioms.append(args.pop(0))
        self.annotations = kwargs.get('annotations', [])
        for k, v in kwargs.items():
            cur_v = getattr(self, k, MISSING)
            if cur_v is MISSING:
                raise ValueError(f"Unknown argument to Ontology: {k}")
            if cur_v is None:
                setattr(self, k, v)
            elif k != 'annotations':
                setattr(self, k, cur_v + v)

        if args:
            raise ValueError(f"Unrecognized arguments to Ontology: {args}")
        self._naxioms = 0
Пример #2
0
def cast(typ: Type, v: Any, _coercion_allowed: Optional[bool] = None) -> Any:
    """
    Convert value v to type typ.  Raises TypeError if conversion is not possible.  Note that None and empty lists are
    treated as universal types

    :param typ: type to convert v to
    :param v: value to convert to type
    :param _coercion_allowed: True means type coercion is allowed.  False means only matching types work
    :return: instance of type
    """
    from funowl.base.fun_owl_choice import FunOwlChoice

    if v is None or v == []:  # Null and empty list are always allowed (a bit too permissive but...)
        return v

    # Union[...]
    if is_union(typ):
        for t in get_args(typ):
            if type(v) is t:
                return v
            elif _coercion_allowed is not False and isinstance_(v, t):
                return cast(t, v)
        raise TypeError(f"Type mismatch between {v} (type: {type(v)} and {typ}")

    # List[...]
    if is_iterable(typ):
        list_type = get_args(typ)[0]
        if isinstance(v, str) or not isinstance(v, Iterable):  # You can assign a singleton directly
            v = [v]
        return [cast(list_type, vi) for vi in v]

    if issubclass(type(v), typ):        # conversion is treated as idempotent (typ(typ(v)) = typ(v)
        return copy(v)

    if isinstance(typ, type) and issubclass(typ, FunOwlChoice):
        hints = typ.hints()
        pos_types = ', '.join([t.__name__ for t in hints])
        logging.debug(f"value: {v} (type: {type(v)}) testing against {typ}[{pos_types}]")
        for poss_type in hints:
            if issubclass(type(v), poss_type) or (_coercion_allowed is not False and isinstance(v, poss_type)):
                logging.debug(f"     Matches {poss_type.__name__}")
                if getattr(poss_type, '_parse_input', None):
                    return typ(poss_type(*poss_type._parse_input(v)))
                return typ(poss_type(v))
        logging.debug('     No match')

    # Determine whether v can be cooreced into type
    if _coercion_allowed is False or not isinstance_(v, typ):
        raise TypeError(f"value: {v} (type: {type(v)}) cannot be converted to {typ}")

    # Vanilla typing
    return typ(*(getattr(typ, '_parse_input', lambda e: e))(v))
Пример #3
0
 def add_arg(self, arg: [IRI.types(), Import, Axiom, Annotation]):
     if isinstance_(arg, Axiom):
         self.axioms.append(arg)
         self._naxioms += 1
         if not self._naxioms % 100000:
             print('H')
         elif not self._naxioms % 10000:
             print('K')
         elif not self._naxioms % 1000:
             print('k', end='')
             sys.stdout.flush()
         elif not self._naxioms % 100:
             print('.', end='')
             sys.stdout.flush()
     elif isinstance(arg, IRI):
         if not self.iri:
             self.iri = arg
         elif not self.version:
             self.version = arg
         else:
             raise ValueError(f"Raw IRI is not a valid argument {arg}")
     elif isinstance(arg, Import):
         self.directlyImportsDocuments.append(arg)
     elif isinstance(arg, Annotation):
         self.annotations.append(arg)
     else:
         raise ValueError(f"Unrecognized argument to Ontology: {arg}")
Пример #4
0
 def set_v(self, value: Any) -> bool:
     """ Default setter -- can be invoked from more elaborate coercion routines
     :param value: value to set
     :return: True if v was set
     """
     for choice_type in self.hints():
         if issubclass(
                 type(value),
                 choice_type) or (self._coercion_allowed
                                  and isinstance_(value, choice_type)):
             super().__setattr__('v', value)
             logging.debug(
                 f"{type(self).__name__}: value = {str(self.v)} (type: {type(self.v).__name__})"
             )
             return True
     return False
Пример #5
0
def remove_exclusions(typ: Union[Field, Type]) -> Union[List[Type], Type]:
    """
    Convert typ into an ordered list of possible types, removing any exclusions

    :param typ: Field, FunOwlChoice instance or Type definition
    :return: Ordered list of types with exclusions removed
    """
    from funowl.base.fun_owl_choice import FunOwlChoice

    if isinstance(typ, type) and issubclass(typ, FunOwlChoice):
        return typ.real_types()

    if isinstance_(typ, Field):
        # If it is a field, the actual type is Field.type.
        if is_union(typ.type):
            exclusions = typ.metadata.get('exclude', [])
            return [t for t in get_args(typ.type) if t not in exclusions]
        else:
            typ = typ.type
    return [typ]
Пример #6
0
def cast(cast_to: Union[Type, Field],
         v: Any,
         _coercion_allowed: Optional[bool] = None) -> Any:
    """
    Convert value v to type cast_to.  Raises TypeError if conversion is not possible.  Note that None and empty lists are
    treated as universal types

    :param cast_to: Field, FunOwlChoice instance or Type definition we want to cast v to
    :param v: value to cast.  Note that None and empty lists are treated as always cast.
    :param _coercion_allowed: True means type coercion is allowed.  False means only matching types work
    :return: instance of cast_to
    """
    from funowl.base.fun_owl_choice import FunOwlChoice

    def cast_to_choice(choice: FunOwlChoice, v: Any) -> Any:
        """ Process a choice """
        hints = choice.real_types()
        for poss_type in hints:
            if issubclass(type(v), poss_type):
                return choice_match(poss_type)
        for poss_type in hints:
            if issubclass(type(v),
                          poss_type) or (_coercion_allowed is not False
                                         and isinstance(v, poss_type)):
                return choice_match(poss_type)
        logging.debug('     No match')

    def choice_match(matched_type: Type) -> Any:
        if hasattr(matched_type, '_parse_input'):
            rval = typ(matched_type(*matched_type._parse_input(v)))
        else:
            rval = typ(matched_type(v))
        return rval

    # TODO: this should be a parameterized type for return
    def do_cast(target_type: Type, target_value: Any) -> Any:
        return target_type(
            *(getattr(target_type, '_parse_input', lambda e: e))(target_value))

    # None and empty lists are universal types.  If already cast, we're done
    if v is None or v == [] or (isinstance_(cast_to, Field) and
                                type(v) is cast_to.type) or type(v) is cast_to:
        return v

    # Create an ordered list of target types -- these are the types IN cast_to
    type_list = remove_exclusions(cast_to)

    # If we already match the list, no coercion is necessary
    for typ in type_list:
        if type(v) is typ:
            return v

    # Iterate through the list to determine whether we can coerce v to any of the targets
    if _coercion_allowed is not False:
        for typ in type_list:
            # Note: This parallels the code in TypingHelper.isinstance_  -- it may be worth considering merging these
            # with a visitor idiom

            # Any / unrealized TypeVar is the identity function
            # TODO: not all TypeVar situations will work here
            if typ is Any or isinstance(typ, TypeVar):
                return do_cast(typ, v)

            elif isinstance_(typ, FunOwlChoice):
                return cast_to_choice(typ, v)

            elif is_union(typ):
                for t in get_args(typ):
                    if isinstance_(v, t):
                        if type(v) is t:
                            return v
                        else:
                            return do_cast(t, v)

            elif is_dict(typ):
                if isinstance(v, dict):
                    dict_args = get_args(typ)
                    return {
                        cast(dict_args[0], dk): cast(dict_args[1], dv)
                        for dk, dv in v.items()
                    } if dict_args else v

            elif is_list(typ):
                # casting x == [x]
                if isinstance(v, str) or not isinstance(v, Iterable):
                    v = [v]
                if isinstance(v, list) or isinstance(v, UserList):
                    list_type = get_args(typ)
                    return [cast(list_type[0], vi)
                            for vi in v] if list_type else v

            elif is_tuple(typ):
                if isinstance(v, tuple):
                    tuple_args = get_args(typ)
                    return tuple(
                        cast(tt, vt)
                        for tt, vt in zip(tuple_args, v)) if tuple_args else v

            elif is_set(typ):
                if isinstance_(v, set):
                    set_type = get_args(typ)
                    return set(cast(set_type[0], e)
                               for e in v) if set_type else v

            elif isinstance_(v, typ):
                return do_cast(typ, v if issubclass(typ, str) else copy(v))

    raise TypeError(
        f"Type mismatch between {v} (type: {type(v)} and {type_list}")
Пример #7
0
 def __instancecheck__(self, instance) -> bool:
     return instance is not None and \
            isinstance_(instance, self.python_type) and (self.pattern is None or self.pattern.matches(str(instance)))
Пример #8
0
    def test_isinstance(self):
        self.assertTrue(isinstance_(int, Any))
        self.assertTrue(isinstance_(None, Any))
        self.assertTrue(isinstance_(Any, Any))

        self.assertTrue(isinstance_(17, inst_union))
        self.assertTrue(isinstance_("fred", inst_union))
        self.assertTrue(isinstance_(False, inst_union))

        self.assertTrue(isinstance_(Class("http://example.org"), inst_union))

        self.assertTrue(isinstance_({"k": 42}, inst_union))
        self.assertFalse(isinstance_({"k": 42}, inst_union_2))
        self.assertTrue(isinstance_({"k": "abc"}, inst_union_2))
        self.assertTrue(isinstance_({"k": "abc", "l": "def"}, inst_union_2))
        self.assertFalse(isinstance_({"k": "abc", "l": True}, inst_union_2))
        self.assertTrue(isinstance_({"k": "abc", "l": True}, Union[Dict]))
        self.assertTrue(isinstance_({"k": "abc", "l": True}, Union[dict]))
        self.assertTrue(isinstance_({}, inst_union_2))

        self.assertTrue(isinstance_((17, "a"), inst_union))
        self.assertFalse(isinstance_(("a", "a"), inst_union))

        self.assertTrue(
            isinstance_(([1, 2, 3], [True, False, True]), Tuple[List[int],
                                                                List[bool]]))