-
-
Notifications
You must be signed in to change notification settings - Fork 3k
feat: report @deprecated() on non-overloaded class constructors
#20104
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
0332484
d497f37
53622b1
39cd5f9
a473e52
8f08c60
b0ffd6b
c954f78
00897ab
3b7b986
4b42ea6
9e49aa1
4be62c6
79d0cb0
5302af3
d595948
c7c580c
f02dc8c
9cfdf7a
7c0b5e3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1420,7 +1420,11 @@ def is_generic_decorator_overload_call( | |
| return None | ||
|
|
||
| def handle_decorator_overload_call( | ||
| self, callee_type: CallableType, overloaded: Overloaded, ctx: Context | ||
| self, | ||
| callee_type: CallableType, | ||
| overloaded: Overloaded, | ||
| ctx: Context, | ||
| callee_is_overload_item: bool, | ||
| ) -> tuple[Type, Type] | None: | ||
| """Type-check application of a generic callable to an overload. | ||
|
|
||
|
|
@@ -1432,7 +1436,9 @@ def handle_decorator_overload_call( | |
| for item in overloaded.items: | ||
| arg = TempNode(typ=item) | ||
| with self.msg.filter_errors() as err: | ||
| item_result, inferred_arg = self.check_call(callee_type, [arg], [ARG_POS], ctx) | ||
| item_result, inferred_arg = self.check_call( | ||
| callee_type, [arg], [ARG_POS], ctx, is_overload_item=callee_is_overload_item | ||
| ) | ||
| if err.has_new_errors(): | ||
| # This overload doesn't match. | ||
| continue | ||
|
|
@@ -1538,6 +1544,7 @@ def check_call( | |
| callable_name: str | None = None, | ||
| object_type: Type | None = None, | ||
| original_type: Type | None = None, | ||
| is_overload_item: bool = False, | ||
| ) -> tuple[Type, Type]: | ||
| """Type check a call. | ||
|
|
||
|
|
@@ -1558,6 +1565,7 @@ def check_call( | |
| or None if unavailable (examples: 'builtins.open', 'typing.Mapping.get') | ||
| object_type: If callable_name refers to a method, the type of the object | ||
| on which the method is being called | ||
| is_overload_item: Whether this check is for an individual overload item | ||
| """ | ||
| callee = get_proper_type(callee) | ||
|
|
||
|
|
@@ -1568,7 +1576,7 @@ def check_call( | |
| # Special casing for inline application of generic callables to overloads. | ||
| # Supporting general case would be tricky, but this should cover 95% of cases. | ||
| overloaded_result = self.handle_decorator_overload_call( | ||
| callee, overloaded, context | ||
| callee, overloaded, context, is_overload_item | ||
| ) | ||
| if overloaded_result is not None: | ||
| return overloaded_result | ||
|
|
@@ -1582,6 +1590,7 @@ def check_call( | |
| callable_node, | ||
| callable_name, | ||
| object_type, | ||
| is_overload_item, | ||
| ) | ||
| elif isinstance(callee, Overloaded): | ||
| return self.check_overload_call( | ||
|
|
@@ -1659,11 +1668,18 @@ def check_callable_call( | |
| callable_node: Expression | None, | ||
| callable_name: str | None, | ||
| object_type: Type | None, | ||
| is_overload_item: bool = False, | ||
| ) -> tuple[Type, Type]: | ||
| """Type check a call that targets a callable value. | ||
|
|
||
| See the docstring of check_call for more information. | ||
| """ | ||
| # Check implicit calls to deprecated class constructors. | ||
| # Only the non-overload case is handled here. Overloaded constructors are handled | ||
| # separately during overload resolution. | ||
| if (not is_overload_item) and callee.is_type_obj(): | ||
| self.chk.warn_deprecated(callee.definition, context) | ||
|
Comment on lines
+1680
to
+1681
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks very nice now! Maybe a little bit more readable: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! I didn't initially want to sprinkle an extra method parameter everywhere, but was necessary for supporting
I wouldn't usually write it this way. Here, the majority of time that |
||
|
|
||
| # Always unpack **kwargs before checking a call. | ||
| callee = callee.with_unpacked_kwargs().with_normalized_var_args() | ||
| if callable_name is None and callee.name: | ||
|
|
@@ -2910,6 +2926,7 @@ def infer_overload_return_type( | |
| context=context, | ||
| callable_name=callable_name, | ||
| object_type=object_type, | ||
| is_overload_item=True, | ||
| ) | ||
| is_match = not w.has_new_errors() | ||
| if is_match: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
callee_is_overload_itemin this method doesn't actually activate any code paths. Its addition is for logical consistency and future-proofing any more cases handled here:mypy/mypy/checkexpr.py
Lines 1403 to 1415 in 054f721
The test for future-proofing is this one:
mypy/test-data/unit/check-deprecated.test
Line 834 in 79d0cb0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A cannot come up with a case where
callee_is_overload_itemwould actually be required. Could you please give an example?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be required if mypy supported the following:
That is, wrapping an overload with a class (rather than a function) while preserving or transforming its signature.
The change was made in anticipation that the ideal case should be supported some day, and wouldn't let a potential deprecation report slip by. However, it may be a bit premature on my part?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This use case seems very complicated, and I am not sure deducing
Overloadinstead ofOverloadWrapperwould be ideal. Additional members ofOverloadWrapperwould then be unknown to Mypy, wouldn't they?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there already a request for such a feature?