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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With