Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 460
Duncan Macleod Avatar asked Oct 27 '25 04:10

Duncan Macleod


2 Answers

pylint pays attention to typing.TYPE_CHECKING. So you can do:

import typing
if typing.TYPE_CHECKING:
    import numpy

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

typing.TYPE_CHECKING is always false at runtime, so the import doesn't get run. However, pylint assumes typing.TYPE_CHECKING to be true and will analyse the code as if the import had been performed.

like image 79
Jack Avatar answered Oct 29 '25 19:10

Jack


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

like image 22
polku Avatar answered Oct 29 '25 18:10

polku



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!