code: def __post_init__(self):
      if (
          self.sender
          and self.sender_socket
          and self.receiver
          and self.receiver_socket
      ):
          # If we're trying to connect the same sockets again, this should be a no-op
          if (
              self.receiver in self.sender_socket.receivers
              and self.sender in self.receiver_socket.senders
          ):
              return
  
          # Make sure the receiving socket isn't already connected, unless it's variadic. Sending sockets can be
          # connected as many times as needed, so they don't need this check
          if (
              self.receiver_socket.senders
              and not self.receiver_socket.is_variadic
          ):
              raise PipelineConnectError(
                  f"Cannot connect '{self.sender}.{self.sender_socket.name}' with '{self.receiver}.{self.receiver_socket.name}': "
                  f"{self.receiver}.{self.receiver_socket.name} is already connected to {self.receiver_socket.senders}.\n"
              )
  
          self.sender_socket.receivers.append(self.receiver)
          self.receiver_socket.senders.append(self.sender)
  
file_path: haystack/haystack/core/component/connection.py
imports: import itertools
  from typing import Optional, List, Tuple
  from dataclasses import dataclass
  from haystack.core.component.sockets import InputSocket, OutputSocket
  from haystack.core.type_utils import _type_name, _types_are_compatible
  from haystack.core.errors import PipelineConnectError
label_desc: Use image node_id 1 for calling the Connection obj's underlying member method code with example usage: obj.__post_init__() without return types