class_docstr: TFX artifact used for orchestration.
  
  This is used for type-checking and inter-component communication. Currently,
  it wraps a tuple of (ml_metadata.proto.Artifact,
  ml_metadata.proto.ArtifactType) with additional property accessors for
  internal state.
  
  A user may create a subclass of Artifact and override the TYPE_NAME property
  with the type for this artifact subclass. Users of the subclass may then omit
  the "type_name" field when construction the object.
  
  A user may specify artifact type-specific properties for an Artifact subclass
  by overriding the PROPERTIES dictionary, as detailed below.
  
  Note: the behavior of this class is experimental, without backwards
  compatibility guarantees, and may change in upcoming releases.
class_docstr_tok: ["TFX","artifact","used","for","orchestration",".","This","is","used","for","type-checking","and","inter-component","communication",".","Currently",",","it","wraps","a","tuple","of","(","ml_metadata.proto.Artifact",",","ml_metadata.proto.ArtifactType",")","with","additional","property","accessors","for","internal","state",".","A","user","may","create","a","subclass","of","Artifact","and","override","the","TYPE_NAME","property","with","the","type","for","this","artifact","subclass",".","Users","of","the","subclass","may","then","omit","the","``","type_name","''","field","when","construction","the","object",".","A","user","may","specify","artifact","type-specific","properties","for","an","Artifact","subclass","by","overriding","the","PROPERTIES","dictionary",",","as","detailed","below",".","Note",":","the","behavior","of","this","class","is","experimental",",","without","backwards","compatibility","guarantees",",","and","may","change","in","upcoming","releases","."]
code: def _get_artifact_type(cls):
      existing_artifact_type = getattr(cls, "_MLMD_ARTIFACT_TYPE", None)
      if (not existing_artifact_type) or (
          cls.TYPE_NAME != existing_artifact_type.name
      ):
          type_name = cls.TYPE_NAME
          if not (type_name and isinstance(type_name, str)):
              raise ValueError(
                  (
                      "The Artifact subclass %s must override the TYPE_NAME attribute "
                      "with a string type name identifier (got %r instead)."
                  )
                  % (cls, type_name)
              )
          artifact_type = metadata_store_pb2.ArtifactType()
          artifact_type.name = type_name
  
          # Populate ML Metadata artifact properties dictionary.
          if cls.PROPERTIES:
              # Perform validation on PROPERTIES dictionary.
              if not isinstance(cls.PROPERTIES, dict):
                  raise ValueError(
                      "Artifact subclass %s.PROPERTIES is not a dictionary."
                      % cls
                  )
              for key, value in cls.PROPERTIES.items():
                  if not (
                      isinstance(key, (str, bytes))
                      and isinstance(value, Property)
                  ):
                      raise ValueError(
                          (
                              "Artifact subclass %s.PROPERTIES dictionary must have keys of "
                              "type string and values of type artifact.Property."
                          )
                          % cls
                      )
  
              for key, value in cls.PROPERTIES.items():
                  artifact_type.properties[key] = value.mlmd_type()
  
          # Populate ML Metadata artifact type field: `base_type`.
          type_annotation_cls = cls.TYPE_ANNOTATION
          if type_annotation_cls:
              if not issubclass(type_annotation_cls, SystemArtifact):
                  raise ValueError(
                      "TYPE_ANNOTATION %s is not a subclass of SystemArtifact."
                      % type_annotation_cls
                  )
              if type_annotation_cls.MLMD_SYSTEM_BASE_TYPE:
                  artifact_type.base_type = (
                      type_annotation_cls.MLMD_SYSTEM_BASE_TYPE
                  )
  
          cls._MLMD_ARTIFACT_TYPE = artifact_type
      return copy.deepcopy(cls._MLMD_ARTIFACT_TYPE)
  
imports: import builtins
  import copy
  import importlib
  import json
  from typing import Any, Dict, List, Optional, Type, Union
  from absl import logging
  from tfx.types import artifact_property
  from tfx.types.system_artifacts import SystemArtifact
  from tfx.utils import doc_controls
  from tfx.utils import json_utils
  from tfx.utils import proto_utils
  from google.protobuf import struct_pb2
  from google.protobuf import json_format
  from google.protobuf import message
  from ml_metadata.proto import metadata_store_pb2
label_desc: Use image node_id 2 for calling the Artifact obj's underlying member method code with example usage: obj._get_artifact_type(cls) and returns: copy