Skip to content

Commit f7a6b15

Browse files
committed
Handle built-in __init__ call with bad args.
1 parent 9f4828d commit f7a6b15

File tree

2 files changed

+40
-24
lines changed

2 files changed

+40
-24
lines changed

pylint/checkers/typecheck.py

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,13 +1455,13 @@ def visit_call(self, node: nodes.Call) -> None:
14551455
"""
14561456

14571457
def _dp(s, val=None):
1458-
if "Attribute.__init__ l.13" not in str(node):
1459-
# print("Not in init")
1460-
return
1461-
if val is None:
1462-
print(f" {s}", flush=True)
1463-
else:
1464-
print(f" {s}: {val}", flush=True)
1458+
return
1459+
## if "Attribute.__init__" not in str(node):
1460+
## return
1461+
## if val is None:
1462+
## print(f" {s}", flush=True)
1463+
## else:
1464+
## print(f" {s}: {val}", flush=True)
14651465

14661466
_dp("-" * 25)
14671467
_dp("visit call, node", node)
@@ -1477,24 +1477,44 @@ def _dp(s, val=None):
14771477

14781478
_dp("Data dump for __init__ call")
14791479
call_site = astroid.arguments.CallSite.from_call(node)
1480-
num_positional_args = len(call_site.positional_arguments)
1480+
_dp("call_site", call_site)
1481+
# _dp("call_site args", call_site.arguments)
1482+
# _dp("call site positional args:", call_site.positional_arguments)
1483+
# _dp("call site keyword args:", call_site.keyword_arguments)
1484+
# _dp("call site invalid args", call_site.has_invalid_arguments())
1485+
# _dp("call site inv keywords", call_site.has_invalid_keywords())
1486+
_dp("node args", node.args)
14811487
_dp("node frame", node.frame())
1482-
_dp("isinst", isinstance(node.frame(), nodes.ClassDef))
1483-
_dp("funcdef", isinstance(called, nodes.FunctionDef))
1488+
# _dp("isinst", isinstance(node.frame(), nodes.ClassDef))
1489+
# _dp("funcdef", isinstance(called, nodes.FunctionDef))
14841490
_dp("called", called)
1491+
_dp("bound method init in called", "BoundMethod __init__ of builtins.object" in str(called))
1492+
_dp("called.args", called.args)
14851493
_dp("frame body", node.frame().body)
1486-
_dp("called in frame body", called in node.frame().body)
1487-
_dp("npa", num_positional_args)
1488-
_dp("dec names", called.decoratornames())
1494+
# _dp("called in frame body", called in node.frame().body)
1495+
# _dp("dec names", called.decoratornames())
1496+
1497+
def _call_site_has_args(cs):
1498+
"True if any args passed."
1499+
has_args = (
1500+
False
1501+
or len(cs.positional_arguments) > 0
1502+
or len(cs.keyword_arguments.items()) > 0
1503+
or cs.starargs is not None
1504+
or cs.kwargs is not None
1505+
)
1506+
return has_args
14891507

14901508
if called.args.args is None:
1491-
_dp("called.args.args is None")
1492-
_dp("called.name", called.name)
14931509
if called.name == "isinstance":
14941510
# Verify whether second argument of isinstance is a valid type
14951511
self._check_isinstance_args(node, callable_name)
14961512
# Built-in functions have no argument information.
1497-
_dp("Returning now")
1513+
# Check built-in __init__ ... a user-defined __init__ function
1514+
# is handled elsewhere.
1515+
if "BoundMethod __init__ of builtins.object" in str(called):
1516+
if _call_site_has_args(call_site):
1517+
self.add_message("too-many-function-args", node=node, args=("__init__",))
14981518
return
14991519

15001520
if len(called.argnames()) != len(set(called.argnames())):

tests/test_self.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -343,21 +343,17 @@ def test_wrong_import_position_when_others_disabled(self) -> None:
343343

344344
def test_super_init_with_non_self_argument(self) -> None:
345345
module1 = join(HERE, "regrtest_data", "super_init_with_non_self_argument.py")
346-
args = [module1]
346+
args = [module1, "-rn", "-sn"]
347347
out = StringIO()
348348
self._run_pylint(args, out=out)
349349
actual_output = self._clean_paths(out.getvalue().strip())
350-
351-
expected_output = textwrap.dedent(
350+
expected = textwrap.dedent(
352351
f"""
353352
************* Module super_init_with_non_self_argument
354-
{module1}:11:0: blah
353+
{module1}:13:8: E1121: Too many positional arguments for __init__ call (too-many-function-args)
355354
"""
356355
)
357-
assert (
358-
"Your code has been rated at 10.00/10" not in actual_output
359-
), "bad code should fail."
360-
assert self._clean_paths(expected_output.strip()) == actual_output.strip()
356+
assert self._clean_paths(expected.strip()) == actual_output.strip()
361357

362358
def test_progress_reporting(self) -> None:
363359
module1 = join(HERE, "regrtest_data", "import_something.py")

0 commit comments

Comments
 (0)