I've been using pylint for a long time, it's always helpful. Recently I've started annotating types in my python 3.5 code (to see what https://github.com/JukkaL/mypy can do, but this is unrelated), and for the first time I stumbled across an issue with pylint.
sample output from pylint:
.../experiments$ pylint -r n my_metaclass.py
No config file found, using default configuration
************* Module my_metaclass
E:104,25: Value 'typing.Sequence' is unsubscriptable (unsubscriptable-object)
E:104,47: Value 'typing.Sequence' is unsubscriptable (unsubscriptable-object)
E:105, 8: Value 'typing.Sequence' is unsubscriptable (unsubscriptable-object)
E:109,25: Value 'typing.Sequence' is unsubscriptable (unsubscriptable-object)
E:109,47: Value 'typing.Sequence' is unsubscriptable (unsubscriptable-object)
E:110, 8: Value 'typing.Sequence' is unsubscriptable (unsubscriptable-object)
.../experiments$
The code responsible for above output is here: https://gist.github.com/mbdevpl/5746f888d628b84fb025
In that code I was testing meta-classes and pylint's support for them, investigating why Sequence would be seen as unsubscriptable. But pylint has no issue with my custom subscriptable classes based on my custom metaclass. The issue is really just with Sequence from stdlib typing module.
So, the error boils down to more or less:
import typing
T = typing.Sequence[int] # Value 'typing.Sequence' is unsubscriptable
print(T)
However, typing.Sequence is generic, i.e. subscriptable:
https://docs.python.org/3/library/typing.html#typing.Sequence
What is going on here? Is it an expected issue due to partial support of PEP 484?
For completeness, my pylint --version:
No config file found, using default configuration
pylint 1.5.3,
astroid 1.4.3
Python 3.5.1 (default, Jan 12 2016, 00:06:29)
[GCC 5.3.0 20151204]
A gist with very minimal example, for which error comes up: https://gist.github.com/mbdevpl/24dfaecae8f6652a451e
Thanks for the report. Yes, most likely this is caused by a bad interaction with typing's metaclasses, which don't seem to be correctly understood by pylint. We don't quite support PEP 484 for now, but we're planning to have it for the next major release (2.0).
In the mean time, I'll try to see what exactly impedes our understanding of typing's classes.
What is puzzling for me is that many other subscriptable classes from typing module (e.g. Optional and Callable, as in my longer gist mentioned above) are correctly detected as subscriptable. But I haven't tested that it is only Sequence that causes this issue...
Maybe this observation will help in finding the cause. I think about doing some more tests for pylint and typing module. Could such tests be submitted (if compliant) as a test case for pylint via pull request?
Sure, let me know if you need anything for setting up the tests.
Yeah, I'll look into it, we should detect even indexing a class which defines the subscript protocol in the metaclass. Maybe it's something related to the MRO or Sequence.
I couldn't reproduce the bug in master, since we were already handling properly classes with unknown base classes there, while it was missing from the 1.5 branch.
The problem with Sequence is that it has in its base classes the Iterable[T_co] class, which astroid, pylint's inference engine, can't understand right now. This will probably change when we'll have support for PEP 484.
You mean PyLint will support type hinting in the future? :-)
That would be wonderful (I badly wish Python was typed)
I'm not any authority here, but from what I know: yes, there are plans
for that, since PEP484 makes type hints a part of the language. I'm not
sure about any dates though.
BTW some parts of mypy (especially the stubs
https://github.com/python/typeshed which are used by mypy) already are
kind of conceptually similar to stubs in pylint's brain (i.e. astroid),
at least in my opinion.
But I don't think Python will ever be typed ;)
Anyway, about the type hints (really, just hints) take a look at
https://github.com/JukkaL/mypy which is a type checker that uses those
hints.
Yes, there are plans for supporting it, it's on my roadmap (which I should publish on the wiki or so). But I'm not sure when this will be though. I hope that somewhere around april-may I could start working on this.
I get the Value 'x' is unsibscriptable when I try to assign to an object that has a setitem method, but no getitem. Is that related to this bug, or should I report it separately?
I'm still running into this and from the above comment it's not clear whether this has been closed and forgotten or if it was indeed fixed back in 2016 and is now resurfacing for some reason. Here's a simple piece of code reproducing this:
from typing import Sequence
def foo(hello: Sequence[str]) -> str:
return hello[0]
And here's some output:
core› ./env/bin/pylint thint.py ✓
/home/users/malbert/work/ipbase/core/env/lib/python3.5/site-packages/astroid/interpreter/_import/spec.py:15: PendingDeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
import imp
************* Module thint
thint.py:1:0: C0114: Missing module docstring (missing-module-docstring)
thint.py:4:0: C0102: Black listed name "foo" (blacklisted-name)
thint.py:4:0: C0116: Missing function or method docstring (missing-function-docstring)
thint.py:4:15: E1136: Value 'Sequence' is unsubscriptable (unsubscriptable-object)
----------------------------------------------------------------------
Your code has been rated at -16.67/10 (previous run: -16.67/10, +0.00)
pylint version:
/core› ./env/bin/pylint --version ✗: 18
/home/users/malbert/work/ipbase/core/env/lib/python3.5/site-packages/astroid/interpreter/_import/spec.py:15: PendingDeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
import imp
pylint 2.6.0
astroid 2.4.2
Python 3.5.2 (default, Jul 17 2020, 14:04:10)
[GCC 5.4.0 20160609]
Most helpful comment
I'm still running into this and from the above comment it's not clear whether this has been closed and forgotten or if it was indeed fixed back in 2016 and is now resurfacing for some reason. Here's a simple piece of code reproducing this:
And here's some output:
pylint version: