Repository URL to install this package:
Version:
0.11.1 ▾
|
from statsmodels.tools.sm_exceptions import CacheWriteWarning
from statsmodels.compat.pandas import cache_readonly as PandasCacheReadonly
import warnings
__all__ = ['cache_readonly', 'cache_writable', 'deprecated_alias',
'ResettableCache']
class ResettableCache(dict):
"""DO NOT USE. BACKWARD COMPAT ONLY"""
def __init__(self, *args, **kwargs):
super(ResettableCache, self).__init__(*args, **kwargs)
self.__dict__ = self
def deprecated_alias(old_name, new_name, remove_version=None, msg=None,
warning=FutureWarning):
"""
Deprecate attribute in favor of alternative name.
Parameters
----------
old_name : str
Old, deprecated name
new_name : str
New name
remove_version : str, optional
Version that the alias will be removed
msg : str, optional
Message to show. Default is
`old_name` is a deprecated alias for `new_name`
warning : Warning, optional
Warning class to give. Default is FutureWarning.
Notes
-----
Older or less-used classes may not conform to statsmodels naming
conventions. `deprecated_alias` lets us bring them into conformance
without breaking backward-compatibility.
Example
-------
Instances of the `Foo` class have a `nvars` attribute, but it _should_
be called `neqs`:
class Foo(object):
nvars = deprecated_alias('nvars', 'neqs')
def __init__(self, neqs):
self.neqs = neqs
>>> foo = Foo(3)
>>> foo.nvars
__main__:1: FutureWarning: nvars is a deprecated alias for neqs
3
"""
if msg is None:
msg = '%s is a deprecated alias for %s' % (old_name, new_name)
if remove_version is not None:
msg += ', will be removed in version %s' % remove_version
def fget(self):
warnings.warn(msg, warning, stacklevel=2)
return getattr(self, new_name)
def fset(self, value):
warnings.warn(msg, warning, stacklevel=2)
setattr(self, new_name, value)
res = property(fget=fget, fset=fset)
return res
class CachedAttribute(object):
def __init__(self, func, cachename=None):
self.fget = func
self.name = func.__name__
self.cachename = cachename or '_cache'
def __get__(self, obj, type=None):
if obj is None:
return self.fget
# Get the cache or set a default one if needed
_cachename = self.cachename
_cache = getattr(obj, _cachename, None)
if _cache is None:
setattr(obj, _cachename, {})
_cache = getattr(obj, _cachename)
# Get the name of the attribute to set and cache
name = self.name
_cachedval = _cache.get(name, None)
if _cachedval is None:
_cachedval = self.fget(obj)
_cache[name] = _cachedval
return _cachedval
def __set__(self, obj, value):
errmsg = "The attribute '%s' cannot be overwritten" % self.name
warnings.warn(errmsg, CacheWriteWarning)
class CachedWritableAttribute(CachedAttribute):
def __set__(self, obj, value):
_cache = getattr(obj, self.cachename)
name = self.name
_cache[name] = value
class _cache_readonly(property):
"""
Decorator for CachedAttribute
"""
def __init__(self, cachename=None):
self.func = None
self.cachename = cachename
def __call__(self, func):
return CachedAttribute(func,
cachename=self.cachename)
class cache_writable(_cache_readonly):
"""
Decorator for CachedWritableAttribute
"""
def __call__(self, func):
return CachedWritableAttribute(func,
cachename=self.cachename)
# Use pandas since it works with docs correctly
cache_readonly = PandasCacheReadonly
# cached_value and cached_data behave identically to cache_readonly, but
# are used by `remove_data` to
# a) identify array-like attributes to remove (cached_data)
# b) make sure certain values are evaluated before caching (cached_value)
# TODO: Disabled since the subclasses break doc strings
# class cached_data(PandasCacheReadonly):
# pass
cached_data = PandasCacheReadonly
# class cached_value(PandasCacheReadonly):
# pass
cached_value = PandasCacheReadonly
def nottest(fn):
fn.__test__ = False
return fn