def producer(*, name = None, metric = call_default):
    """Decorator to measure a function that produces many items.

    The function should return an object that supports ``__len__`` (ie, a
    list). If the function returns an iterator, use :func:`all` instead.

    :arg function metric: f(name, count, total_time)
    :arg str name: name for the metric
    """

    def wrapper(func):
        def instrumenter(name_, *args, **kwargs):
            t = time.time()
            try:
                ret = func(*args, **kwargs)
            except Exception:
                # record a metric for other exceptions, than raise
                metric(name_, 0, time.time() - t)
                raise
            else:
                # normal path, record metric & return
                metric(name_, len(ret), time.time() - t)
                return ret

        name_ = name if name is not None else func.__module__ + '.' +func.__name__
        class instrument_decorator(object): # must be a class for descriptor magic to work
            @wraps(func)
            def __call__(self, *args, **kwargs):
                return instrumenter(name_, *args, **kwargs)

            def __get__(self, instance, class_):
                name_ = name if name is not None else\
                    ".".join((class_.__module__, class_.__name__, func.__name__))
                @wraps(func)
                def wrapped_method(*args, **kwargs):
                    return instrumenter(name_, instance, *args, **kwargs)
                return wrapped_method

        return instrument_decorator()
    return wrapper
def producer ( * , name = None , metric = call_default ) : def wrapper ( func ) : def instrumenter ( name_ , * args , ** kwargs ) : t = time . time ( ) try : ret = func ( * args , ** kwargs ) except Exception : metric ( name_ , 0 , time . time ( ) - t ) raise else : metric ( name_ , len ( ret ) , time . time ( ) - t ) return ret name_ = name if name is not None else func . __module__ + '.' + func . __name__ class instrument_decorator ( object ) : @ wraps ( func ) def __call__ ( self , * args , ** kwargs ) : return instrumenter ( name_ , * args , ** kwargs ) def __get__ ( self , instance , class_ ) : name_ = name if name is not None else "." . join ( ( class_ . __module__ , class_ . __name__ , func . __name__ ) ) @ wraps ( func ) def wrapped_method ( * args , ** kwargs ) : return instrumenter ( name_ , instance , * args , ** kwargs ) return wrapped_method return instrument_decorator ( ) return wrapper
Decorator to measure a function that produces many items.

    The function should return an object that supports ``__len__`` (ie, a
    list). If the function returns an iterator, use :func:`all` instead.

    :arg function metric: f(name, count, total_time)
    :arg str name: name for the metric