code: def find_method_signature(klass, method: str) -> inspect.Signature:
      """Look through a class' ancestors and fill out the methods signature.
  
      A class method has a signature. But it might now always be complete. When a parameter is not
      annotated, we might want to look through the ancestors and determine the annotation. This is
      very useful when you have a base class that has annotations, and child classes that are not.
  
      Examples
      --------
  
      >>> class Parent:
      ...
      ...     def foo(self, x: int) -> int:
      ...         ...
  
      >>> find_method_signature(Parent, 'foo')
      <Signature (self, x: int) -> int>
  
      >>> class Child(Parent):
      ...
      ...     def foo(self, x, y: float) -> str:
      ...         ...
  
      >>> find_method_signature(Child, 'foo')
      <Signature (self, x: int, y: float) -> str>
  
      """
  
      m = getattr(klass, method)
      sig = inspect.signature(m)
  
      params = []
  
      for param in sig.parameters.values():
          if (
              param.name == "self"
              or param.annotation is not param.empty
          ):
              params.append(param)
              continue
  
          for ancestor in inspect.getmro(klass):
              try:
                  ancestor_meth = inspect.signature(
                      getattr(ancestor, m.__name__)
                  )
              except AttributeError:
                  break
              try:
                  ancestor_param = ancestor_meth.parameters[param.name]
              except KeyError:
                  break
              if ancestor_param.annotation is not param.empty:
                  param = param.replace(
                      annotation=ancestor_param.annotation
                  )
                  break
  
          params.append(param)
  
      return_annotation = sig.return_annotation
      if return_annotation is inspect._empty:
          for ancestor in inspect.getmro(klass):
              try:
                  ancestor_meth = inspect.signature(
                      getattr(ancestor, m.__name__)
                  )
              except AttributeError:
                  break
              if ancestor_meth.return_annotation is not inspect._empty:
                  return_annotation = ancestor_meth.return_annotation
                  break
  
      return sig.replace(
          parameters=params, return_annotation=return_annotation
      )
  
imports: import argparse
  import collections
  import doctest
  import functools
  import importlib
  import inspect
  import os
  import pathlib
  import re
  import shutil
  from numpydoc.docscrape import ClassDoc, FunctionDoc
label_desc: Use image node_id 11 for calling a global function with example usage: find_method_signature(klass, method) and returns: sig