code: def encode_placeholder_with_channels(
      placeholder: ph.Placeholder,
      channel_to_key_fn: Callable[[channel.BaseChannel], str],
  ) -> placeholder_pb2.PlaceholderExpression:
      """Encodes the placeholder with the given channel keys.
  
      When a ChannelWrappedPlaceholder is initially constructed, it does not have a
      key. This means that Predicates, which comprise of ChannelWrappedPlaceholders,
      do not contain sufficient information to be evaluated at run time. Thus, after
      the Pipeline is fully defined, the compiler will use this method to fill in
      the keys when encoding the placeholder/predicate.
  
      Within the context of each node, each Channel corresponds to a key in the
      input_dict (see `ResolverStrategy.resolve_artifacts`).
      The Placeholder/Predicate has an internal tree data structure to keep track of
      all the placeholders and operations. As we traverse this tree to create this
      proto, `channel_to_key_fn` is called each time a ChannelWrappedPlaceholder is
      encountered, and its output is used as the placeholder key in the Placeholder
      proto produced during encoding.
  
      Note that the ChannelWrappedPlaceholder itself is unchanged after this
      function returns.
  
      Args:
        placeholder: The placeholder to be encoded.
        channel_to_key_fn: The function used to determine the placeholder key for
          each ChannelWrappedPlaceholder. If None, no attempt to fill in the
          placeholder keys will be made.
  
      Returns:
        A PlaceholderExpression proto that represent the given placeholder. Note
        that the given Placeholder remains unchanged.
      """
      for p in placeholder.traverse():
          if isinstance(p, ph.ChannelWrappedPlaceholder):
              p.set_key(channel_to_key_fn(p.channel))
      try:
          return placeholder.encode()
      finally:
          for p in placeholder.traverse():
              if isinstance(p, ph.ChannelWrappedPlaceholder):
                  p.set_key(None)
  
imports: import typing
  from typing import Callable, Dict, Iterable, Iterator, List, Optional, Sequence, Set, Type, cast
  from tfx.dsl.placeholder import placeholder
  from tfx.proto.orchestration import placeholder_pb2
  from tfx.types import artifact
  from tfx.types import channel
label_desc: Use image node_id 9 for calling a global function with example usage: encode_placeholder_with_channels(placeholder, channel_to_key_fn) and returns: placeholder