diff --git a/conformance/results/mypy/directives_deprecated.toml b/conformance/results/mypy/directives_deprecated.toml new file mode 100644 index 000000000..9c7552b54 --- /dev/null +++ b/conformance/results/mypy/directives_deprecated.toml @@ -0,0 +1,20 @@ +conformant = "Unsupported" +notes = """ +Does not support @deprecated. +""" +conformance_automated = "Fail" +errors_diff = """ +Line 15: Expected 1 errors +Line 23: Expected 1 errors +Line 24: Expected 1 errors +Line 29: Expected 1 errors +Line 40: Expected 1 errors +Line 41: Expected 1 errors +Line 43: Expected 1 errors +Line 46: Expected 1 errors +Line 47: Expected 1 errors +Line 57: Expected 1 errors +Line 87: Expected 1 errors +""" +output = """ +""" diff --git a/conformance/results/mypy/version.toml b/conformance/results/mypy/version.toml index 8f919ed46..b79e0a27d 100644 --- a/conformance/results/mypy/version.toml +++ b/conformance/results/mypy/version.toml @@ -1,2 +1,2 @@ version = "mypy 1.11.0" -test_duration = 1.0 +test_duration = 1.4 diff --git a/conformance/results/pyre/directives_deprecated.toml b/conformance/results/pyre/directives_deprecated.toml new file mode 100644 index 000000000..9c7552b54 --- /dev/null +++ b/conformance/results/pyre/directives_deprecated.toml @@ -0,0 +1,20 @@ +conformant = "Unsupported" +notes = """ +Does not support @deprecated. +""" +conformance_automated = "Fail" +errors_diff = """ +Line 15: Expected 1 errors +Line 23: Expected 1 errors +Line 24: Expected 1 errors +Line 29: Expected 1 errors +Line 40: Expected 1 errors +Line 41: Expected 1 errors +Line 43: Expected 1 errors +Line 46: Expected 1 errors +Line 47: Expected 1 errors +Line 57: Expected 1 errors +Line 87: Expected 1 errors +""" +output = """ +""" diff --git a/conformance/results/pyre/directives_reveal_type.toml b/conformance/results/pyre/directives_reveal_type.toml index 92a179946..ed30bc74f 100644 --- a/conformance/results/pyre/directives_reveal_type.toml +++ b/conformance/results/pyre/directives_reveal_type.toml @@ -1,5 +1,5 @@ conformant = "Partial" -notes = """" +notes = """ Produces errors rather than warnings on `reveal_type`. """ output = """ diff --git a/conformance/results/pyre/version.toml b/conformance/results/pyre/version.toml index 31ee493d9..dc6693abb 100644 --- a/conformance/results/pyre/version.toml +++ b/conformance/results/pyre/version.toml @@ -1,2 +1,2 @@ version = "pyre 0.9.22" -test_duration = 2.5 +test_duration = 1.8 diff --git a/conformance/results/pyright/directives_deprecated.toml b/conformance/results/pyright/directives_deprecated.toml new file mode 100644 index 000000000..20cf127ad --- /dev/null +++ b/conformance/results/pyright/directives_deprecated.toml @@ -0,0 +1,31 @@ +conformant = "Partial" +notes = """ +Does not report error for deprecated magic methods. +""" +conformance_automated = "Fail" +errors_diff = """ +Line 40: Expected 1 errors +Line 41: Expected 1 errors +Line 47: Expected 1 errors +Line 33: Unexpected errors ['directives_deprecated.py:33:7 - error: The class "Ham" is deprecated'] +""" +output = """ +directives_deprecated.py:15:44 - error: The class "Ham" is deprecated +  Use Spam instead (reportDeprecated) +directives_deprecated.py:23:9 - error: The function "norwegian_blue" is deprecated +  It is pining for the fiords (reportDeprecated) +directives_deprecated.py:24:13 - error: The function "norwegian_blue" is deprecated +  It is pining for the fiords (reportDeprecated) +directives_deprecated.py:29:9 - error: The function "foo" is deprecated +  Only str will be allowed (reportDeprecated) +directives_deprecated.py:33:7 - error: The class "Ham" is deprecated +  Use Spam instead (reportDeprecated) +directives_deprecated.py:43:6 - error: The getter for property "greasy" is deprecated +  All spam will be equally greasy (reportDeprecated) +directives_deprecated.py:46:6 - error: The setter for property "shape" is deprecated +  Shapes are becoming immutable (reportDeprecated) +directives_deprecated.py:57:9 - error: The function "lorem" is deprecated +  Deprecated (reportDeprecated) +directives_deprecated.py:87:13 - error: The method "foo" in class "Fooable" is deprecated +  Deprecated (reportDeprecated) +""" diff --git a/conformance/results/pyright/version.toml b/conformance/results/pyright/version.toml index 3229acb55..4d7fa4a51 100644 --- a/conformance/results/pyright/version.toml +++ b/conformance/results/pyright/version.toml @@ -1,2 +1,2 @@ version = "pyright 1.1.373" -test_duration = 1.4 +test_duration = 1.2 diff --git a/conformance/results/pytype/directives_deprecated.toml b/conformance/results/pytype/directives_deprecated.toml new file mode 100644 index 000000000..9fb6a4dfa --- /dev/null +++ b/conformance/results/pytype/directives_deprecated.toml @@ -0,0 +1,26 @@ +conformant = "Unsupported" +notes = """ +Does not support @deprecated. +""" +conformance_automated = "Fail" +errors_diff = """ +Line 23: Expected 1 errors +Line 24: Expected 1 errors +Line 29: Expected 1 errors +Line 40: Expected 1 errors +Line 41: Expected 1 errors +Line 43: Expected 1 errors +Line 46: Expected 1 errors +Line 47: Expected 1 errors +Line 57: Expected 1 errors +Line 87: Expected 1 errors +Line 16: Unexpected errors ['File "directives_deprecated.py", line 16, in : Can\\'t find module \\'_directives_deprecated_library\\'. [import-error]'] +Line 18: Unexpected errors ['File "directives_deprecated.py", line 18, in : typing_extensions.deprecated not supported yet [not-supported-yet]'] +Line 66: Unexpected errors ['File "directives_deprecated.py", line 66, in : typing.override not supported yet [not-supported-yet]'] +""" +output = """ +File "directives_deprecated.py", line 15, in : Can't find module '_directives_deprecated_library'. [import-error] +File "directives_deprecated.py", line 16, in : Can't find module '_directives_deprecated_library'. [import-error] +File "directives_deprecated.py", line 18, in : typing_extensions.deprecated not supported yet [not-supported-yet] +File "directives_deprecated.py", line 66, in : typing.override not supported yet [not-supported-yet] +""" diff --git a/conformance/results/pytype/version.toml b/conformance/results/pytype/version.toml index 16866283c..cf4474998 100644 --- a/conformance/results/pytype/version.toml +++ b/conformance/results/pytype/version.toml @@ -1,2 +1,2 @@ version = "pytype 2024.04.11" -test_duration = 32.7 +test_duration = 30.0 diff --git a/conformance/results/results.html b/conformance/results/results.html index 04c1a6ab3..fd3eec957 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -159,16 +159,16 @@

Python Type System Conformance Test Results

+ + + + + + diff --git a/conformance/tests/_directives_deprecated_library.py b/conformance/tests/_directives_deprecated_library.py new file mode 100644 index 000000000..efcc6dcfd --- /dev/null +++ b/conformance/tests/_directives_deprecated_library.py @@ -0,0 +1,44 @@ +""" +Support module for directive_deprecated. +""" + +from typing import Self, overload + +from typing_extensions import deprecated + + +@deprecated("Use Spam instead") +class Ham: ... + + +@deprecated("It is pining for the fiords") +def norwegian_blue(x: int) -> int: ... + + +@overload +@deprecated("Only str will be allowed") +def foo(x: int) -> str: ... + + +@overload +def foo(x: str) -> str: ... + + +def foo(x: int | str) -> str: ... + + +class Spam: + + @deprecated("There is enough spam in the world") + def __add__(self, other: object) -> Self: ... + + @property + @deprecated("All spam will be equally greasy") + def greasy(self) -> float: ... + + @property + def shape(self) -> str: ... + + @shape.setter + @deprecated("Shapes are becoming immutable") + def shape(self, value: str) -> None: ... diff --git a/conformance/tests/directives_deprecated.py b/conformance/tests/directives_deprecated.py new file mode 100644 index 000000000..cbae60547 --- /dev/null +++ b/conformance/tests/directives_deprecated.py @@ -0,0 +1,116 @@ +""" +Tests the warnings.deprecated function. +""" + +# pyright: reportDeprecated=true + +# Specification: https://typing.readthedocs.io/en/latest/spec/directives.html#deprecated +# See also https://peps.python.org/pep-0702/ + +# > Type checkers should produce a diagnostic whenever they encounter a usage of an object +# > marked as deprecated. [...] For deprecated classes and functions, this includes: + +# > * `from` imports + +from _directives_deprecated_library import Ham # E: Use of deprecated class Ham +import _directives_deprecated_library as library + +from typing_extensions import deprecated + + +# > * References through module, class, or instance attributes + +library.norwegian_blue(1) # E: Use of deprecated function norwegian_blue +map(library.norwegian_blue, [1, 2, 3]) # E: Use of deprecated function norwegian_blue + + +# > For deprecated overloads, this includes all calls that resolve to the deprecated overload. + +library.foo(1) # E: Use of deprecated overload for foo +library.foo("x") # OK + + +ham = Ham() # OK (already reported above) + + +# > * Any syntax that indirectly triggers a call to the function. + +spam = library.Spam() + +_ = spam + 1 # E: Use of deprecated method Spam.__add__ +spam += 1 # E: Use of deprecated method Spam.__add__ + +spam.greasy # E: Use of deprecated property Spam.greasy +spam.shape # OK + +spam.shape = "cube" # E: Use of deprecated property setter Spam.shape +spam.shape += "cube" # E: Use of deprecated property setter Spam.shape + + +class Invocable: + + @deprecated("Deprecated") + def __call__(self) -> None: ... + +invocable = Invocable() +invocable() # E: Use of deprecated method __call__ + + +# > * Any usage of deprecated objects in their defining module + +@deprecated("Deprecated") +def lorem() -> None: ... + + +ipsum = lorem() # E: Use of deprecated function lorem + + +# > There are additional scenarios where deprecations could come into play. +# > For example, an object may implement a `typing.Protocol`, +# > but one of the methods required for protocol compliance is deprecated. +# > As scenarios such as this one appear complex and relatively unlikely to come up in practice, +# > this PEP does not mandate that type checkers detect them. + +from typing import Protocol, override + + +class Fooable(Protocol): + + @deprecated("Deprecated") + def foo(self) -> None: ... + + def bar(self) -> None: ... + + +class Fooer(Fooable): + + @override + def foo(self) -> None: # E?: Implementation of deprecated method foo + ... + + def bar(self) -> None: ... + + +def foo_it(fooable: Fooable) -> None: + fooable.foo() # E: Use of deprecated method foo + fooable.bar() + + +# https://github.com/python/typing/pull/1822#discussion_r1693991644 + +class Fooable2(Protocol): + + def foo(self) -> None: ... + + +class Concrete: + + @deprecated("Deprecated") + def foo(self) -> None: ... + + +def take_fooable(f: Fooable2) -> None: ... + + +def caller(c: Concrete) -> None: + take_fooable(c) # E?: Concrete is a Fooable2, but only because of a deprecated method
 
mypy 1.11.0
-
1.0sec
+
1.4sec
pyright 1.1.373
-
1.4sec
+
1.2sec
pyre 0.9.22
-
2.5sec
+
1.8sec
pytype 2024.04.11
-
32.7sec
+
30.0sec
@@ -972,6 +972,12 @@

Python Type System Conformance Test Results

Pass
Partial

Does not reject a call to "cast" with additional arguments.

     directives_deprecated
Unsupported

Does not support @deprecated.

Partial

Does not report error for deprecated magic methods.

Unsupported

Does not support @deprecated.

Unsupported

Does not support @deprecated.

     directives_no_type_check
Partial

Does not honor `@no_type_check` class decorator (allowed).

Does not reject invalid call of `@no_type_check` function.

Pass*

Does not honor `@no_type_check` class decorator (allowed).