This details how the requires decorator can be used.
In [1]:
from opt import requires
The function takes an arbitrary number of strings that describe the dependencies introduced by the class or function.
In [2]:
@requires('pandas')
def test():
import pandas
print('yay pandas version {}'.format(pandas.__version__))
In [3]:
test()
So, neat. What if we didn't have the module needed?
In [4]:
@requires("notarealmodule")
def test2():
print("you shouldn't see this")
In [5]:
test2()
So, if the requirements aren't met, your original function is replaced with a new function.
it looks kind of like this:
In [6]:
def passer():
if verbose:
missing = [arg for i,arg in enumerate(args) if not available[i]]
print("missing dependencies: {d}".format(d=missing))
print("not running {}".format(function.__name__))
else:
pass
By deafult, the function is replaced with a verbose version. If you pass verbose=False, then the function gets replaced with a nonprinting version.
In [7]:
@requires("notarealmodule", verbose=False)
def test3():
print("you shouldn't see this, either")
In [8]:
test3()
The cool thing is, this works on class definitions as well:
In [9]:
@requires("notarealmodule")
class OLS_mock(object):
def __init__(self, *args, **kwargs):
for arg in args:
print(arg)
In [10]:
OLS_mock(1,2,3,4,5, w='Tom')
In [11]:
@requires("pymc3")
class BayesianHLM(object):
def __init__(self, *args, **kwargs):
print(arg)for arg in args[0:]:
In [12]:
BayesianHLM(1,2,3,4,5, w='Tom')
Out[12]:
I think this could make more sense for spreg dependencies, where the extra stuff might be reasonable at a function or class level, rather than at the module level.
In addition, it could be useful for any plans for a viz setup, where maybe a projected map would require cartopy, but an unprojected map could just use matplotlib. This would let us do this function-by-function and print or raise reasonable fail states.