code: def extract_signature(func, ignore_first=False):
      
      sig_params = get_signature_params(func)
  
      if ignore_first:
          if len(sig_params) == 0:
              raise Exception("Methods must take a 'self' argument, but the "
                              "method '{}' does not have one.".format(
                                  func.__name__))
          sig_params = sig_params[1:]
  
      # Construct the argument default values and other argument information.
      arg_names = []
      arg_defaults = []
      arg_is_positionals = []
      keyword_names = set()
      for arg_name, parameter in sig_params:
          arg_names.append(arg_name)
          arg_defaults.append(parameter.default)
          arg_is_positionals.append(parameter.kind == parameter.VAR_POSITIONAL)
          if parameter.kind == Parameter.POSITIONAL_OR_KEYWORD:
              # Note KEYWORD_ONLY arguments currently unsupported.
              keyword_names.add(arg_name)
  
      return FunctionSignature(arg_names, arg_defaults, arg_is_positionals,
                               keyword_names, func.__name__)
docs: Extract the function signature from the function.
  
      Args:
          func: The function whose signature should be extracted.
          ignore_first: True if the first argument should be ignored. This should
              be used when func is a method of a class.
  
      Returns:
          A function signature object, which includes the names of the keyword
              arguments as well as their default values.