Skip to content

PEP 702 (@deprecated): consider overloads in snapshot descriptions #19613

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion mypy/server/astdiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,15 @@ def snapshot_definition(node: SymbolNode | None, common: SymbolSnapshot) -> Symb
setter_type = snapshot_optional_type(first_item.var.setter_type)
is_trivial_body = impl.is_trivial_body if impl else False
dataclass_transform_spec = find_dataclass_transform_spec(node)

deprecated: str | list[str | None] | None = None
if isinstance(node, FuncDef):
deprecated = node.deprecated
elif isinstance(node, OverloadedFuncDef):
deprecated = [node.deprecated] + [
i.func.deprecated for i in node.items if isinstance(i, Decorator)
]

return (
"Func",
common,
Expand All @@ -262,7 +271,7 @@ def snapshot_definition(node: SymbolNode | None, common: SymbolSnapshot) -> Symb
signature,
is_trivial_body,
dataclass_transform_spec.serialize() if dataclass_transform_spec is not None else None,
node.deprecated if isinstance(node, FuncDef) else None,
deprecated,
setter_type, # multi-part properties are stored as OverloadedFuncDef
)
elif isinstance(node, Var):
Expand Down
308 changes: 308 additions & 0 deletions test-data/unit/fine-grained.test
Original file line number Diff line number Diff line change
Expand Up @@ -11033,6 +11033,314 @@ b.py:1: error: class a.C is deprecated: use C2 instead
b.py:2: error: class a.D is deprecated: use D2 instead


[case testDeprecatedAddKeepChangeAndRemoveOverloadedFunctionDeprecation]
# flags: --enable-error-code=deprecated

from a import f
f(1)
f("y")
import a
a.f(1)
a.f("y")

[file a.py]
from typing import overload, Union
@overload
def f(x: int) -> int: ...
@overload
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[file a.py.2]
from typing import overload, Union
from typing_extensions import deprecated
@overload
def f(x: int) -> int: ...
@overload
@deprecated("pass int")
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[file a.py.3]
from typing import overload, Union
from typing_extensions import deprecated
@overload
def f(x: int) -> int: ...
@overload
@deprecated("pass int")
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[file a.py.4]
from typing import overload, Union
from typing_extensions import deprecated
@overload
def f(x: int) -> int: ...
@overload
@deprecated("pass int, please")
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[file a.py.5]
from typing import overload, Union
@overload
def f(x: int) -> int: ...
@overload
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[builtins fixtures/tuple.pyi]
[out]
==
main:5: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int
main:8: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int
==
main:5: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int
main:8: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int
==
main:5: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int, please
main:8: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int, please
==


[case testDeprecatedRemoveOverloadedFunctionDeprecation]
# flags: --enable-error-code=deprecated

from a import f
f(1)
f("y")
import a
a.f(1)
a.f("y")

[file a.py]
from typing import overload, Union
from typing_extensions import deprecated
@overload
def f(x: int) -> int: ...
@overload
@deprecated("pass int")
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[file a.py.2]
from typing import overload, Union
@overload
def f(x: int) -> int: ...
@overload
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[builtins fixtures/tuple.pyi]
[out]
main:5: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int
main:8: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int
==


[case testDeprecatedKeepOverloadedFunctionDeprecation]
# flags: --enable-error-code=deprecated

from a import f
f(1)
f("y")
import a
a.f(1)
a.f("y")

[file a.py]
from typing import overload, Union
from typing_extensions import deprecated
@overload
def f(x: int) -> int: ...
@overload
@deprecated("pass int")
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[file a.py.2]
from typing import overload, Union
from typing_extensions import deprecated
@overload
def f(x: int) -> int: ...
@overload
@deprecated("pass int")
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[builtins fixtures/tuple.pyi]
[out]
main:5: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int
main:8: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int
==
main:5: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int
main:8: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int


[case testDeprecatedAddOverloadedFunctionDeprecationIndirectImport]
# flags: --enable-error-code=deprecated

from b import f
f(1)
f("y")
import b
b.f(1)
b.f("y")

[file b.py]
from a import f

[file a.py]
from typing import overload, Union
@overload
def f(x: int) -> int: ...
@overload
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[file a.py.2]
from typing import overload, Union
from typing_extensions import deprecated
@overload
def f(x: int) -> int: ...
@overload
@deprecated("pass int")
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[builtins fixtures/tuple.pyi]
[out]
==
main:5: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int
main:8: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int


[case testDeprecatedChangeOverloadedFunctionDeprecationIndirectImport]
# flags: --enable-error-code=deprecated

from b import f
f(1)
f("y")
import b
b.f(1)
b.f("y")

[file b.py]
from a import f

[file a.py]
from typing import overload, Union
from typing_extensions import deprecated
@overload
def f(x: int) -> int: ...
@overload
@deprecated("pass int")
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[file a.py.2]
from typing import overload, Union
from typing_extensions import deprecated
@overload
def f(x: int) -> int: ...
@overload
@deprecated("pass int, please")
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[builtins fixtures/tuple.pyi]
[out]
main:5: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int
main:8: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int
==
main:5: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int, please
main:8: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int, please


[case testDeprecatedRemoveOverloadedFunctionDeprecationIndirectImport]
# flags: --enable-error-code=deprecated

from b import f
f(1)
f("y")
import b
b.f(1)
b.f("y")

[file b.py]
from a import f

[file a.py]
from typing import overload, Union
from typing_extensions import deprecated
@overload
def f(x: int) -> int: ...
@overload
@deprecated("pass int")
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[file a.py.2]
from typing import overload, Union
@overload
def f(x: int) -> int: ...
@overload
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[builtins fixtures/tuple.pyi]
[out]
main:5: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int
main:8: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: pass int
==


[case testDeprecatedOverloadedFunctionAlreadyDecorated]
# flags: --enable-error-code=deprecated

from b import f
f(1)
f("y")
import b
b.f(1)
b.f("y")

[file b.py]
from a import f

[file a.py]
from typing import Callable, overload, Union

def d(t: Callable[[str], str]) -> Callable[[str], str]: ...

@overload
def f(x: int) -> int: ...
@overload
@d
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[file a.py.2]
from typing import Callable, overload, Union
from typing_extensions import deprecated

def d(t: Callable[[str], str]) -> Callable[[str], str]: ...

@overload
def f(x: int) -> int: ...
@overload
@deprecated("deprecated decorated overload")
@d
def f(x: str) -> str: ...
def f(x: Union[int, str]) -> Union[int, str]: ...

[builtins fixtures/tuple.pyi]
[out]
==
main:5: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: deprecated decorated overload
main:8: error: overload def (x: builtins.str) -> builtins.str of function a.f is deprecated: deprecated decorated overload


[case testDeprecatedChangeClassDeprecationIndirectImport]
# flags: --enable-error-code=deprecated
from b import C
Expand Down
Loading