Skip to content

Commit

Permalink
[stubtest] don't call the __bool__ of default function param
Browse files Browse the repository at this point in the history
( ͡° ͜ʖ ͡°)
  • Loading branch information
jorenham authored and KotlinIsland committed Dec 10, 2024
1 parent d3e5574 commit 5bc55a3
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 39 deletions.
64 changes: 28 additions & 36 deletions .mypy/baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -1867,7 +1867,7 @@
"code": "no-any-expr",
"column": 40,
"message": "Expression type contains \"Any\" (has type \"(str, CacheMeta | None)\")",
"offset": 412,
"offset": 410,
"src": "new_interface_hash, self.meta = write_cache(",
"target": "mypy.build.State.write_cache"
},
Expand Down Expand Up @@ -2029,7 +2029,7 @@
"code": "redundant-expr",
"column": 31,
"message": "Condition is always true",
"offset": 499,
"offset": 504,
"src": "if new_frame is None:",
"target": "mypy.checker.TypeChecker.check_func_def"
},
Expand Down Expand Up @@ -2927,7 +2927,7 @@
"code": "explicit-override",
"column": 4,
"message": "Method \"visit_list_expr\" is not using @override but is overriding a method in class \"mypy.visitor.ExpressionVisitor\"",
"offset": 228,
"offset": 230,
"src": "def visit_list_expr(self, e: ListExpr) -> Type:",
"target": "mypy.checkexpr.ExpressionChecker.visit_list_expr"
},
Expand Down Expand Up @@ -13543,7 +13543,7 @@
"code": "explicit-override",
"column": 4,
"message": "Method \"__str__\" is not using @override but is overriding a method in class \"builtins.object\"",
"offset": 102,
"offset": 114,
"src": "def __str__(self) -> str:",
"target": "mypy.nodes.Node.__str__"
},
Expand Down Expand Up @@ -17329,7 +17329,7 @@
"code": "explicit-override",
"column": 4,
"message": "Method \"visit_func_def\" is not using @override but is overriding a method in class \"mypy.visitor.NodeVisitor\"",
"offset": 358,
"offset": 357,
"src": "def visit_func_def(self, defn: FuncDef) -> None:",
"target": "mypy.semanal.SemanticAnalyzer.visit_func_def"
},
Expand Down Expand Up @@ -17465,7 +17465,7 @@
"code": "explicit-override",
"column": 4,
"message": "Method \"visit_import\" is not using @override but is overriding a method in class \"mypy.visitor.NodeVisitor\"",
"offset": 428,
"offset": 430,
"src": "def visit_import(self, i: Import) -> None:",
"target": "mypy.semanal.SemanticAnalyzer.visit_import"
},
Expand Down Expand Up @@ -25160,7 +25160,7 @@
"column": 7,
"message": "Expression has type \"Any\"",
"offset": 45,
"src": "if runtime_arg.default != inspect.Parameter.empty:",
"src": "if runtime_arg.default is not inspect.Parameter.empty:",
"target": "mypy.stubtest._verify_arg_default_value"
},
{
Expand Down Expand Up @@ -25328,7 +25328,7 @@
"column": 28,
"message": "Expression has type \"Any\"",
"offset": 1,
"src": "return bool(arg.default != inspect.Parameter.empty)",
"src": "return bool(arg.default is not inspect.Parameter.empty)",
"target": "mypy.stubtest.Signature.__str__"
},
{
Expand Down Expand Up @@ -26656,38 +26656,14 @@
"column": 30,
"message": "Expression has type \"Any\"",
"offset": 18,
"src": "has_default = arg.default == inspect.Parameter.empty",
"target": "mypy.stubtest.get_mypy_type_of_runtime_value"
},
{
"code": "no-any-expr",
"column": 54,
"message": "Expression has type \"Any\"",
"offset": 2,
"src": "arg_kinds.append(nodes.ARG_POS if has_default else nodes.ARG_OPT)",
"target": "mypy.stubtest.get_mypy_type_of_runtime_value"
},
{
"code": "no-any-expr",
"column": 54,
"message": "Expression has type \"Any\"",
"offset": 2,
"src": "arg_kinds.append(nodes.ARG_POS if has_default else nodes.ARG_OPT)",
"target": "mypy.stubtest.get_mypy_type_of_runtime_value"
},
{
"code": "no-any-expr",
"column": 56,
"message": "Expression has type \"Any\"",
"offset": 2,
"src": "arg_kinds.append(nodes.ARG_NAMED if has_default else nodes.ARG_NAMED_OPT)",
"src": "has_default = arg.default is inspect.Parameter.empty",
"target": "mypy.stubtest.get_mypy_type_of_runtime_value"
},
{
"code": "redundant-expr",
"column": 21,
"message": "Condition is always true",
"offset": 3,
"offset": 9,
"src": "elif arg.kind == inspect.Parameter.VAR_KEYWORD:",
"target": "mypy.stubtest.get_mypy_type_of_runtime_value"
},
Expand Down Expand Up @@ -28653,7 +28629,7 @@
"code": "no-any-explicit",
"column": 0,
"message": "Explicit \"Any\" is not allowed",
"offset": 206,
"offset": 205,
"src": "def collect_cases(fn: Callable[..., Iterator[Case]]) -> FunctionType[..., None]:",
"target": "mypy.test.teststubtest.collect_cases"
},
Expand Down Expand Up @@ -29377,11 +29353,27 @@
"src": "def test_type_check_only(self) -> Iterator[Case]:",
"target": "mypy.test.teststubtest"
},
{
"code": "no-any-expr",
"column": 5,
"message": "Expression type contains \"Any\" (has type \"def (fn: (...) -> Iterator[Case]) -> def (...) -> None\")",
"offset": 65,
"src": "@collect_cases",
"target": "mypy.test.teststubtest"
},
{
"code": "no-any-decorated",
"column": 4,
"message": "Type of decorated function contains type \"Any\" (\"def (...) -> None\")",
"offset": 1,
"src": "def test_no_param_defaults_bool_eval(self) -> Iterator[Case]:",
"target": "mypy.test.teststubtest"
},
{
"code": "no-any-explicit",
"column": 8,
"message": "Explicit \"Any\" is not allowed",
"offset": 225,
"offset": 176,
"src": "def f(a: int, b: int, *, c: int, d: int = 0, **kwargs: Any) -> None:",
"target": "mypy.test.teststubtest.StubtestMiscUnit.test_signature"
},
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## [Unreleased]
### Added
- `collections.User*` should have `__repr__`
### Fixes
- `stubtest`: the `__bool__` method of function parameter defaults will no longer be unnecessarily evaluated

## [2.8.0]
### Added
Expand Down
6 changes: 3 additions & 3 deletions mypy/stubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ def _verify_arg_default_value(
stub_arg: nodes.Argument, runtime_arg: inspect.Parameter
) -> Iterator[str]:
"""Checks whether argument default values are compatible."""
if runtime_arg.default != inspect.Parameter.empty:
if runtime_arg.default is not inspect.Parameter.empty:
if stub_arg.kind.is_required():
yield (
f'runtime argument "{runtime_arg.name}" '
Expand Down Expand Up @@ -749,7 +749,7 @@ def get_type(arg: Any) -> str | None:

def has_default(arg: Any) -> bool:
if isinstance(arg, inspect.Parameter):
return bool(arg.default != inspect.Parameter.empty)
return bool(arg.default is not inspect.Parameter.empty)
if isinstance(arg, nodes.Argument):
return arg.kind.is_optional()
raise AssertionError
Expand Down Expand Up @@ -1618,7 +1618,7 @@ def anytype() -> mypy.types.UntypedType:
arg_names.append(
None if arg.kind == inspect.Parameter.POSITIONAL_ONLY else arg.name
)
has_default = arg.default == inspect.Parameter.empty
has_default = arg.default is inspect.Parameter.empty
if arg.kind == inspect.Parameter.POSITIONAL_ONLY:
arg_kinds.append(nodes.ARG_POS if has_default else nodes.ARG_OPT)
elif arg.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
Expand Down
17 changes: 17 additions & 0 deletions mypy/test/teststubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2411,6 +2411,23 @@ def func2() -> None: ...
error="func2",
)

@collect_cases
def test_no_param_defaults_bool_eval(self) -> Iterator[Case]:
yield Case(
stub="""
class Censored:
def __bool__(self) -> bool: ...
def snowflaky(sensitive_do_not_touch: Censored = ...) -> None: ...
""",
runtime="""
class Censored:
def __bool__(self) -> bool: # never try this at home, kids
raise ValueError
def snowflaky(sensitive_do_not_touch: Censored = Censored()) -> None: ...
""",
error=None,
)


def remove_color_code(s: str) -> str:
return re.sub("\\x1b.*?m", "", s) # this works!
Expand Down

0 comments on commit 5bc55a3

Please sign in to comment.