Exemplo n.º 1
0
 def test_generic_forvard_ref(self):
     LLT = List[List['CC']]
     class CC: pass
     self.assertEqual(typing._eval_type(LLT, globals(), locals()), List[List[CC]])
     T = TypeVar('T')
     TTE = Tuple[T, ...]
     self.assertIs(typing._eval_type(TTE, globals(), locals()), Tuple[T, ...])
Exemplo n.º 2
0
def resolve_annotations(raw_annotations: Dict[str, Type[Any]],
                        module_name: Optional[str]) -> Dict[str, Type[Any]]:
    """
    Partially taken from typing.get_type_hints.

    Resolve string or ForwardRef annotations into type objects if possible.
    """
    if module_name:
        base_globals: Optional[Dict[str,
                                    Any]] = sys.modules[module_name].__dict__
    else:
        base_globals = None
    annotations = {}
    for name, value in raw_annotations.items():
        if isinstance(value, str):
            if sys.version_info >= (3, 7):
                value = ForwardRef(value, is_argument=False)
            else:
                value = ForwardRef(value)
        try:
            value = _eval_type(value, base_globals, None)
        except NameError:
            # this is ok, it can be fixed with update_forward_refs
            pass
        annotations[name] = value
    return annotations
Exemplo n.º 3
0
def get_canonical_type_hints(cls: Type) -> Dict[str, Union[Type, ForwardRef]]:
    """Extract class type annotations returning forward references for partially undefined types.

    The canonicalization consists in returning either a fully-specified type
    annotation or a :class:`typing.ForwarRef` instance with the type annotation
    for not fully-specified types.

    Based on :func:`typing.get_type_hints` implementation.
    """
    hints: Dict[str, Union[Type, ForwardRef]] = {}

    for base in reversed(cls.__mro__):
        base_globals = sys.modules[base.__module__].__dict__
        ann = base.__dict__.get("__annotations__", {})
        for name, value in ann.items():
            if value is None:
                value = type(None)
            elif isinstance(value, str):
                value = ForwardRef(value, is_argument=False)

            try:
                value = typing._eval_type(
                    value, base_globals, None
                )  # type: ignore[attr-defined]  # typing._eval_type is not public
            except NameError as e:
                if "ForwardRef(" not in repr(value):
                    raise e
            if not isinstance(value,
                              ForwardRef) and "ForwardRef(" in repr(value):
                value = canonicalize_forward_ref(value)

            hints[name] = value

    return hints
Exemplo n.º 4
0
def get_class_type_hints_strict(
        cls: type,
        globalns: Mapping[str, Any] = None,
        localns: Mapping[str, Any] = None) -> Dict[str, type]:
    if not inspect.isclass(cls):
        raise TypeError(
            "cls needs to be a class. Use typing.get_type_hints for other types"
        )

    if globalns is None:
        globalns = sys.modules[cls.__module__].__dict__

    ann = cls.__dict__.get("__annotations__", {})

    hints = {}

    for name, value in ann.items():
        if value is None:
            value = type(None)
        if isinstance(value, str):
            value = ForwardRef(value, is_argument=False)

        value = _eval_type(value, globalns, localns)
        hints[name] = value

    return hints
Exemplo n.º 5
0
def eval_type(obj: Annotation, globals_: dict, locals_: dict, recursive_guard: frozenset = frozenset()) -> Annotation:
    """
    Evaluate all forward references in the given type t.
    For use of globals_ and locals_ see the docstring for get_type_hints().
    recursive_guard is used to prevent infinite recursion with recursive ForwardRef.
    """
    return typing._eval_type(obj, globals_, locals_, recursive_guard)
Exemplo n.º 6
0
def get_class_type_hints(klass: Type, localns=None) -> Dict[str, Any]:
    """Return type hints for a class. Adapted from `typing.get_type_hints`, adds support for PEP 585 & PEP 604"""
    hints = {}
    for base in reversed(klass.__mro__):
        base_globals = sys.modules[base.__module__].__dict__
        base_globals['_Union'] = Union
        if sys.version_info < (3, 9):
            base_globals['_List'] = List
            base_globals['_Set'] = Set
            base_globals['_Type'] = Type
            base_globals['_Tuple'] = Tuple
            base_globals['_Dict'] = Dict
        ann = base.__dict__.get('__annotations__', {})
        for name, value in ann.items():
            if value is None:
                value = type(None)
            if isinstance(value, str):
                t = ast.parse(value, '<unknown>', 'eval')
                union_transformer = RewriteUnionTypes()
                t = union_transformer.visit(t)
                builtin_generics_transformer = RewriteBuiltinGenerics()
                if sys.version_info < (3, 9):
                    t = builtin_generics_transformer.visit(t)
                if builtin_generics_transformer.rewritten or union_transformer.rewritten:
                    # Note: ForwardRef raises a TypeError when given anything that isn't a string, so we need
                    # to compile & eval the ast here
                    code = compile(t, '<unknown>', 'eval')
                    hints[name] = eval(code, base_globals, localns)
                    continue
                else:
                    value = ForwardRef(value, is_argument=False)
            value = _eval_type(value, base_globals, localns)
            hints[name] = value
    return hints
Exemplo n.º 7
0
def resolve_annotations(raw_annotations: Dict[str, Type[Any]],
                        module_name: Optional[str]) -> Dict[str, Type[Any]]:
    """
    Partially taken from typing.get_type_hints.

    Resolve string or ForwardRef annotations into type objects if possible.
    """
    base_globals: Optional[Dict[str, Any]] = None
    if module_name:
        try:
            module = sys.modules[module_name]
        except KeyError:
            # happens occasionally, see https://github.com/samuelcolvin/pydantic/issues/2363
            pass
        else:
            base_globals = module.__dict__

    annotations = {}
    for name, value in raw_annotations.items():
        if isinstance(value, str):
            if sys.version_info >= (3, 7):
                value = ForwardRef(value, is_argument=False)
            else:
                value = ForwardRef(value)
        try:
            value = _eval_type(value, base_globals, None)
        except NameError:
            # this is ok, it can be fixed with update_forward_refs
            pass
        annotations[name] = value
    return annotations
Exemplo n.º 8
0
 def _eval_type(self, globalns, localns):
     new_tp = typing._eval_type(self.__type__, globalns, localns)
     if new_tp == self.__type__:
         return self
     return type(self)(self.__name__, self.__bases__,
                       dict(self.__dict__), tp=self.__type__,
                       _root=True)
Exemplo n.º 9
0
def annodize(name="__main__", annotations=None):
    globals, locals = map(vars, map(importlib.import_module, [name] * 2))
    __annotations__ = globals.get("__annotations__", {})
    annotations = toolz.keymap(Forward, (annotations or {}))
    annotations = toolz.keymap(lambda x: typing._eval_type(x, globals, locals),
                               annotations)
    for key, value in __annotations__.items():
        if getattr(value, "__forward_coerce__", False) is True:
            value.__forward_coerce__ = key
        if value in annotations:
            new = copy.copy(annotations[value])

            if getattr(new, "__forward_coerce__", False) is True:
                new.__forward_coerce__ = key
            __annotations__[key] = typing.Union[value, new]

        typing._eval_type(__annotations__[key], globals, locals)
Exemplo n.º 10
0
 def _get_typed_annotation(self, param: inspect.Parameter,
                           globalns: Dict[str, Any]) -> Any:
     try:
         if isinstance(param.annotation, str):
             return _eval_type(ForwardRef(param.annotation), globalns,
                               globalns)
         else:
             return param.annotation
     except Exception:
         return param.annotation
Exemplo n.º 11
0
def _evaluate_type(typ: t.Type[t.Any], field: Field[t.Any]) -> t.Type[t.Any]:
    field_type = field.type
    if not isinstance(field_type, str):
        return field_type

    m = sys.modules[typ.__module__]
    # TODO: the types that defined in closure is not supported yet
    field_type = field.type = t._eval_type(t.ForwardRef(field_type),
                                           m.__dict__, typ.__dict__)
    return field_type
Exemplo n.º 12
0
def evaluate_forward_reference(forward_reference, module_name=None):
    """
    Evaluate a forward reference using the module name's dict
    """
    if module_name:
        try:
            globalns = sys.modules[module_name].__dict__
        except (KeyError, AttributeError):
            globalns = None
    else:
        globalns = None
    return _eval_type(forward_reference, globalns, None)
Exemplo n.º 13
0
def evaluate(tp: t.Union[str, t.TypeVar, t.Type, t.ForwardRef], *, frame=None):
    if isinstance(tp, str):
        tp = t.ForwardRef(tp)

    if ti.is_typevar(tp):
        tp = ti.get_bound(tp)

    # TODO python versions
    return t._eval_type(
        tp,
        frame.f_globals if frame else None,
        frame.f_locals if frame else None,
    )
Exemplo n.º 14
0
def _class_annotations(cls, globalns, localns):
    hints = {}
    if globalns is None:
        base_globals = sys.modules[cls.__module__].__dict__
    else:
        base_globals = globalns
    for name, value in cls.__dict__.get("__annotations__", {}).items():
        if value is None:
            value = type(None)
        if isinstance(value, str):
            value = ForwardRef(value, is_argument=False)
        hints[name] = _eval_type(value, base_globals, localns)
    return hints
Exemplo n.º 15
0
def resolve_type(
    type_hint: Any,
    global_ns: Optional[Dict[str, Any]] = None,
    local_ns: Optional[Dict[str, Any]] = None,
    *,
    allow_partial: bool = False,
) -> Union[Type, ForwardRef]:
    """Resolve forward references in type annotations.

    Arguments:
        global_ns: globals dict used in the evaluation of the annotations.
        local_ns: locals dict used in the evaluation of the annotations.

    Keyword Arguments:
        allow_partial: if ``True``, the resolution is allowed to fail and
            a :class:`typing.ForwardRef` will be returned.

    Examples:
        >>> import typing
        >>> resolve_type(
        ...     typing.Dict[typing.ForwardRef('str'), 'typing.Tuple["int", typing.ForwardRef("float")]']
        ... )
        typing.Dict[str, typing.Tuple[int, float]]

    """
    actual_type = ForwardRef(type_hint) if isinstance(type_hint,
                                                      str) else type_hint
    while "ForwardRef(" in repr(actual_type):
        try:
            if local_ns:
                safe_local_ns = {**local_ns}
                safe_local_ns.setdefault("typing", sys.modules["typing"])
                safe_local_ns.setdefault("NoneType", type(None))
            else:
                safe_local_ns = {
                    "typing": sys.modules["typing"],
                    "NoneType": type(None)
                }
            actual_type = typing._eval_type(  # type: ignore[attr-defined]  # typing._eval_type is not visible for mypy
                actual_type,
                global_ns,
                safe_local_ns,
            )
        except Exception as e:
            if allow_partial:
                actual_type = canonicalize_forward_ref(actual_type)
                break
            else:
                raise e

    return actual_type
Exemplo n.º 16
0
    def _eval_type(self, globals, locals, **kwargs):
        for arg in (self.__forward_arg__ if toolz.isiterable(
                self.__forward_arg__) else (self.__forward_arg__, )):
            if isinstance(arg, str):
                arg = Forward(arg)

            if isinstance(arg, Forward):
                arg.__forward_coerce__ = (arg.__forward_coerce__
                                          or self.__forward_coerce__)

            object = typing._eval_type(arg, globals, locals)
            if (object
                    is not None) and (not isinstance(object, BaseException)):
                return object
Exemplo n.º 17
0
def eval_type(type_, globalns=None, localns=None):
    """Evaluate the type. If the type is string, evaluate it with ForwardRef.

    Args:
        type_: The type to evaluate.
        globalns: The currently known global namespace.
        localns: The currently known local namespace.

    Returns:
        The evaluated type.
    """
    globalns, localns = _get_namespace(type_, globalns, localns)
    if isinstance(type_, six.string_types):
        type_ = ForwardRef(type_)
    return _eval_type(type_, globalns, localns)
Exemplo n.º 18
0
 def get_type(self, forwarded_type):
     actual_type = None
     for base in self._obj.__mro__:
         base_globals = sys.modules[base.__module__].__dict__
         ref = forwarded_type
         if isinstance(forwarded_type, str):
             ref = ForwardRef(forwarded_type, is_argument=False)
         try:
             actual_type = _eval_type(ref, base_globals, None)
             break
         except NameError:
             continue
     if not actual_type:
         raise ValidationError(f'Can not find type {forwarded_type}')
     return actual_type
Exemplo n.º 19
0
    def build_choices(
        self,
        clazz: Type,
        parent_name: str,
        parent_namespace: Optional[str],
        choices: List[Dict],
    ):
        existing_types = set()
        globalns = sys.modules[clazz.__module__].__dict__
        for choice in choices:
            xml_type = XmlType.WILDCARD if choice.get(
                "wildcard") else XmlType.ELEMENT
            namespace = choice.get("namespace")
            tokens = choice.get("tokens", False)
            nillable = choice.get("nillable", False)
            format_str = choice.get("format", None)
            default_value = choice.get("default_factory",
                                       choice.get("default"))

            types = self.real_types(_eval_type(choice["type"], globalns, None))
            is_class = any(is_dataclass(clazz) for clazz in types)
            any_type = xml_type == XmlType.ELEMENT and object in types
            derived = any(True
                          for tp in types if tp in existing_types) or any_type

            namespaces = self.resolve_namespaces(xml_type, namespace,
                                                 parent_namespace)
            default_namespace = self.default_namespace(namespaces)
            qname = build_qname(default_namespace, choice.get("name", "any"))

            existing_types.update(types)

            yield XmlVar(
                xml_type=xml_type,
                name=parent_name,
                qname=qname,
                tokens=tokens,
                format=format_str,
                derived=derived,
                any_type=any_type,
                nillable=nillable,
                dataclass=is_class,
                default=default_value,
                types=types,
                namespaces=namespaces,
            )
Exemplo n.º 20
0
def _try_import_forward_ref(thing, bound):  # pragma: no cover
    """
    Tries to import a real bound type from ``TypeVar`` bound to a ``ForwardRef``.

    This function is very "magical" to say the least, please don't use it.
    This function fully covered, but is excluded from coverage
    because we can only cover each path in a separate python version.
    """
    try:
        return typing._eval_type(bound, vars(sys.modules[thing.__module__]),
                                 None)
    except (KeyError, AttributeError, NameError):
        # We fallback to `ForwardRef` instance, you can register it as a type as well:
        # >>> from typing import ForwardRef
        # >>> from hypothesis import strategies as st
        # >>> st.register_type_strategy(ForwardRef('YourType'), your_strategy)
        return bound
Exemplo n.º 21
0
    def resolve(self) -> Union[StrawberryType, type]:
        annotation: object
        if isinstance(self.annotation, str):
            annotation = ForwardRef(self.annotation)
        else:
            annotation = self.annotation

        evaled_type = _eval_type(annotation, self.namespace, None)
        if evaled_type is None:
            raise ValueError("Annotation cannot be plain None type")
        if self._is_async_generator(evaled_type):
            evaled_type = self._strip_async_generator(evaled_type)
        if self._is_lazy_type(evaled_type):
            return evaled_type

        if self._is_generic(evaled_type):
            if any(is_type_var(type_) for type_ in evaled_type.__args__):
                return evaled_type
            return self.create_concrete_type(evaled_type)

        # Simply return objects that are already StrawberryTypes
        if self._is_strawberry_type(evaled_type):
            return evaled_type

        # Everything remaining should be a raw annotation that needs to be turned into
        # a StrawberryType
        if self._is_enum(evaled_type):
            return self.create_enum(evaled_type)
        if self._is_list(evaled_type):
            return self.create_list(evaled_type)
        elif self._is_optional(evaled_type):
            return self.create_optional(evaled_type)
        elif self._is_scalar(evaled_type):
            return evaled_type
        elif self._is_union(evaled_type):
            return self.create_union(evaled_type)
        elif is_type_var(evaled_type):
            return self.create_type_var(evaled_type)

        # TODO: Raise exception now, or later?
        # ... raise NotImplementedError(f"Unknown type {evaled_type}")
        return evaled_type
Exemplo n.º 22
0
def _dp_init_subclass(sub_cls, *args, **kwargs):
    # Add function for datapipe instance to reinforce the type
    sub_cls.reinforce_type = reinforce_type

    # TODO:
    # - add global switch for type checking at compile-time

    # Ignore internal type class
    if getattr(sub_cls, '__type_class__', False):
        return

    # Check if the string type is valid
    if isinstance(sub_cls.type.param, ForwardRef):
        base_globals = sys.modules[sub_cls.__module__].__dict__
        try:
            param = _eval_type(sub_cls.type.param, base_globals, locals())
            sub_cls.type.param = param
        except TypeError as e:
            raise TypeError("{} is not supported by Python typing".format(
                sub_cls.type.param.__forward_arg__)) from e

    if '__iter__' in sub_cls.__dict__:
        iter_fn = sub_cls.__dict__['__iter__']
        hints = get_type_hints(iter_fn)
        if 'return' in hints:
            return_hint = hints['return']
            # Plain Return Hint for Python 3.6
            if return_hint == Iterator:
                return
            if not (hasattr(return_hint, '__origin__') and
                    (return_hint.__origin__ == Iterator
                     or return_hint.__origin__ == collections.abc.Iterator)):
                raise TypeError(
                    "Expected 'Iterator' as the return annotation for `__iter__` of {}"
                    ", but found {}".format(sub_cls.__name__,
                                            _type_repr(hints['return'])))
            data_type = return_hint.__args__[0]
            if not issubtype(data_type, sub_cls.type.param):
                raise TypeError(
                    "Expected return type of '__iter__' as a subtype of {}, but found {}"
                    " for {}".format(sub_cls.type, _type_repr(data_type),
                                     sub_cls.__name__))
Exemplo n.º 23
0
def eval_type(typ: Any,
              globalns: Dict[str, Any] = None,
              localns: Dict[str, Any] = None,
              invalid_types: Set = None,
              alias_types: Mapping = None) -> Type:
    """Convert (possible) string annotation to actual type.

    Examples:
        >>> eval_type('List[int]') == typing.List[int]
    """
    invalid_types = invalid_types or set()
    alias_types = alias_types or {}
    if isinstance(typ, str):
        typ = ForwardRef(typ)
    if isinstance(typ, ForwardRef):
        # On 3.6/3.7 _eval_type crashes if str references ClassVar
        typ = _ForwardRef_safe_eval(typ, globalns, localns)
    typ = _eval_type(typ, globalns, localns)
    if typ in invalid_types:
        raise InvalidAnnotation(typ)
    return alias_types.get(typ, typ)
Exemplo n.º 24
0
def _safe_get_type_hints(
        annotation: Union[Type, Callable]) -> Dict[str, Type[Any]]:
    raw_annotations: Dict[str, Any] = {}
    base_globals: Dict[str, Any] = {"typing": typing}
    if isinstance(annotation, type):
        for base in reversed(annotation.__mro__):
            base_globals.update(sys.modules[base.__module__].__dict__)
            raw_annotations.update(
                getattr(base, "__annotations__", None) or {})
    else:
        raw_annotations = getattr(annotation, "__annotations__", None) or {}
        module_name = getattr(annotation, "__module__", None)
        if module_name:
            base_globals.update(sys.modules[module_name].__dict__)
    annotations = {}
    for name, value in raw_annotations.items():
        if isinstance(value, str):
            value = transform_annotation(value)
            if not isinstance(value, ForwardRef):
                if sys.version_info >= (3, 9, 8) and sys.version_info[:3] != (
                        3, 10, 0):
                    value = ForwardRef(  # type: ignore
                        value,
                        is_argument=False,
                        is_class=inspect.isclass(annotation),
                    )
                elif sys.version_info >= (3, 7):
                    value = ForwardRef(value, is_argument=False)
                else:
                    value = ForwardRef(value)
        try:
            value = _eval_type(value, base_globals or None, None)
        except NameError:
            # this is ok, we deal with it later.
            pass
        except TypeError as e:
            warnings.warn(f"Couldn't evaluate type {value!r}: {e}")
            value = Any
        annotations[name] = value
    return annotations
Exemplo n.º 25
0
def get_type_hints(
    obj,  # type: Any
    globalns=None,  # type: Optional[Dict[str, Any]]
    localns=None  # type: Optional[Dict[str, Any]]
):
    # type: (...) -> Dict[str, Any]
    """Return all type hints for the function.

    This attempts to use typing.get_type_hints first, but if that returns None
    then it will attempt to reuse much of the logic from the Python 3 version
    of typing.get_type_hints; the Python 2 version does nothing. In addition to
    this logic, if no code annotations exist, it will attempt to extract
    comment type hints for Python 2/3 compatibility.

    Args:
        obj: The object to search for type hints.
        globalns: The currently known global namespace.
        localns: The currently known local namespace.

    Returns:
        A mapping of value names to type hints.
    """
    hints = {}
    try:
        if not isinstance(obj, type):
            hints = _get_type_hints(obj, globalns, localns) or {}
    except TypeError:
        if not isinstance(obj, _STRING_TYPES):
            raise
    if not hints and not getattr(obj, '__no_type_check__', None):
        globalns, localns = _get_namespace(obj, globalns, localns)
        hints = _get_comment_type_hints(obj, globalns, localns)
        for name, value in six.iteritems(hints):
            if value is None:
                value = type(None)
            elif isinstance(value, _STRING_TYPES):
                value = ForwardRef(value)
            hints[name] = _eval_type(value, globalns, localns)
    return hints
Exemplo n.º 26
0
def _try_import_forward_ref(thing, bound):  # pragma: no cover
    """
    Tries to import a real bound type from ``TypeVar`` bound to a ``ForwardRef``.

    This function is very "magical" to say the least, please don't use it.
    This function fully covered, but is excluded from coverage
    because we can only cover each path in a separate python version.
    """
    try:
        return typing._eval_type(bound, vars(sys.modules[thing.__module__]),
                                 None)
    except (KeyError, AttributeError, NameError):
        if (isinstance(thing, typing.TypeVar)
                and getattr(thing, "__module__", None) == "typing"):
            raise ResolutionFailed(
                "It looks like you're using a TypeVar bound to a ForwardRef on Python "
                "3.6, which is not supported - try ugrading to Python 3.7 or later."
            ) from None
        # We fallback to `ForwardRef` instance, you can register it as a type as well:
        # >>> from typing import ForwardRef
        # >>> from hypothesis import strategies as st
        # >>> st.register_type_strategy(ForwardRef('YourType'), your_strategy)
        return bound
Exemplo n.º 27
0
 def _eval_type(self, globalns, localns):
     new_tp = typing._eval_type(self.__type__, globalns, localns)
     if new_tp == self.__type__:
         return self
     return type(self)(new_tp, _root=True)
Exemplo n.º 28
0
def proc_forward(etype, namespace: Dict[str, Any]):
    """ Resolve etype to an actual type if it is a forward reference """
    return _eval_type(etype, namespace,
                      namespace) if type(etype) is ForwardRef else etype
Exemplo n.º 29
0
def proc_forwards(cls, glob_ns) -> None:
    for f in fields(cls):
        f.type = _eval_type(f.type, glob_ns, glob_ns)
Exemplo n.º 30
0
 def _eval_type(self, globalns, localns):
     new_tp = typing._eval_type(self.__type__, globalns, localns)
     if new_tp == self.__type__:
         return self
     return type(self)(new_tp, _root=True)
Exemplo n.º 31
0
 def update_event(self, inp=-1):
     self.set_output_val(
         0,
         typing._eval_type(self.input(0), self.input(1), self.input(2),
                           self.input(3)))
Exemplo n.º 32
0
    def _eval_type(self, globals, locals, **kwargs):
        eval = self.__forward_evaluated__
        kwargs.update(self.__forward_kwargs__)
        try:
            try:
                if not isinstance(self.__forward_arg__, str):
                    self.__forward_evaluated__ = True
                    self.__forward_value__ = self.__forward_arg__
                object = typing._ForwardRef._eval_type(self, globals, locals)
            except TypeError as Exception:
                module, name = _module_and_name(self.__forward_arg__)
                return getattr(importlib.import_module(module), name,
                               Exception)
        except BaseException as Exception:
            return Exception
        if kwargs:
            for key, item in kwargs.items():
                if isinstance(item, str):
                    item = Forward(item)
                try:
                    kwargs[key] = typing._eval_type(item, globals, locals)
                except BaseException as Exception:
                    return Exception
            object = functools.partial(object, **kwargs)

        if self.__forward_observe__ and self.__forward_coerce__:
            if not eval and isinstance(self.__forward_coerce__, str):
                module, name = _module_and_name(self.__forward_coerce__)
                self.__forward_display__ = object(
                    **{
                        self.__forward_observe__:
                        getattr(importlib.import_module(module), name, None)
                    })

                def change(change):
                    nonlocal globals, locals, self
                    if not isinstance(change, dict):
                        change = dict(new=change)
                    setattr(importlib.import_module(module), name,
                            change["new"])

                if hasattr(self.__forward_display__, "param"):
                    self.__forward_display__.param.watch(
                        change, self.__forward_observe__)
                elif hasattr(self.__forward_display__, "observe"):
                    self.__forward_display__.observe(change,
                                                     self.__forward_observe__)

                if hasattr(self.__forward_display__, "description"):
                    self.__forward_display__.description = self.__forward_coerce__

                change(getattr(self.__forward_display__, "value"))
                IPython.display.display(self.__forward_display__)

        elif self.__forward_coerce__ and self.__forward_coerce__ is not True:
            module, name = _module_and_name(self.__forward_coerce__)
            value = globals.get(self.__forward_coerce__, None)

            if (not isinstance(object, type)) or (not isinstance(
                    value, object)):
                setattr(importlib.import_module(module), name, object(value))

        return object