code: def log_methods_calls(fname, some_class, prefix=None):
      
      # test if file is writable
      open(fname, 'a').close()
      FILENAME = fname
      CLASS = some_class
  
      PREFIX = "--[ %(asked)s / %(called)s / %(defined)s ]--"
      if prefix != None:
          PREFIX = prefix
      MAXWIDTH = {'o_O': 10}  # hack with editable closure dict, to align names
                 
      def format_prefix(method, methodobj):
          """
          --[ ShellBase / Internal / BaseEdit ]------- get_position
          """
          classnames = {
              'asked': CLASS.__name__,
              'called': methodobj.__class__.__name__,
              'defined': get_class_that_defined(method)
          }
          line = PREFIX % classnames
          MAXWIDTH['o_O'] = max(len(line), MAXWIDTH['o_O'])
          return line.ljust(MAXWIDTH['o_O'], '-')
         
      import types
      def __getattribute__(self, name):
          attr = object.__getattribute__(self, name)
          if type(attr) is not types.MethodType:
              return attr
          else:
              def newfunc(*args, **kwargs):
                  log = open(FILENAME, 'a')
                  prefix = format_prefix(attr, self)
                  log.write('%s %s\n' % (prefix, name))
                  log.close()
                  result = attr(*args, **kwargs)
                  return result
              return newfunc
   
      some_class.__getattribute__ = __getattribute__
docs: Hack `some_class` to log all method calls into `fname` file.
      If `prefix` format is not set, each log entry is prefixed with:
        --[ asked / called / defined ] --
          asked   - name of `some_class`
          called  - name of class for which a method is called
          defined - name of class where method is defined
      
      Must be used carefully, because it monkeypatches __getattribute__ call.
      
      Example:  log_methods_calls('log.log', ShellBaseWidget)