Search code examples
pythonpython-decoratorspylint

How can I tell pylint that a variable will be defined at run time?


Short version: If I define a decorator to import a module at run time and declare it in the func_globals for a method, how can I tell Pylint that the resulting variable has been defined?

Long version: Consider the following example:

from importlib import import_module

def with_import(module):
    modname = module.split('.')[-1]
    def decorate(func):
        def wrapper(*args, **kwargs):
            func.func_globals[modname] = import_module(module)
            return func(*args, **kwargs)
        return wrapper
    return decorate

@with_import('numpy')
def create_array(n):
    return numpy.empty(n)

print(create_array(5))

This code works just fine since the with_import decorator declares numpy for the create_array function. However, when I run PyLint I see

E: 16,11: Undefined variable 'numpy' (undefined-variable)

Is there a way to tell Pylint that this variable will in fact be defined at run time? I don't really want to disable the unused-variable check for the whole module in case someone actually declares a regular unused variable at a later date.


Solution

  • You can disable checks on a block or line basis, for example

    def f():
        # pylint: disable=E0602
        x[0] = 5
        y[0] = 5
    # No errors
    
    def f():
        x[0] = 5 # pylint: disable=E0602
        y[0] = 5
    # Only y will raise the undefined variable error
    

    With decorators you have an equivalent to the first one, I was actually surprised it works, and thinks it's quite ugly but:

    @deco
    # pylint: disable=E0602
    def f():
        x[0] = 5 # No error here
    y[0] = 5 # Error here
    

    Note you'll have a I: Locally disabling undefined-variable (E0602) in the pylint report