pycodestyle
pycodestyle copied to clipboard
E721: `Do not compare types, use 'isinstance()'` is overzealous with `type(None)`
Note: May be a dupe of (or at least related to) #882.
I discovered this while writing a decorator to parse the values of typing.get_type_hints(). This isn't exactly a bug in the flake8 feature, but rather an inconsistency in how NoneType is handled in the python3 typing system. This definitely feels like a bug, given that isinstance(none_type, type(None)) != none_type is type(None). If nothing else it's worth documenting the behavior because I couldn't find anything written up about it:
Setup:
# Setup:
from typing import Union
my_type = Union[str, None]
# --> typing.Union[str, NoneType]
none_arg = my_type.__args__[1]
# --> <class 'NoneType'>
Examples/behavior:
# Expected output based on recommendations for validating NoneType in python 3,
# but this triggers e721:
none_arg is type(None)
# --> True
# Just for example:
none_arg is None
# --> False
# Recommended by E721 but not actually valid
isinstance(none_arg, type(None))
# --> False
isinstance(none_arg, None)
# --> TypeError: isinstance() arg 2 must be a type or tuple of types
isinstance(none_arg, (None, ))
# --> TypeError: isinstance() arg 2 must be a type or tuple of types
Current workaround:
# Redefine local copy of NoneType no longer present in Python3
NoneType = type(None)
none_arg is NoneType
# --> True
# However, this fails to pass `mypy` inspection, so I'm now back to:
none_arg is type(None) # noqa: E721
# --> True