docs: def memoize(ttl=None):
      """ Cache the result of the function call with given args for until
          ttl (datetime.timedelta) expires.
      """
      def decorator(obj):
          cache = obj.cache = {}
  
          @functools.wraps(obj)
          def memoizer(*args, **kwargs):
              now = datetime.now()
              key = str(args) + str(kwargs)
              if key not in cache:
                  cache[key] = (obj(*args, **kwargs), now)
              value, last_update = cache[key]
              if ttl and (now - last_update) > ttl:
                  cache[key] = (obj(*args, **kwargs), now)
              return cache[key][0]
          return memoizer
      return decorator