class_docstr: Metaclass for ResolverOp.
  
  Features:
  1. ResolverOp cannot be instantiated directly. Calling ResolverOp() returns
     OpNode instance which is used for function tracing. Instead _ResolverOpMeta
     exposes create() classmethod to actually create a ResolverOp isntance.
  2. _ResolverOpMeta is aware of Property, and keyword argument values
     given from the ResolverOp invocation is validated without creating a
     ResolverOp instance.
  3. It inherits ABCMeta, so @abstractmethod works.
class_docstr_tok: ["Metaclass","for","ResolverOp",".","Features",":","1",".","ResolverOp","can","not","be","instantiated","directly",".","Calling","ResolverOp","(",")","returns","OpNode","instance","which","is","used","for","function","tracing",".","Instead","_ResolverOpMeta","exposes","create","(",")","classmethod","to","actually","create","a","ResolverOp","isntance",".","2",".","_ResolverOpMeta","is","aware","of","Property",",","and","keyword","argument","values","given","from","the","ResolverOp","invocation","is","validated","without","creating","a","ResolverOp","instance",".","3",".","It","inherits","ABCMeta",",","so","@","abstractmethod","works","."]
code: def __init__(
      cls,
      name,
      bases,
      attrs,
      *,
      canonical_name: Optional[str] = None,
      arg_data_types: Sequence[DataType] = (
          DataType.ARTIFACT_MULTIMAP,
      ),
      return_data_type: DataType = DataType.ARTIFACT_MULTIMAP,
  ):
      cls._props_by_name = {
          prop.name: prop
          for prop in attrs.values()
          if isinstance(prop, Property)
      }
      cls._canonical_name = canonical_name
      if not typing_utils.is_compatible(
          arg_data_types, Sequence[_ValidDataType]
      ):
          raise ValueError(
              f"Invalid arg_data_types = {arg_data_types}. "
              "Expected Sequence[DataType]."
          )
      cls._arg_data_types = arg_data_types
      if not typing_utils.is_compatible(
          return_data_type, _ValidDataType
      ):
          raise ValueError(
              f"Invalid return_data_type = {return_data_type}. Expected DataType."
          )
      cls._return_data_type = return_data_type
      super().__init__(name, bases, attrs)
  
imports: from __future__ import annotations
  import abc
  from typing import Any, Generic, Literal, Mapping, Optional, Sequence, Set, Type, TypeVar, Union
  import attr
  from tfx import types
  from tfx.proto.orchestration import pipeline_pb2
  from tfx.utils import json_utils
  from tfx.utils import typing_utils
  import ml_metadata
label_desc: Use image node_id 2 to create a new _ResolverOpMeta object from inherited base classes: abc with example: obj = _ResolverOpMeta(cls, name, bases, attrs)