summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2017-04-13 13:03:41 +0300
committerClaudiu Popa <pcmanticore@gmail.com>2017-04-13 13:04:46 +0300
commitbf3e06fcb86fef4d0273ba40f8254377a050aa00 (patch)
treed52027be112c175d5dd6a5fba8e9dea835c6ea93
parent67b1508d91ae2983aa9b6c2ead374a6cb5ff3e3e (diff)
downloadpylint-git-bf3e06fcb86fef4d0273ba40f8254377a050aa00.tar.gz
We don't emit by default ``no-member`` if we have opaque inference objects in the inference results
This is controlled through the new flag ``--ignore-on-opaque-inference``, which is by default True. The inference can return multiple potential results while evaluating a Python object, but some branches might not be evaluated, which results in partial inference. In that case, it might be useful to still emit no-member and other checks for the rest of the inferred objects.
-rw-r--r--ChangeLog11
-rw-r--r--doc/whatsnew/1.7.rst8
-rw-r--r--pylint/checkers/typecheck.py39
-rw-r--r--pylint/test/functional/member_checks.py2
-rw-r--r--pylint/test/functional/member_checks.txt1
-rw-r--r--pylint/test/functional/member_checks_opaque.py6
-rw-r--r--pylint/test/functional/member_checks_opaque.rc2
-rw-r--r--pylint/test/functional/member_checks_opaque.txt1
8 files changed, 54 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 81bdfb450..9896b7bdf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,10 +6,19 @@ What's New in Pylint 1.7?
=========================
Release date: tba
+
* Don't emit missing-final-newline or trailing-whitespace for formfeeds (page breaks).
Close #1218 and #1219
-
+
+ * Don't emit by default no-member if we have opaque inference objects in the inference results
+
+ This is controlled through the new flag ignore-on-opaque-inference, which is by
+ default True. The inference can return multiple potential results while
+ evaluating a Python object, but some branches might not be evaluated, which
+ results in partial inference. In that case, it might be useful to still emit
+ no-member and other checks for the rest of the inferred objects.
+
* Added new message `assign-to-new-keyword` to warn about assigning to names which
will become a keyword in future Python releases.
diff --git a/doc/whatsnew/1.7.rst b/doc/whatsnew/1.7.rst
index 219691760..662323536 100644
--- a/doc/whatsnew/1.7.rst
+++ b/doc/whatsnew/1.7.rst
@@ -596,6 +596,14 @@ New checkers
Other Changes
=============
+* We don't emit by default ``no-member`` if we have opaque inference objects in the inference results
+
+ This is controlled through the new flag ``--ignore-on-opaque-inference``, which is by
+ default True. The inference can return multiple potential results while
+ evaluating a Python object, but some branches might not be evaluated, which
+ results in partial inference. In that case, it might be useful to still emit
+ no-member and other checks for the rest of the inferred objects.
+
* Namespace packages are now supported by pylint. This includes both explicit namespace
packages and implicit namespace packages, supported in Python 3 through PEP 420.
diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py
index 89f5b34c4..a504c1c40 100644
--- a/pylint/checkers/typecheck.py
+++ b/pylint/checkers/typecheck.py
@@ -474,7 +474,17 @@ class TypeChecker(BaseChecker):
msgs = MSGS
priority = -1
# configuration options
- options = (('ignore-mixin-members',
+ options = (('ignore-on-opaque-inference',
+ {'default': True, 'type': 'yn', 'metavar': '<y_or_n>',
+ 'help': 'This flag controls whether pylint should warn about '
+ 'no-member and similar checks whenever an opaque object '
+ 'is returned when inferring. The inference can return '
+ 'multiple potential results while evaluating a Python object, '
+ 'but some branches might not be evaluated, which results in '
+ 'partial inference. In that case, it might be useful to still emit '
+ 'no-member and other checks for the rest of the inferred objects.'}
+ ),
+ ('ignore-mixin-members',
{'default' : True, 'type' : 'yn', 'metavar': '<y_or_n>',
'help' : 'Tells whether missing members accessed in mixin \
class should be ignored. A mixin class is detected if its name ends with \
@@ -610,22 +620,26 @@ accessed. Python regular expressions are accepted.'}
return
try:
- infered = list(node.expr.infer())
+ inferred = list(node.expr.infer())
except exceptions.InferenceError:
return
+
# list of (node, nodename) which are missing the attribute
missingattr = set()
- inference_failure = False
- for owner in infered:
- # skip yes object
- if owner is astroid.YES:
- inference_failure = True
- continue
- if isinstance(owner, astroid.nodes.Unknown):
- inference_failure = True
- continue
+ non_opaque_inference_results = [
+ owner for owner in inferred
+ if owner is not astroid.Uninferable
+ and not isinstance(owner, astroid.nodes.Unknown)
+ ]
+ if (len(non_opaque_inference_results) != len(inferred)
+ and self.config.ignore_on_opaque_inference):
+ # There is an ambiguity in the inference. Since we can't
+ # make sure that we won't emit a false positive, we just stop
+ # whenever the inference returns an opaque inference object.
+ return
+ for owner in non_opaque_inference_results:
name = getattr(owner, 'name', None)
if _is_owner_ignored(owner, name, self.config.ignored_classes,
self.config.ignored_modules):
@@ -666,7 +680,6 @@ accessed. Python regular expressions are accepted.'}
if actual in done:
continue
done.add(actual)
- confidence = INFERENCE if not inference_failure else INFERENCE_FAILURE
if self.config.missing_member_hint:
hint = _missing_member_hint(owner, node.attrname,
@@ -678,7 +691,7 @@ accessed. Python regular expressions are accepted.'}
self.add_message('no-member', node=node,
args=(owner.display_type(), name,
node.attrname, hint),
- confidence=confidence)
+ confidence=INFERENCE)
@check_messages('assignment-from-no-return', 'assignment-from-none')
def visit_assign(self, node):
diff --git a/pylint/test/functional/member_checks.py b/pylint/test/functional/member_checks.py
index 86dcc0d0a..cb5f2313c 100644
--- a/pylint/test/functional/member_checks.py
+++ b/pylint/test/functional/member_checks.py
@@ -83,7 +83,7 @@ class Getattribute(object):
print(object.__init__)
print(property.__init__)
-print(Client().set_later.lower()) # [no-member]
+print(Client().set_later.lower())
print(Mixin().nanana())
print(Getattr().nananan())
print(Getattribute().batman())
diff --git a/pylint/test/functional/member_checks.txt b/pylint/test/functional/member_checks.txt
index f599da943..bf5f2c2c8 100644
--- a/pylint/test/functional/member_checks.txt
+++ b/pylint/test/functional/member_checks.txt
@@ -7,7 +7,6 @@ no-member:55:Client.test_bt_types:Instance of 'tuple' has no 'append' member:INF
no-member:57:Client.test_bt_types:Instance of 'str' has no 'loower' member; maybe 'lower'?:INFERENCE
no-member:59:Client.test_bt_types:Instance of 'int' has no 'whatever' member:INFERENCE
no-member:65:Client.test_no_false_positives:Super of 'Client' has no 'misssing' member:INFERENCE
-no-member:86::Instance of 'int' has no 'lower' member:INFERENCE_FAILURE
no-member:97::Instance of 'Client' has no 'indeed' member:INFERENCE
no-member:104::Class 'Client' has no 'missing' member:INFERENCE
no-member:110::Class 'Client' has no 'missing' member:INFERENCE
diff --git a/pylint/test/functional/member_checks_opaque.py b/pylint/test/functional/member_checks_opaque.py
new file mode 100644
index 000000000..d5e71a775
--- /dev/null
+++ b/pylint/test/functional/member_checks_opaque.py
@@ -0,0 +1,6 @@
+# pylint: disable=missing-docstring
+
+import json
+
+
+json.loads('bar').get('baz') # [no-member]
diff --git a/pylint/test/functional/member_checks_opaque.rc b/pylint/test/functional/member_checks_opaque.rc
new file mode 100644
index 000000000..025cd2a0f
--- /dev/null
+++ b/pylint/test/functional/member_checks_opaque.rc
@@ -0,0 +1,2 @@
+[TYPECHECK]
+ignore-on-opaque-inference=n
diff --git a/pylint/test/functional/member_checks_opaque.txt b/pylint/test/functional/member_checks_opaque.txt
new file mode 100644
index 000000000..68af2e6b9
--- /dev/null
+++ b/pylint/test/functional/member_checks_opaque.txt
@@ -0,0 +1 @@
+no-member:6::Instance of 'bool' has no 'get' member:INFERENCE