docs: def proxify_elt(elt, bases=None, _dict=None, public=False):
      """Proxify input elt.
  
      :param elt: elt to proxify.
      :param bases: elt class base classes. If None, use elt type.
      :param dict _dict: specific elt class content to use.
      :param bool public: if True (default False), proxify only public members
          (where name starts with the character '_').
      :return: proxified element.
      :raises: TypeError if elt does not implement all routines of bases and
          _dict.
      """
  
      # ensure _dict is a dictionary
      proxy_dict = {} if _dict is None else _dict.copy()
      # set of proxified attribute names which are proxified during bases parsing
      # and avoid to proxify them twice during _dict parsing
      proxified_attribute_names = set()
      # ensure bases is a tuple of types
      if bases is None:
          bases = (elt if isclass(elt) else elt.__class__,)
  
      if isinstance(bases, string_types):
          bases = (lookup(bases),)
  
      elif isclass(bases):
          bases = (bases,)
  
      else:
          bases = tuple(bases)
  
      # fill proxy_dict with routines of bases
      for base in bases:
          # exclude object
          if base is object:
              continue
          for name, member in getmembers(base, isroutine):
              # check if name is public
              if public and not name.startswith('_'):
                  continue
              eltmember = getattr(elt, name, None)
              if eltmember is None:
                  raise TypeError(
                      'Wrong elt {0}. Must implement {1} ({2}) of {3}.'.
                      format(elt, name, member, base)
                  )
              # proxify member if member is not a constructor
              if name not in ['__new__', '__init__']:
                  # get routine from proxy_dict or eltmember
                  routine = proxy_dict.get(name, eltmember)
                  # exclude object methods
                  if getattr(routine, '__objclass__', None) is not object:
                      # get routine proxy
                      routine_proxy = proxify_routine(routine)
                      if ismethod(routine_proxy):
                          routine_proxy = get_method_function(routine_proxy)
                      # update proxy_dict
                      proxy_dict[name] = routine_proxy
                      # and save the proxified attribute flag
                      proxified_attribute_names.add(name)
  
      # proxify proxy_dict
      for name in proxy_dict:
          value = proxy_dict[name]
          if not hasattr(elt, name):
              raise TypeError(
                  'Wrong elt {0}. Must implement {1} ({2}).'.format(
                      elt, name, value
                  )
              )
          if isroutine(value):
              # if member has not already been proxified
              if name not in proxified_attribute_names:
                  # proxify it
                  value = proxify_routine(value)
              proxy_dict[name] = value
  
      # set default constructors if not present in proxy_dict
      if '__new__' not in proxy_dict:
          proxy_dict['__new__'] = object.__new__
  
      if '__init__' not in proxy_dict:
          proxy_dict['__init__'] = object.__init__
  
      # generate a new proxy class
      cls = type('Proxy', bases, proxy_dict)
      # instantiate proxy cls
      result = cls if isclass(elt) else cls()
      # bind elt to proxy
      setattr(result, __PROXIFIED__, elt)
  
      return result