summaryrefslogtreecommitdiff
path: root/pylint
diff options
context:
space:
mode:
authoryushao2 <36848472+yushao2@users.noreply.github.com>2023-01-28 23:52:47 +0800
committerGitHub <noreply@github.com>2023-01-28 16:52:47 +0100
commit2cfc8f5d38a2e0ea46be7b3908729cca8c8fb8c4 (patch)
tree80e0d17cb484c51703356b86ed73d975b0417a6e /pylint
parent660405e6218258cee90570e8037c3b5e1440dcb6 (diff)
downloadpylint-git-2cfc8f5d38a2e0ea46be7b3908729cca8c8fb8c4.tar.gz
feat(6489): implement `positional-only-arguments-expected` checker (#8121)
* feat(6489): implement positional-only-arguments-expected checker * Update doc/user_guide/configuration/all-options.rst * update good/bad examples
Diffstat (limited to 'pylint')
-rw-r--r--pylint/checkers/method_args.py41
1 files changed, 40 insertions, 1 deletions
diff --git a/pylint/checkers/method_args.py b/pylint/checkers/method_args.py
index 58fcae5c0..e88248219 100644
--- a/pylint/checkers/method_args.py
+++ b/pylint/checkers/method_args.py
@@ -8,6 +8,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING
+import astroid
from astroid import arguments, bases, nodes
from pylint.checkers import BaseChecker, utils
@@ -22,6 +23,7 @@ class MethodArgsChecker(BaseChecker):
Checks for
* missing-timeout
+ * positional-only-arguments-expected
"""
name = "method_args"
@@ -34,6 +36,13 @@ class MethodArgsChecker(BaseChecker):
"is used. For example for 'requests' the program will never time out "
"(i.e. hang indefinitely).",
),
+ "E3102": (
+ "`%s()` got some positional-only arguments passed as keyword arguments: %s",
+ "positional-only-arguments-expected",
+ "Emitted when positional-only arguments have been passed as keyword arguments. "
+ "Remove the keywords for the affected arguments in the function call.",
+ {"minversion": (3, 8)},
+ ),
}
options = (
(
@@ -57,8 +66,14 @@ class MethodArgsChecker(BaseChecker):
),
)
- @utils.only_required_for_messages("missing-timeout")
+ @utils.only_required_for_messages(
+ "missing-timeout", "positional-only-arguments-expected"
+ )
def visit_call(self, node: nodes.Call) -> None:
+ self._check_missing_timeout(node)
+ self._check_positional_only_arguments_expected(node)
+
+ def _check_missing_timeout(self, node: nodes.Call) -> None:
"""Check if the call needs a timeout parameter based on package.func_name
configured in config.timeout_methods.
@@ -84,6 +99,30 @@ class MethodArgsChecker(BaseChecker):
confidence=INFERENCE,
)
+ def _check_positional_only_arguments_expected(self, node: nodes.Call) -> None:
+ """Check if positional only arguments have been passed as keyword arguments by
+ inspecting its method definition.
+ """
+ inferred_func = utils.safe_infer(node.func)
+ while isinstance(inferred_func, (astroid.BoundMethod, astroid.UnboundMethod)):
+ inferred_func = inferred_func._proxied
+ if not (
+ isinstance(inferred_func, (nodes.FunctionDef))
+ and inferred_func.args.posonlyargs
+ ):
+ return
+ pos_args = [a.name for a in inferred_func.args.posonlyargs]
+ kws = [k.arg for k in node.keywords if k.arg in pos_args]
+ if not kws:
+ return
+
+ self.add_message(
+ "positional-only-arguments-expected",
+ node=node,
+ args=(node.func.as_string(), ", ".join(f"'{k}'" for k in kws)),
+ confidence=INFERENCE,
+ )
+
def register(linter: PyLinter) -> None:
linter.register_checker(MethodArgsChecker(linter))