code: def is_compatible(value: Any, tp: Type[_T]) -> TypeGuard[_T]:
      """Whether the value is compatible with the type.
  
      Similar to builtin.isinstance(), but accepts more advanced subscripted type
      hints.
  
      Args:
        value: The value under test.
        tp: The type to check acceptability.
  
      Returns:
        Whether the `value` is compatible with the type `tp`.
      """
      maybe_origin = typing.get_origin(tp)
      maybe_args = typing.get_args(tp)
      if tp is Any:
          return True
      if tp in (None, type(None)):
          return value is None
      if isinstance(tp, enum_type_wrapper.EnumTypeWrapper):
          return value in tp.values()
      if inspect.isclass(tp):
          if not maybe_args:
              if issubclass(tp, dict) and hasattr(
                  tp, "__annotations__"
              ):
                  return _is_typed_dict_compatible(value, tp)
              return isinstance(value, tp)
      if maybe_origin is not None:
          # Union[T, U] or T | U
          if maybe_origin in _UNION_ORIGINS:
              assert maybe_args, f"{tp} should be subscripted."
              return any(
                  is_compatible(value, arg) for arg in maybe_args
              )
          # Type[T]
          elif maybe_origin is type:
              if not maybe_args:
                  return inspect.isclass(value)
              assert len(maybe_args) == 1
              subtype = maybe_args[0]
              if subtype is Any:
                  return inspect.isclass(value)
              elif typing.get_origin(subtype) is typing.Union:
                  # Convert Type[Union[x, y, ...]] to Union[Type[x], Type[y], ...].
                  subtypes = [
                      typing.Type[a] for a in typing.get_args(subtype)
                  ]
                  return any(is_compatible(value, t) for t in subtypes)
              elif inspect.isclass(subtype):
                  return inspect.isclass(value) and issubclass(
                      value, subtype
                  )
          # List[T], Set[T], FrozenSet[T], Iterable[T], Sequence[T], MutableSeuence[T]
          elif maybe_origin in (
              list,
              set,
              frozenset,
              collections.abc.Iterable,
              collections.abc.Sequence,
              collections.abc.MutableSequence,
              collections.abc.Collection,
              collections.abc.Container,
          ):
              if not isinstance(value, maybe_origin):
                  return False
              if not maybe_args:
                  return True
              assert len(maybe_args) == 1
              if maybe_args[0] is str and isinstance(value, str):
                  # `str` is technically Iterable[str], etc., but it's mostly not intended
                  # for type checking and fail to catch a bug. Therefore we don't regard
                  # str as Iterable[str], etc. This is also consistent with pytype
                  # behavior:
                  # https://github.com/google/pytype/blob/main/docs/faq.md#why-doesnt-str-match-against-string-iterables
                  return False
              return all(is_compatible(v, maybe_args[0]) for v in value)
          # Tuple[T]
          elif maybe_origin is tuple:
              if not isinstance(value, tuple):
                  return False
              if not maybe_args:
                  return True
              if len(maybe_args) == 2 and maybe_args[-1] is Ellipsis:
                  return all(
                      is_compatible(v, maybe_args[0]) for v in value
                  )
              return len(maybe_args) == len(value) and all(
                  is_compatible(v, arg)
                  for v, arg in zip(value, maybe_args)
              )
          # Dict[K, V], Mapping[K, V], MutableMapping[K, V]
          elif maybe_origin in (
              dict,
              collections.abc.Mapping,
              collections.abc.MutableMapping,
          ):
              if not isinstance(value, maybe_origin):
                  return False
              if not maybe_args:  # Unsubscripted Dict.
                  return True
              assert len(maybe_args) == 2
              kt, vt = maybe_args
              return all(
                  is_compatible(k, kt) and is_compatible(v, vt)
                  for k, v in value.items()
              )
          # Literal[T]
          elif maybe_origin is Literal:
              assert maybe_args
              return value in maybe_args
          elif maybe_origin is Annotated:
              assert maybe_args
              return is_compatible(value, maybe_args[0])
          # Required[T] and NotRequired[T]
          elif maybe_origin in (Required, NotRequired):
              assert len(maybe_args) == 1
              return is_compatible(value, maybe_args[0])
          else:
              raise NotImplementedError(
                  f"Type {tp} with unsupported origin type {maybe_origin}."
              )
      raise NotImplementedError(f"Unsupported type {tp}.")
  
file_path: tfx/tfx/utils/pure_typing_utils.py
imports: import collections.abc
  import inspect
  import sys
  import types
  import typing
  from typing import Any, Iterable, Literal, Mapping, Type, TypeVar, TypedDict
  from typing_extensions import Annotated, NotRequired, Required, TypeGuard
  from google.protobuf.internal import enum_type_wrapper
label_desc: Use image node_id 4 for calling a global function with example usage: is_compatible(value, tp) and returns: True, unknown, unknown, isinstance, any, _is_typed_dict_compatible, inspect, inspect, all, any, False, True, False, unknown, unknown, False, True, all, all, False, True, unknown, is_compatible, is_compatible