docs: def put_properties(elt, properties, ttl=None, ctx=None):
      """Put properties in elt.
  
      :param elt: properties elt to put. Not None methods.
      :param number ttl: If not None, property time to leave.
      :param ctx: elt ctx from where put properties. Equals elt if None. It
          allows to get function properties related to a class or instance if
          related function is defined in base class.
      :param dict properties: properties to put in elt. elt and ttl are exclude.
  
      :return: Timer if ttl is not None.
      :rtype: Timer
      """
  
      result = None
  
      if properties:
  
          # get the best context
          if ctx is None:
              ctx = find_ctx(elt=elt)
  
          # get elt properties
          elt_properties = _ctx_elt_properties(elt=elt, ctx=ctx, create=True)
  
          # set properties
          elt_properties.update(properties)
  
          if ttl is not None:
              kwargs = {
                  'elt': elt,
                  'ctx': ctx,
                  'keys': tuple(properties.keys())
              }
              result = Timer(ttl, del_properties, kwargs=kwargs)
              result.start()
  
      return result