blob: 6efefd550fe9f7e22fc9ff3c228294f8417dc3ef [file] [log] [blame]
"""
Checks that primitive values are not used in an
iterating/mapping context.
"""
# pylint: disable=missing-docstring,invalid-name,too-few-public-methods,no-init,no-self-use,import-error,unused-argument,bad-mcs-method-argument,wrong-import-position,no-else-return, useless-object-inheritance, unnecessary-comprehension
from __future__ import print_function
# primitives
numbers = [1, 2, 3]
for i in numbers:
pass
for i in iter(numbers):
pass
for i in "123":
pass
for i in u"123":
pass
for i in b"123":
pass
for i in bytearray(b"123"):
pass
for i in set(numbers):
pass
for i in frozenset(numbers):
pass
for i in dict(a=1, b=2):
pass
# comprehensions
for i in [x for x in range(10)]:
pass
for i in {x for x in range(1, 100, 2)}:
pass
for i in {x: 10 - x for x in range(10)}:
pass
# generators
def powers_of_two():
k = 0
while k < 10:
yield 2 ** k
k += 1
for i in powers_of_two():
pass
for i in powers_of_two: # [not-an-iterable]
pass
# check for custom iterators
class A(object):
pass
class B(object):
def __iter__(self):
return self
def __next__(self):
return 1
def next(self):
return 1
class C(object):
"old-style iterator"
def __getitem__(self, k):
if k > 10:
raise IndexError
return k + 1
def __len__(self):
return 10
for i in C():
print(i)
def test(*args):
print(args)
test(*A()) # [not-an-iterable]
test(*B())
test(*B) # [not-an-iterable]
for i in A(): # [not-an-iterable]
pass
for i in B():
pass
for i in B: # [not-an-iterable]
pass
for i in range: # [not-an-iterable]
pass
# check that primitive non-iterable types are caught
for i in True: # [not-an-iterable]
pass
for i in None: # [not-an-iterable]
pass
for i in 8.5: # [not-an-iterable]
pass
for i in 10: # [not-an-iterable]
pass
# skip uninferable instances
from some_missing_module import Iterable
class MyClass(Iterable):
pass
m = MyClass()
for i in m:
print(i)
# skip checks if statement is inside mixin/base/abstract class
class ManagedAccessViewMixin(object):
access_requirements = None
def get_access_requirements(self):
return self.access_requirements
def dispatch(self, *_args, **_kwargs):
klasses = self.get_access_requirements()
# no error should be emitted here
for requirement in klasses:
print(requirement)
class BaseType(object):
valid_values = None
def validate(self, value):
if self.valid_values is None:
return True
else:
# error should not be emitted here
for v in self.valid_values:
if value == v:
return True
return False
class AbstractUrlMarkManager(object):
def __init__(self):
self._lineparser = None
self._init_lineparser()
# error should not be emitted here
for line in self._lineparser:
print(line)
def _init_lineparser(self):
raise NotImplementedError
# class is not named as abstract
# but still is deduceably abstract
class UrlMarkManager(object):
def __init__(self):
self._lineparser = None
self._init_lineparser()
# error should not be emitted here
for line in self._lineparser:
print(line)
def _init_lineparser(self):
raise NotImplementedError
class HasDynamicGetattr(object):
def __init__(self):
self._obj = []
def __getattr__(self, attr):
return getattr(self._obj, attr)
for elem in HasDynamicGetattr():
pass