code: def _assert_artifact_map_equals(
      self,
      expected: Dict[str, _TArtifactList],
      actual: Dict[str, _TArtifactList],
  ) -> None:
      self.assertSameElements(expected.keys(), actual.keys())
      for key in expected.keys():
          e, a = (
              v.artifacts
              if isinstance(
                  v, execution_result_pb2.ExecutorOutput.ArtifactList
              )
              else v
              for v in [expected[key], actual[key]]
          )
          self.assertProtoEquals(
              list(map(self._convert_to_artifact_proto, e)),
              list(map(self._convert_to_artifact_proto, a)),
          )
  
imports: from typing import Dict, List, Union
  import tensorflow
  from tfx.orchestration.portable import data_types
  from tfx.orchestration.python_execution_binary import python_execution_binary_utils
  from tfx.proto.orchestration import executable_spec_pb2
  from tfx.proto.orchestration import execution_result_pb2
  from tfx.proto.orchestration import pipeline_pb2
  from tfx.types import artifact
  from tfx.types import channel
  from google.protobuf import text_format
  from ml_metadata.proto import metadata_store_pb2
label_desc: Use image node_id 2 for calling the PythonExecutorBinaryUtilsTest obj's underlying member method code with example usage: obj._assert_artifact_map_equals(expected, actual) without return types