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()


yay pandas version 0.16.2

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()


missing dependencies: ['notarealmodule']
not running 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')


missing dependencies: ['notarealmodule']
not running OLS_mock

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')


1
2
3
4
5
Out[12]:
<__main__.BayesianHLM at 0x7fe3a32f9e90>

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.