reconnect moved files to git repo
This commit is contained in:
@ -0,0 +1,98 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Author: Taylor Smith <taylor.smith@alkaline-ml.com>
|
||||
#
|
||||
# Metaestimators for the ARIMA class. These classes are derived from the
|
||||
# sklearn metaestimators, but adapted for more specific use with pmdarima.
|
||||
|
||||
from operator import attrgetter
|
||||
from functools import update_wrapper
|
||||
|
||||
__all__ = [
|
||||
'if_has_delegate'
|
||||
]
|
||||
|
||||
|
||||
class _IffHasDelegate(object):
|
||||
"""Implements a conditional property using the descriptor protocol.
|
||||
Using this class to create a decorator will raise an ``AttributeError``
|
||||
if none of the delegates (specified in ``delegate_names``) is an attribute
|
||||
of the base object or the first found delegate does not have an attribute
|
||||
``attribute_name``.
|
||||
|
||||
This allows ducktyping of the decorated method based on
|
||||
``delegate.attribute_name``. Here ``delegate`` is the first item in
|
||||
``delegate_names`` for which ``hasattr(object, delegate) is True``.
|
||||
|
||||
See https://docs.python.org/3/howto/descriptor.html for an explanation of
|
||||
descriptors.
|
||||
"""
|
||||
def __init__(self, fn, delegate_names):
|
||||
self.fn = fn
|
||||
self.delegate_names = delegate_names
|
||||
|
||||
# update the docstring of the descriptor
|
||||
update_wrapper(self, fn)
|
||||
|
||||
def __get__(self, obj, type=None):
|
||||
# raise an AttributeError if the attribute is not present on the object
|
||||
if obj is not None:
|
||||
# delegate only on instances, not the classes.
|
||||
# this is to allow access to the docstrings.
|
||||
for delegate_name in self.delegate_names:
|
||||
try:
|
||||
attrgetter(delegate_name)(obj)
|
||||
except AttributeError:
|
||||
continue
|
||||
else:
|
||||
break
|
||||
else:
|
||||
attrgetter(self.delegate_names[-1])(obj)
|
||||
|
||||
# lambda, but not partial, allows help() to work with update_wrapper
|
||||
out = (lambda *args, **kwargs: self.fn(obj, *args, **kwargs))
|
||||
# update the docstring of the returned function
|
||||
update_wrapper(out, self.fn)
|
||||
return out
|
||||
|
||||
|
||||
def if_has_delegate(delegate):
|
||||
"""Wrap a delegated instance attribute function.
|
||||
|
||||
Creates a decorator for methods that are delegated in the presence of a
|
||||
results wrapper. This enables duck-typing by ``hasattr`` returning True
|
||||
according to the sub-estimator.
|
||||
|
||||
This function was adapted from scikit-learn, which defines
|
||||
``if_delegate_has_method``, but operates differently by injecting methods
|
||||
not based on method presence, but by delegate presence.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from pmdarima.utils.metaestimators import if_has_delegate
|
||||
>>>
|
||||
>>> class A(object):
|
||||
... @if_has_delegate('d')
|
||||
... def func(self):
|
||||
... return True
|
||||
>>>
|
||||
>>> a = A()
|
||||
>>> # the delegate does not exist yet
|
||||
>>> assert not hasattr(a, 'func')
|
||||
>>> # inject the attribute
|
||||
>>> a.d = None
|
||||
>>> assert hasattr(a, 'func') and a.func()
|
||||
|
||||
Parameters
|
||||
----------
|
||||
delegate : string, list of strings or tuple of strings
|
||||
Name of the sub-estimator that can be accessed as an attribute of the
|
||||
base object. If a list or a tuple of names are provided, the first
|
||||
sub-estimator that is an attribute of the base object will be used.
|
||||
"""
|
||||
if isinstance(delegate, list):
|
||||
delegate = tuple(delegate)
|
||||
if not isinstance(delegate, tuple):
|
||||
delegate = (delegate,)
|
||||
|
||||
return lambda fn: _IffHasDelegate(fn, delegate)
|
||||
Reference in New Issue
Block a user