summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDani Alcala <112832187+clavedeluna@users.noreply.github.com>2022-11-15 09:57:15 -0300
committerGitHub <noreply@github.com>2022-11-15 07:57:15 -0500
commitd46d61320569891abcbb0cfbc160c5495fbb877c (patch)
treed8a7bfe5de47f0de3687a54a180a6c4a446f5e63
parent92fef269f223c382417db4ec0baed032795776e9 (diff)
downloadpylint-git-d46d61320569891abcbb0cfbc160c5495fbb877c.tar.gz
Improve bad-threading-instantiation check (#7617)
-rw-r--r--doc/whatsnew/fragments/7570.bugfix4
-rw-r--r--pylint/checkers/stdlib.py12
-rw-r--r--tests/functional/b/bad_thread_instantiation.py20
-rw-r--r--tests/functional/b/bad_thread_instantiation.txt10
4 files changed, 39 insertions, 7 deletions
diff --git a/doc/whatsnew/fragments/7570.bugfix b/doc/whatsnew/fragments/7570.bugfix
new file mode 100644
index 000000000..13cbc2916
--- /dev/null
+++ b/doc/whatsnew/fragments/7570.bugfix
@@ -0,0 +1,4 @@
+Improve ``bad-thread-instantiation`` check to warn if ``target`` is not passed in as a keyword argument
+or as a second argument.
+
+Closes #7570
diff --git a/pylint/checkers/stdlib.py b/pylint/checkers/stdlib.py
index e7ef763c4..6f40116f7 100644
--- a/pylint/checkers/stdlib.py
+++ b/pylint/checkers/stdlib.py
@@ -381,7 +381,7 @@ class StdlibChecker(DeprecatedMixin, BaseChecker):
"threading.Thread needs the target function",
"bad-thread-instantiation",
"The warning is emitted when a threading.Thread class "
- "is instantiated without the target function being passed. "
+ "is instantiated without the target function being passed as a kwarg or as a second argument. "
"By default, the first parameter is the group param, not the target param.",
),
"W1507": (
@@ -488,8 +488,14 @@ class StdlibChecker(DeprecatedMixin, BaseChecker):
# synced with the config argument deprecated-modules
def _check_bad_thread_instantiation(self, node: nodes.Call) -> None:
- if not node.kwargs and not node.keywords and len(node.args) <= 1:
- self.add_message("bad-thread-instantiation", node=node)
+ func_kwargs = {key.arg for key in node.keywords}
+ if "target" in func_kwargs:
+ return
+
+ if len(node.args) < 2 and (not node.kwargs or "target" not in func_kwargs):
+ self.add_message(
+ "bad-thread-instantiation", node=node, confidence=interfaces.HIGH
+ )
def _check_for_preexec_fn_in_popen(self, node: nodes.Call) -> None:
if node.keywords:
diff --git a/tests/functional/b/bad_thread_instantiation.py b/tests/functional/b/bad_thread_instantiation.py
index e7e02eaed..3c9aa5e55 100644
--- a/tests/functional/b/bad_thread_instantiation.py
+++ b/tests/functional/b/bad_thread_instantiation.py
@@ -1,8 +1,24 @@
-# pylint: disable=missing-docstring
+# pylint: disable=missing-docstring, redundant-keyword-arg, invalid-name, line-too-long
import threading
threading.Thread(lambda: None).run() # [bad-thread-instantiation]
threading.Thread(None, lambda: None)
+threading.Thread(lambda: None, group=None) # [bad-thread-instantiation]
+threading.Thread() # [bad-thread-instantiation]
+
threading.Thread(group=None, target=lambda: None).run()
-threading.Thread() # [bad-thread-instantiation]
+threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
+threading.Thread(None, None, "name")
+
+def thread_target(n):
+ print(n ** 2)
+
+
+thread = threading.Thread(thread_target, args=(10,)) # [bad-thread-instantiation]
+
+
+kw = {'target_typo': lambda x: x}
+threading.Thread(None, **kw) # [unexpected-keyword-arg, bad-thread-instantiation]
+
+threading.Thread(None, target_typo=lambda x: x) # [unexpected-keyword-arg, bad-thread-instantiation]
diff --git a/tests/functional/b/bad_thread_instantiation.txt b/tests/functional/b/bad_thread_instantiation.txt
index e969a2473..91358d30a 100644
--- a/tests/functional/b/bad_thread_instantiation.txt
+++ b/tests/functional/b/bad_thread_instantiation.txt
@@ -1,2 +1,8 @@
-bad-thread-instantiation:5:0:5:30::threading.Thread needs the target function:UNDEFINED
-bad-thread-instantiation:8:0:8:18::threading.Thread needs the target function:UNDEFINED
+bad-thread-instantiation:5:0:5:30::threading.Thread needs the target function:HIGH
+bad-thread-instantiation:7:0:7:42::threading.Thread needs the target function:HIGH
+bad-thread-instantiation:8:0:8:18::threading.Thread needs the target function:HIGH
+bad-thread-instantiation:18:9:18:52::threading.Thread needs the target function:HIGH
+bad-thread-instantiation:22:0:22:28::threading.Thread needs the target function:HIGH
+unexpected-keyword-arg:22:0:22:28::Unexpected keyword argument 'target_typo' in constructor call:UNDEFINED
+bad-thread-instantiation:24:0:24:47::threading.Thread needs the target function:HIGH
+unexpected-keyword-arg:24:0:24:47::Unexpected keyword argument 'target_typo' in constructor call:UNDEFINED