How do I make a dummy do-nothing @jit decorator?

Question:

I want numba to be an optional dependency, so that it’s fast if installed or slow if not. So when numba is not installed, I want @njit to be a dummy decorator that does nothing.

If I follow these directions and use:

def njit(func):
    return func

Then when the decorator is called like @njit(cache=True, nogil=True) I get errors about:

TypeError: njit() got an unexpected keyword argument 'cache'

If I try to catch the args and ignore them using

    def njit(func, *args, **kwargs):
        return func

then I get:

missing 1 required positional argument: 'func'

How do I just make a dummy decorator that does nothing and ignores kwargs?

Asked By: endolith

||

Answers:

Think of decorators with arguments as decorator factory, they return a decorator. This way

def decorator(func):
    return func

The above is a decorator, now with arguments

def decorator_factory(a,b,c):
    def decorator(func):
        return func
    return decorator

The inner decorator has access to the a,b,c arguments because it is a closure. I hope that helps


So it can be defined as:

def njit(cache, nogil):
    def decorator(func):
        return func 
    return decorator
Answered By: geckos

If you want to save some time and be able to do the same with all numba decorators, try numbasub. It provides exactly what you are asking for, and you can apply it to any project you want.

Answered By: Giorgio Balestrieri

Expanding on geckos’ answer, we can adapt it to be compatible with @njit as well.

The code for jit can be found in https://github.com/numba/numba/blob/main/numba/core/decorators.py

What we need to do is to make jit act as a factory decorator when used as @jit() and as a simple decorator when used as @jit.

def njit(f=None, *args, **kwargs):
    def decorator(func):
        return func 

    if callable(f):
        return f
    else:
        return decorator

This should work in both cases.

Answered By: jinawee