astroid
astroid copied to clipboard
Regression in 2.5.7 causing false positives in matplotlib
Steps to reproduce
I'm seeing a lot of false positives inside matplotlib with the latest release of astroid
but they all appear to haver a common cause. To reproduce create a file named test.py
and install matplotlib 3.4.2:
from matplotlib import pyplot as plt
ax = plt.Axes(plt.gcf(), [0.0, 0.0, 1.0, 1.0])
ax.set_yticks([0, 1])
It looks like the issue is coming from an advanced use of wrappers to define the set_yticks
methods:
get_yticks = _axis_method_wrapper("yaxis", "get_ticklocs")
set_yticks = _axis_method_wrapper("yaxis", "set_ticks")
https://github.com/matplotlib/matplotlib/blob/v3.4.2/lib/matplotlib/axes/_base.py#L34-L92
Current behavior
With astroid 2.5.7:
$ pylint -E test.py
************* Module test
test.py:3:0: E1102: ax.set_yticks is not callable (not-callable)
Expected behavior
With astroid 2.5.6:
$ pylint -E test.py
Yeah, it appears that matplotlib uses a custom __set_name__
(see https://docs.python.org/3/reference/datamodel.html#creating-the-class-object) to dynamically create these descriptors. There's no explicit support for this in astroid
. As to the behaviour you're seeing, as far as pylint is concerned it's seen these attributes go from Uninferable
to Instance of ._axis_method_wrapper
in 2.5.7. IMO, a custom __set_name__
(or probably any custom behaviour in the type.__new__
chain, e.g. __init_subclass__
, __prepare__
, etc.) should be grounds for marking that node Uninferable
.
@nelfin should we change this issue title to "A custom __set_name__
should mark a node as Uninferable
" ?
@Pierre-Sassoulas, maybe. I'm not 100% sold on the title. I guess I'd ask "how would someone search for this issue in the future" before considering changing the title. If instead your thoughts are "what's a good short description of this change so I can keep track of it in an upcoming milestone", then I guess I see your point.