# Path: infi/pyutils/decorators.py
# def wraps(wrapped):
#     """ a convenience function on top of functools.wraps:
# 
#     - adds the original function to the wrapped function as __wrapped__ attribute."""
#     def new_decorator(f):
#         returned = functools.wraps(wrapped)(f)
#         returned.__wrapped__ = wrapped
#         return returned
#     return new_decorator
# 
# Path: infi/pyutils/python_compat.py
# _PYTHON_VERSION = platform.python_version()
# _IS_PYTHON_3 = _PYTHON_VERSION >= '3'
# _IS_BELOW_PYTHON_2_7 = _PYTHON_VERSION < '2.7'
# def get_underlying_function(f):
# def _get_underlying_classmethod_function(f):
#     def create_bound_method(func, self):
#     class TemporaryClass(object):


import itertools
import time
from .decorators import wraps
from .python_compat import iteritems
from logging import getLogger
from types import MethodType, FunctionType
    from inspect import getmembers
    else:
        return
    _ = getattr(self, '_cache', {}).pop(key, None)

def populate_cache(self, attributes_to_skip=[]):
    """this method attempts to get all the lazy cached properties and methods
    There are two special cases:

    - Some attributes may not be available and raises exceptions.
      If you wish to skip these, pass them in the attributes_to_skip list
    - The calling of cached methods is done without any arguments, and catches TypeError exceptions
      for the case a cached method requires arguments. The exception is logged."""
    for key, value in getmembers(self):
        if key in attributes_to_skip:
            continue
        if hasattr(value, "__cached_method__"):
            logger.debug("getting attribute %s from %s", repr(key), repr(self))
            try:
                _ = value()
            except TypeError as e:
                logger.exception(e)

class LazyImmutableDict(object):
    """ Use this object when you have a list of keys but fetching the values is expensive,
    and you want to do it in a lazy fasion"""
    def __init__(self, dict):
        self._dict = dict

    def __getitem__(self, key):
        value = self._dict[key]

# Path: infi/pyutils/decorators.py
# def wraps(wrapped):
#     """ a convenience function on top of functools.wraps:
# 
#     - adds the original function to the wrapped function as __wrapped__ attribute."""
#     def new_decorator(f):
#         returned = functools.wraps(wrapped)(f)
#         returned.__wrapped__ = wrapped
#         return returned
#     return new_decorator
# 
# Path: infi/pyutils/python_compat.py
# _PYTHON_VERSION = platform.python_version()
# _IS_PYTHON_3 = _PYTHON_VERSION >= '3'
# _IS_BELOW_PYTHON_2_7 = _PYTHON_VERSION < '2.7'
# def get_underlying_function(f):
# def _get_underlying_classmethod_function(f):
#     def create_bound_method(func, self):
#     class TemporaryClass(object):


# Path: infi/pyutils/lazy.py
import itertools
import time
from .decorators import wraps
from .python_compat import iteritems
from logging import getLogger
from types import MethodType, FunctionType
    from inspect import getmembers

    else:
        return
    _ = getattr(self, '_cache', {}).pop(key, None)

def populate_cache(self, attributes_to_skip=[]):
    """this method attempts to get all the lazy cached properties and methods
    There are two special cases:

    - Some attributes may not be available and raises exceptions.
      If you wish to skip these, pass them in the attributes_to_skip list
    - The calling of cached methods is done without any arguments, and catches TypeError exceptions
      for the case a cached method requires arguments. The exception is logged."""
    for key, value in getmembers(self):
        if key in attributes_to_skip:
            continue
        if hasattr(value, "__cached_method__"):
            logger.debug("getting attribute %s from %s", repr(key), repr(self))
            try:
                _ = value()
            except TypeError as e:
                logger.exception(e)

class LazyImmutableDict(object):
    """ Use this object when you have a list of keys but fetching the values is expensive,
    and you want to do it in a lazy fasion"""
    def __init__(self, dict):
        self._dict = dict

    def __getitem__(self, key):
        value = self._dict[key]

        if value is None: