Open pylint-bot opened 8 years ago
Original comment by BitBucket: dmand, GitHub: @dmand?:
Okay, so here's the smaller code sample for reproducing one of false positives from the repo (this one was taken from rebulk.rules and truncated a bit).
from abc import ABCMeta, abstractmethod
from types import GeneratorType
import six
def is_iterable(obj):
return hasattr(obj, '__iter__') and not isinstance(obj, str) or isinstance(obj, GeneratorType)
@six.add_metaclass(ABCMeta)
class Consequence(object):
@abstractmethod
def then(self, matches, when_response, context):
pass
class AppendTags(Consequence):
def __init__(self, tags):
self.tags = tags
self.remove = RemoveMatch()
def then(self, matches, when_response, context):
removed = self.remove.then(matches, when_response, context)
if is_iterable(removed):
removed = list(removed)
for match in removed:
match.tags.extend(self.tags)
elif removed:
removed.tags.extend(self.tags) # Error: Instance of 'list' has no 'tags' member (no-member)
class RemoveMatch(Consequence):
def then(self, matches, when_response, context):
if is_iterable(when_response):
ret = []
when_response = list(when_response)
for match in when_response:
if match in matches:
matches.remove(match)
ret.append(match)
return ret
else:
if when_response in matches:
matches.remove(when_response)
return when_response
The trouble comes from the fact that RemoveMatch.then
method can return either a list or its second argument value. And in AppendTags.then
pylint is unable to see the assertion made with if-statement, so it emits the warning about possible list value of removed
not having tags
member.
Possible solutions:
RemoveMatch.then
method to always return values of one type (it doesn't seem like a bad idea, honestly, but there must be another way)helpers.safe_infer
)RemoveMatch.then
) or understanding assertions about values made with if-statements (not sure if we can implement that).Original comment by Marcin Barczyński (BitBucket: marcinbarczynski, GitHub: @marcinbarczynski?):
More examples in python 2.7:
#!python
try:
open("a")
except Exception as e:
if isinstance(e, OSError):
print e.errno
pylint 1.5 prints: [E1101(no-member), ] Instance of 'Exception' has no 'errno' member
#!python
import Queue
from multiprocessing.managers import SyncManager
SyncManager.register('LifoQueue', Queue.LifoQueue)
[E1101(no-member), ] Class 'SyncManager' has no 'register' member
Originally reported by: Rémi Alvergnat (BitBucket: Toilal, GitHub: @Toilal?)
I'm trying to reproduce in a small environment, but it currently occurs in https://github.com/Toilal/rebulk. (I've disabled no-member as a workaround)
It was working properly on 1.4.x