mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 05:44:56 +00:00
[ty] Add support for @warnings.deprecated
(#19376)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
* [x] basic handling * [x] parse and discover `@warnings.deprecated` attributes * [x] associate them with function definitions * [x] associate them with class definitions * [x] add a new "deprecated" diagnostic * [x] ensure diagnostic is styled appropriately for LSPs (DiagnosticTag::Deprecated) * [x] functions * [x] fire on calls * [x] fire on arbitrary references * [x] classes * [x] fire on initializers * [x] fire on arbitrary references * [x] methods * [x] fire on calls * [x] fire on arbitrary references * [ ] overloads * [ ] fire on calls * [ ] fire on arbitrary references(??? maybe not ???) * [ ] only fire if the actual selected overload is deprecated * [ ] dunder desugarring (warn on deprecated `__add__` if `+` is invoked) * [ ] alias supression? (don't warn on uses of variables that deprecated items were assigned to) * [ ] import logic * [x] fire on imports of deprecated items * [ ] suppress subsequent diagnostics if the import diagnostic fired (is this handled by alias supression?) * [x] fire on all qualified references (`module.mydeprecated`) * [x] fire on all references that depend on a `*` import Fixes https://github.com/astral-sh/ty/issues/153
This commit is contained in:
parent
e9a64e5825
commit
06f9f52e59
15 changed files with 1000 additions and 73 deletions
355
crates/ty_python_semantic/resources/mdtest/deprecated.md
Normal file
355
crates/ty_python_semantic/resources/mdtest/deprecated.md
Normal file
|
@ -0,0 +1,355 @@
|
|||
# Tests for the `@deprecated` decorator
|
||||
|
||||
## Introduction
|
||||
|
||||
<!-- snapshot-diagnostics -->
|
||||
|
||||
The decorator `@deprecated("some message")` can be applied to functions, methods, overloads, and
|
||||
classes. Uses of these items should subsequently produce a warning.
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
|
||||
@deprecated("use OtherClass")
|
||||
def myfunc(): ...
|
||||
|
||||
myfunc() # error: [deprecated] "use OtherClass"
|
||||
```
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
|
||||
@deprecated("use BetterClass")
|
||||
class MyClass: ...
|
||||
|
||||
MyClass() # error: [deprecated] "use BetterClass"
|
||||
```
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
|
||||
class MyClass:
|
||||
@deprecated("use something else")
|
||||
def afunc(): ...
|
||||
@deprecated("don't use this!")
|
||||
def amethod(self): ...
|
||||
|
||||
MyClass.afunc() # error: [deprecated] "use something else"
|
||||
MyClass().amethod() # error: [deprecated] "don't use this!"
|
||||
```
|
||||
|
||||
## Syntax
|
||||
|
||||
<!-- snapshot-diagnostics -->
|
||||
|
||||
The typeshed declaration of the decorator is as follows:
|
||||
|
||||
```ignore
|
||||
class deprecated:
|
||||
message: LiteralString
|
||||
category: type[Warning] | None
|
||||
stacklevel: int
|
||||
def __init__(self, message: LiteralString, /, *, category: type[Warning] | None = ..., stacklevel: int = 1) -> None: ...
|
||||
def __call__(self, arg: _T, /) -> _T: ...
|
||||
```
|
||||
|
||||
Only the mandatory message string is of interest to static analysis, the other two affect only
|
||||
runtime behaviour.
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
|
||||
@deprecated # error: [invalid-argument-type] "LiteralString"
|
||||
def invalid_deco(): ...
|
||||
|
||||
invalid_deco() # error: [missing-argument]
|
||||
```
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
|
||||
@deprecated() # error: [missing-argument] "message"
|
||||
def invalid_deco(): ...
|
||||
|
||||
invalid_deco()
|
||||
```
|
||||
|
||||
The argument is supposed to be a LiteralString, and we can handle simple constant propagations like
|
||||
this:
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
|
||||
x = "message"
|
||||
|
||||
@deprecated(x)
|
||||
def invalid_deco(): ...
|
||||
|
||||
invalid_deco() # error: [deprecated] "message"
|
||||
```
|
||||
|
||||
However sufficiently opaque LiteralStrings we can't resolve, and so we lose the message:
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated, LiteralString
|
||||
|
||||
def opaque() -> LiteralString:
|
||||
return "message"
|
||||
|
||||
@deprecated(opaque())
|
||||
def valid_deco(): ...
|
||||
|
||||
valid_deco() # error: [deprecated]
|
||||
```
|
||||
|
||||
Fully dynamic strings are technically allowed at runtime, but typeshed mandates that the input is a
|
||||
LiteralString, so we can/should emit a diagnostic for this:
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
|
||||
def opaque() -> str:
|
||||
return "message"
|
||||
|
||||
@deprecated(opaque()) # error: [invalid-argument-type] "LiteralString"
|
||||
def dubious_deco(): ...
|
||||
|
||||
dubious_deco()
|
||||
```
|
||||
|
||||
Although we have no use for the other arguments, we should still error if they're wrong.
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
|
||||
@deprecated("some message", dsfsdf="whatever") # error: [unknown-argument] "dsfsdf"
|
||||
def invalid_deco(): ...
|
||||
|
||||
invalid_deco()
|
||||
```
|
||||
|
||||
And we should always handle correct ones fine.
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
|
||||
@deprecated("some message", category=DeprecationWarning, stacklevel=1)
|
||||
def valid_deco(): ...
|
||||
|
||||
valid_deco() # error: [deprecated] "some message"
|
||||
```
|
||||
|
||||
## Different Versions
|
||||
|
||||
There are 2 different sources of `@deprecated`: `warnings` and `typing_extensions`. The version in
|
||||
`warnings` was added in 3.13, the version in `typing_extensions` is a compatibility shim.
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.13"
|
||||
```
|
||||
|
||||
`main.py`:
|
||||
|
||||
```py
|
||||
import warnings
|
||||
import typing_extensions
|
||||
|
||||
@warnings.deprecated("nope")
|
||||
def func1(): ...
|
||||
@typing_extensions.deprecated("nada")
|
||||
def func2(): ...
|
||||
|
||||
func1() # error: [deprecated] "nope"
|
||||
func2() # error: [deprecated] "nada"
|
||||
```
|
||||
|
||||
## Imports
|
||||
|
||||
### Direct Import Deprecated
|
||||
|
||||
Importing a deprecated item should produce a warning. Subsequent uses of the deprecated item
|
||||
shouldn't produce a warning.
|
||||
|
||||
`module.py`:
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
|
||||
@deprecated("Use OtherType instead")
|
||||
class DeprType: ...
|
||||
|
||||
@deprecated("Use other_func instead")
|
||||
def depr_func(): ...
|
||||
```
|
||||
|
||||
`main.py`:
|
||||
|
||||
```py
|
||||
# error: [deprecated] "Use OtherType instead"
|
||||
# error: [deprecated] "Use other_func instead"
|
||||
from module import DeprType, depr_func
|
||||
|
||||
# TODO: these diagnostics ideally shouldn't fire since we warn on the import
|
||||
DeprType() # error: [deprecated] "Use OtherType instead"
|
||||
depr_func() # error: [deprecated] "Use other_func instead"
|
||||
|
||||
def higher_order(x): ...
|
||||
|
||||
# TODO: these diagnostics ideally shouldn't fire since we warn on the import
|
||||
higher_order(DeprType) # error: [deprecated] "Use OtherType instead"
|
||||
higher_order(depr_func) # error: [deprecated] "Use other_func instead"
|
||||
|
||||
# TODO: these diagnostics ideally shouldn't fire since we warn on the import
|
||||
DeprType.__str__ # error: [deprecated] "Use OtherType instead"
|
||||
depr_func.__str__ # error: [deprecated] "Use other_func instead"
|
||||
```
|
||||
|
||||
### Non-Import Deprecated
|
||||
|
||||
If the items aren't imported and instead referenced using `module.item` then each use should produce
|
||||
a warning.
|
||||
|
||||
`module.py`:
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
|
||||
@deprecated("Use OtherType instead")
|
||||
class DeprType: ...
|
||||
|
||||
@deprecated("Use other_func instead")
|
||||
def depr_func(): ...
|
||||
```
|
||||
|
||||
`main.py`:
|
||||
|
||||
```py
|
||||
import module
|
||||
|
||||
module.DeprType() # error: [deprecated] "Use OtherType instead"
|
||||
module.depr_func() # error: [deprecated] "Use other_func instead"
|
||||
|
||||
def higher_order(x): ...
|
||||
|
||||
higher_order(module.DeprType) # error: [deprecated] "Use OtherType instead"
|
||||
higher_order(module.depr_func) # error: [deprecated] "Use other_func instead"
|
||||
|
||||
module.DeprType.__str__ # error: [deprecated] "Use OtherType instead"
|
||||
module.depr_func.__str__ # error: [deprecated] "Use other_func instead"
|
||||
```
|
||||
|
||||
### Star Import Deprecated
|
||||
|
||||
If the items are instead star-imported, then the actual uses should warn.
|
||||
|
||||
`module.py`:
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
|
||||
@deprecated("Use OtherType instead")
|
||||
class DeprType: ...
|
||||
|
||||
@deprecated("Use other_func instead")
|
||||
def depr_func(): ...
|
||||
```
|
||||
|
||||
`main.py`:
|
||||
|
||||
```py
|
||||
from module import *
|
||||
|
||||
DeprType() # error: [deprecated] "Use OtherType instead"
|
||||
depr_func() # error: [deprecated] "Use other_func instead"
|
||||
|
||||
def higher_order(x): ...
|
||||
|
||||
higher_order(DeprType) # error: [deprecated] "Use OtherType instead"
|
||||
higher_order(depr_func) # error: [deprecated] "Use other_func instead"
|
||||
|
||||
DeprType.__str__ # error: [deprecated] "Use OtherType instead"
|
||||
depr_func.__str__ # error: [deprecated] "Use other_func instead"
|
||||
```
|
||||
|
||||
## Aliases
|
||||
|
||||
Ideally a deprecated warning shouldn't transitively follow assignments, as you already had to "name"
|
||||
the deprecated symbol to assign it to something else. These kinds of diagnostics would therefore be
|
||||
redundant and annoying.
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
|
||||
@deprecated("Use OtherType instead")
|
||||
class DeprType: ...
|
||||
|
||||
@deprecated("Use other_func instead")
|
||||
def depr_func(): ...
|
||||
|
||||
alias_func = depr_func # error: [deprecated] "Use other_func instead"
|
||||
AliasClass = DeprType # error: [deprecated] "Use OtherType instead"
|
||||
|
||||
# TODO: these diagnostics ideally shouldn't fire
|
||||
alias_func() # error: [deprecated] "Use other_func instead"
|
||||
AliasClass() # error: [deprecated] "Use OtherType instead"
|
||||
```
|
||||
|
||||
## Dunders
|
||||
|
||||
If a dunder like `__add__` is deprecated, then the equivalent syntactic sugar like `+` should fire a
|
||||
diagnostic.
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
|
||||
class MyInt:
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
||||
@deprecated("MyInt `+` support is broken")
|
||||
def __add__(self, other):
|
||||
return MyInt(self.val + other.val)
|
||||
|
||||
x = MyInt(1)
|
||||
y = MyInt(2)
|
||||
z = x + y # TODO error: [deprecated] "MyInt `+` support is broken"
|
||||
```
|
||||
|
||||
## Overloads
|
||||
|
||||
Overloads can be deprecated, but only trigger warnings when invoked.
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
from typing_extensions import overload
|
||||
|
||||
@overload
|
||||
@deprecated("strings are no longer supported")
|
||||
def f(x: str): ...
|
||||
@overload
|
||||
def f(x: int): ...
|
||||
def f(x):
|
||||
print(x)
|
||||
|
||||
f(1)
|
||||
f("hello") # TODO: error: [deprecated] "strings are no longer supported"
|
||||
```
|
||||
|
||||
If the actual impl is deprecated, the deprecation always fires.
|
||||
|
||||
```py
|
||||
from typing_extensions import deprecated
|
||||
from typing_extensions import overload
|
||||
|
||||
@overload
|
||||
def f(x: str): ...
|
||||
@overload
|
||||
def f(x: int): ...
|
||||
@deprecated("unusable")
|
||||
def f(x):
|
||||
print(x)
|
||||
|
||||
f(1) # error: [deprecated] "unusable"
|
||||
f("hello") # error: [deprecated] "unusable"
|
||||
```
|
|
@ -0,0 +1,93 @@
|
|||
---
|
||||
source: crates/ty_test/src/lib.rs
|
||||
expression: snapshot
|
||||
---
|
||||
---
|
||||
mdtest name: deprecated.md - Tests for the `@deprecated` decorator - Introduction
|
||||
mdtest path: crates/ty_python_semantic/resources/mdtest/deprecated.md
|
||||
---
|
||||
|
||||
# Python source files
|
||||
|
||||
## mdtest_snippet.py
|
||||
|
||||
```
|
||||
1 | from typing_extensions import deprecated
|
||||
2 |
|
||||
3 | @deprecated("use OtherClass")
|
||||
4 | def myfunc(): ...
|
||||
5 |
|
||||
6 | myfunc() # error: [deprecated] "use OtherClass"
|
||||
7 | from typing_extensions import deprecated
|
||||
8 |
|
||||
9 | @deprecated("use BetterClass")
|
||||
10 | class MyClass: ...
|
||||
11 |
|
||||
12 | MyClass() # error: [deprecated] "use BetterClass"
|
||||
13 | from typing_extensions import deprecated
|
||||
14 |
|
||||
15 | class MyClass:
|
||||
16 | @deprecated("use something else")
|
||||
17 | def afunc(): ...
|
||||
18 | @deprecated("don't use this!")
|
||||
19 | def amethod(self): ...
|
||||
20 |
|
||||
21 | MyClass.afunc() # error: [deprecated] "use something else"
|
||||
22 | MyClass().amethod() # error: [deprecated] "don't use this!"
|
||||
```
|
||||
|
||||
# Diagnostics
|
||||
|
||||
```
|
||||
warning[deprecated]: The function `myfunc` is deprecated
|
||||
--> src/mdtest_snippet.py:6:1
|
||||
|
|
||||
4 | def myfunc(): ...
|
||||
5 |
|
||||
6 | myfunc() # error: [deprecated] "use OtherClass"
|
||||
| ^^^^^^ use OtherClass
|
||||
7 | from typing_extensions import deprecated
|
||||
|
|
||||
info: rule `deprecated` is enabled by default
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
warning[deprecated]: The class `MyClass` is deprecated
|
||||
--> src/mdtest_snippet.py:12:1
|
||||
|
|
||||
10 | class MyClass: ...
|
||||
11 |
|
||||
12 | MyClass() # error: [deprecated] "use BetterClass"
|
||||
| ^^^^^^^ use BetterClass
|
||||
13 | from typing_extensions import deprecated
|
||||
|
|
||||
info: rule `deprecated` is enabled by default
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
warning[deprecated]: The function `afunc` is deprecated
|
||||
--> src/mdtest_snippet.py:21:9
|
||||
|
|
||||
19 | def amethod(self): ...
|
||||
20 |
|
||||
21 | MyClass.afunc() # error: [deprecated] "use something else"
|
||||
| ^^^^^ use something else
|
||||
22 | MyClass().amethod() # error: [deprecated] "don't use this!"
|
||||
|
|
||||
info: rule `deprecated` is enabled by default
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
warning[deprecated]: The function `amethod` is deprecated
|
||||
--> src/mdtest_snippet.py:22:11
|
||||
|
|
||||
21 | MyClass.afunc() # error: [deprecated] "use something else"
|
||||
22 | MyClass().amethod() # error: [deprecated] "don't use this!"
|
||||
| ^^^^^^^ don't use this!
|
||||
|
|
||||
info: rule `deprecated` is enabled by default
|
||||
|
||||
```
|
|
@ -0,0 +1,178 @@
|
|||
---
|
||||
source: crates/ty_test/src/lib.rs
|
||||
expression: snapshot
|
||||
---
|
||||
---
|
||||
mdtest name: deprecated.md - Tests for the `@deprecated` decorator - Syntax
|
||||
mdtest path: crates/ty_python_semantic/resources/mdtest/deprecated.md
|
||||
---
|
||||
|
||||
# Python source files
|
||||
|
||||
## mdtest_snippet.py
|
||||
|
||||
```
|
||||
1 | from typing_extensions import deprecated
|
||||
2 |
|
||||
3 | @deprecated # error: [invalid-argument-type] "LiteralString"
|
||||
4 | def invalid_deco(): ...
|
||||
5 |
|
||||
6 | invalid_deco() # error: [missing-argument]
|
||||
7 | from typing_extensions import deprecated
|
||||
8 |
|
||||
9 | @deprecated() # error: [missing-argument] "message"
|
||||
10 | def invalid_deco(): ...
|
||||
11 |
|
||||
12 | invalid_deco()
|
||||
13 | from typing_extensions import deprecated
|
||||
14 |
|
||||
15 | x = "message"
|
||||
16 |
|
||||
17 | @deprecated(x)
|
||||
18 | def invalid_deco(): ...
|
||||
19 |
|
||||
20 | invalid_deco() # error: [deprecated] "message"
|
||||
21 | from typing_extensions import deprecated, LiteralString
|
||||
22 |
|
||||
23 | def opaque() -> LiteralString:
|
||||
24 | return "message"
|
||||
25 |
|
||||
26 | @deprecated(opaque())
|
||||
27 | def valid_deco(): ...
|
||||
28 |
|
||||
29 | valid_deco() # error: [deprecated]
|
||||
30 | from typing_extensions import deprecated
|
||||
31 |
|
||||
32 | def opaque() -> str:
|
||||
33 | return "message"
|
||||
34 |
|
||||
35 | @deprecated(opaque()) # error: [invalid-argument-type] "LiteralString"
|
||||
36 | def dubious_deco(): ...
|
||||
37 |
|
||||
38 | dubious_deco()
|
||||
39 | from typing_extensions import deprecated
|
||||
40 |
|
||||
41 | @deprecated("some message", dsfsdf="whatever") # error: [unknown-argument] "dsfsdf"
|
||||
42 | def invalid_deco(): ...
|
||||
43 |
|
||||
44 | invalid_deco()
|
||||
45 | from typing_extensions import deprecated
|
||||
46 |
|
||||
47 | @deprecated("some message", category=DeprecationWarning, stacklevel=1)
|
||||
48 | def valid_deco(): ...
|
||||
49 |
|
||||
50 | valid_deco() # error: [deprecated] "some message"
|
||||
```
|
||||
|
||||
# Diagnostics
|
||||
|
||||
```
|
||||
error[invalid-argument-type]: Argument to class `deprecated` is incorrect
|
||||
--> src/mdtest_snippet.py:3:1
|
||||
|
|
||||
1 | from typing_extensions import deprecated
|
||||
2 |
|
||||
3 | @deprecated # error: [invalid-argument-type] "LiteralString"
|
||||
| ^^^^^^^^^^^ Expected `LiteralString`, found `def invalid_deco() -> Unknown`
|
||||
4 | def invalid_deco(): ...
|
||||
|
|
||||
info: rule `invalid-argument-type` is enabled by default
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
error[missing-argument]: No argument provided for required parameter `arg` of bound method `__call__`
|
||||
--> src/mdtest_snippet.py:6:1
|
||||
|
|
||||
4 | def invalid_deco(): ...
|
||||
5 |
|
||||
6 | invalid_deco() # error: [missing-argument]
|
||||
| ^^^^^^^^^^^^^^
|
||||
7 | from typing_extensions import deprecated
|
||||
|
|
||||
info: rule `missing-argument` is enabled by default
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
error[missing-argument]: No argument provided for required parameter `message` of class `deprecated`
|
||||
--> src/mdtest_snippet.py:9:2
|
||||
|
|
||||
7 | from typing_extensions import deprecated
|
||||
8 |
|
||||
9 | @deprecated() # error: [missing-argument] "message"
|
||||
| ^^^^^^^^^^^^
|
||||
10 | def invalid_deco(): ...
|
||||
|
|
||||
info: rule `missing-argument` is enabled by default
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
warning[deprecated]: The function `invalid_deco` is deprecated
|
||||
--> src/mdtest_snippet.py:20:1
|
||||
|
|
||||
18 | def invalid_deco(): ...
|
||||
19 |
|
||||
20 | invalid_deco() # error: [deprecated] "message"
|
||||
| ^^^^^^^^^^^^ message
|
||||
21 | from typing_extensions import deprecated, LiteralString
|
||||
|
|
||||
info: rule `deprecated` is enabled by default
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
warning[deprecated]: The function `valid_deco` is deprecated
|
||||
--> src/mdtest_snippet.py:29:1
|
||||
|
|
||||
27 | def valid_deco(): ...
|
||||
28 |
|
||||
29 | valid_deco() # error: [deprecated]
|
||||
| ^^^^^^^^^^
|
||||
30 | from typing_extensions import deprecated
|
||||
|
|
||||
info: rule `deprecated` is enabled by default
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
error[invalid-argument-type]: Argument to class `deprecated` is incorrect
|
||||
--> src/mdtest_snippet.py:35:13
|
||||
|
|
||||
33 | return "message"
|
||||
34 |
|
||||
35 | @deprecated(opaque()) # error: [invalid-argument-type] "LiteralString"
|
||||
| ^^^^^^^^ Expected `LiteralString`, found `str`
|
||||
36 | def dubious_deco(): ...
|
||||
|
|
||||
info: rule `invalid-argument-type` is enabled by default
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
error[unknown-argument]: Argument `dsfsdf` does not match any known parameter of class `deprecated`
|
||||
--> src/mdtest_snippet.py:41:29
|
||||
|
|
||||
39 | from typing_extensions import deprecated
|
||||
40 |
|
||||
41 | @deprecated("some message", dsfsdf="whatever") # error: [unknown-argument] "dsfsdf"
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
42 | def invalid_deco(): ...
|
||||
|
|
||||
info: rule `unknown-argument` is enabled by default
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
warning[deprecated]: The function `valid_deco` is deprecated
|
||||
--> src/mdtest_snippet.py:50:1
|
||||
|
|
||||
48 | def valid_deco(): ...
|
||||
49 |
|
||||
50 | valid_deco() # error: [deprecated] "some message"
|
||||
| ^^^^^^^^^^ some message
|
||||
|
|
||||
info: rule `deprecated` is enabled by default
|
||||
|
||||
```
|
Loading…
Add table
Add a link
Reference in a new issue