def __cacheit(maxsize):
        """caching decorator.

           important: the result of cached function must be *immutable*


           Examples
           ========

           >>> from sympy.core.cache import cacheit
           >>> @cacheit
           ... def f(a, b):
           ...    return a+b

           >>> @cacheit
           ... def f(a, b):
           ...    return [a, b] # <-- WRONG, returns mutable object

           to force cacheit to check returned results mutability and consistency,
           set environment variable SYMPY_USE_CACHE to 'debug'
        """
        def func_wrapper(func):
            cfunc = lru_cache(maxsize, typed=True)(func)

            # wraps here does not propagate all the necessary info
            # for py2.7, use update_wrapper below
            def wrapper(*args, **kwargs):
                try:
                    retval = cfunc(*args, **kwargs)
                except __HOLE__:
                    retval = func(*args, **kwargs)
                return retval

            wrapper.cache_info = cfunc.cache_info
            wrapper.cache_clear = cfunc.cache_clear

            # Some versions of update_wrapper erroneously assign the final
            # function of the wrapper chain to __wrapped__, see
            # https://bugs.python.org/issue17482 .
            # To work around this, we need to call update_wrapper first, then
            # assign to wrapper.__wrapped__.
            update_wrapper(wrapper, func)
            wrapper.__wrapped__ = cfunc.__wrapped__

            CACHE.append(wrapper)
            return wrapper

        return func_wrapper
dataset/ETHPy150Open sympy/sympy/sympy/core/cache.py/__cacheit