code: def extract_constraints(call_node):
      
      def render_args():
        return ', '.join(
          # Dump the Name's id to simplify output when available, falling back to the name of the
          # node's class.
          getattr(a, 'id', type(a).__name__)
          for a in call_node.args)
  
      if len(call_node.args) == 2:
        product_type, subject_constructor = call_node.args
        if not isinstance(product_type, ast.Name) or not isinstance(subject_constructor, ast.Call):
          # TODO(#7114): describe what types of objects are expected in the get call, not just the
          # argument names. After #7114 this will be easier because they will just be types!
          raise ValueError(
            'Two arg form of {} expected (product_type, subject_type(subject)), but '
                          'got: ({})'.format(Get.__name__, render_args()))
        return (product_type.id, subject_constructor.func.id)
      elif len(call_node.args) == 3:
        product_type, subject_declared_type, _ = call_node.args
        if not isinstance(product_type, ast.Name) or not isinstance(subject_declared_type, ast.Name):
          raise ValueError(
            'Three arg form of {} expected (product_type, subject_declared_type, subject), but '
                          'got: ({})'.format(Get.__name__, render_args()))
        return (product_type.id, subject_declared_type.id)
      else:
        raise ValueError('Invalid {}; expected either two or three args, but '
                        'got: ({})'.format(Get.__name__, render_args()))
docs: Parses a `Get(..)` call in one of its two legal forms to return its type constraints.
  
      :param call_node: An `ast.Call` node representing a call to `Get(..)`.
      :return: A tuple of product type id and subject type id.