docs: def getsourcefallback(cls):
      """ Fallback for getting the source of interactively defined classes (typically in ipython)
  
      This is basically just a patched version of the inspect module, in which
      we get the code by calling inspect.findsource on an *instancemethod* of
      a class for which inspect.findsource fails.
      """
      for attr in cls.__dict__:
          if inspect.ismethod(getattr(cls, attr)):
              imethod = getattr(cls, attr)
              break
      else:
          raise AttributeError(
              "Cannot get this class' source; it does not appear to have any methods")
  
      ### This part is derived from inspect.findsource ###
      module = inspect.getmodule(cls)
      file = inspect.getfile(imethod)
      lines = linecache.getlines(file, module.__dict__)
      name = cls.__name__
      pat = re.compile(r'^(\s*)class\s*'+name+r'\b')
  
      # AMVMOD: find the encoding (necessary for python 2 only)
      #if PY2:
      #    with open(file, 'rb') as infile:
      #        encoding = detect_encoding(infile.readline)[0]
  
      # make some effort to find the best matching class definition:
      # use the one with the least indentation, which is the one
      # that's most probably not inside a function definition.
      candidates = []
      toplevel = False
      for i in range(len(lines)):
          match = pat.match(lines[i])
          if match:
              # if it's at toplevel, it's already the best one
              if lines[i][0] == 'c':
                  flines, flnum = lines, i
                  toplevel = True
                  break
              # else add whitespace to candidate list
              candidates.append((match.group(1), i))
      if candidates and not toplevel:
          # this will sort by whitespace, and by line number,
          # less whitespace first
          candidates.sort()
          flines, flnum = lines, candidates[0][1]
      elif not candidates and not toplevel:
          raise IOError('could not find class definition')
      ### end modified inspect.findsource ###
  
      # this is what inspect.getsourcelines does
      glines = inspect.getblock(flines[flnum:])
  
      # And this is what inspect.getsource does
      if False: #if PY2:
          return ("".join(glines)).decode(encoding)
      else:
          return "".join(glines)