Skip to content

Commit

Permalink
Merge branch 'main' into dcreager/type-of-any
Browse files Browse the repository at this point in the history
* main:
  [`airflow`] Add fix to remove deprecated keyword arguments (`AIR302`) (#14887)
  Improve mdtests style (#14884)
  Reference `suppress-dummy-regex-options` in documentation of rules supporting it (#14888)
  [`flake8-bugbear`] `itertools.batched()` without explicit `strict` (`B911`) (#14408)
  [`ruff`] Mark autofix for `RUF052` as always unsafe (#14824)
  [red-knot] Improve type inference for except handlers (#14838)
  More typos found by codespell (#14880)
  [red-knot] move standalone expression_ty to TypeInferenceBuilder::file_expression_ty (#14879)
  [`ruff`] Do not simplify `round()` calls (`RUF046`) (#14832)
  Stop referring to early ruff versions (#14862)
  Fix a typo in `class.rs` (#14877)
  [`flake8-pyi`] Also remove `self` and `cls`'s annotation (`PYI034`) (#14801)
  [`pyupgrade`] Remove unreachable code in `UP015` implementation (#14871)
  [`flake8-bugbear`] Skip `B028` if `warnings.warn` is called with `*args` or `**kwargs` (#14870)
  • Loading branch information
dcreager committed Dec 10, 2024
2 parents b65a156 + dc0d944 commit 88d2fc3
Show file tree
Hide file tree
Showing 101 changed files with 3,641 additions and 2,706 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ If you define your own class named `Any`, using that in a type expression refers
isn't a spelling of the Any type.

```py
class Any:
pass
class Any: ...

x: Any

Expand All @@ -59,17 +58,14 @@ assignable to `int`.
```py
from typing import Any

class Subclass(Any):
pass
class Subclass(Any): ...

reveal_type(Subclass.__mro__) # revealed: tuple[Literal[Subclass], Any, Literal[object]]

x: Subclass = 1 # error: [invalid-assignment]
# TODO: no diagnostic
y: int = Subclass() # error: [invalid-assignment]

def f() -> Subclass:
pass

reveal_type(f()) # revealed: Subclass
def _(s: Subclass):
reveal_type(s) # revealed: Subclass
```
Original file line number Diff line number Diff line change
Expand Up @@ -89,28 +89,26 @@ vice versa.
```py
from typing_extensions import Literal, LiteralString

def coinflip() -> bool:
return True
def _(flag: bool):
foo_1: Literal["foo"] = "foo"
bar_1: LiteralString = foo_1 # fine

foo_1: Literal["foo"] = "foo"
bar_1: LiteralString = foo_1 # fine
foo_2 = "foo" if flag else "bar"
reveal_type(foo_2) # revealed: Literal["foo", "bar"]
bar_2: LiteralString = foo_2 # fine

foo_2 = "foo" if coinflip() else "bar"
reveal_type(foo_2) # revealed: Literal["foo", "bar"]
bar_2: LiteralString = foo_2 # fine
foo_3: LiteralString = "foo" * 1_000_000_000
bar_3: str = foo_2 # fine

foo_3: LiteralString = "foo" * 1_000_000_000
bar_3: str = foo_2 # fine
baz_1: str = str()
qux_1: LiteralString = baz_1 # error: [invalid-assignment]

baz_1: str = str()
qux_1: LiteralString = baz_1 # error: [invalid-assignment]
baz_2: LiteralString = "baz" * 1_000_000_000
qux_2: Literal["qux"] = baz_2 # error: [invalid-assignment]

baz_2: LiteralString = "baz" * 1_000_000_000
qux_2: Literal["qux"] = baz_2 # error: [invalid-assignment]

baz_3 = "foo" if coinflip() else 1
reveal_type(baz_3) # revealed: Literal["foo"] | Literal[1]
qux_3: LiteralString = baz_3 # error: [invalid-assignment]
baz_3 = "foo" if flag else 1
reveal_type(baz_3) # revealed: Literal["foo"] | Literal[1]
qux_3: LiteralString = baz_3 # error: [invalid-assignment]
```

### Narrowing
Expand Down
146 changes: 51 additions & 95 deletions crates/red_knot_python_semantic/resources/mdtest/annotations/string.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,152 +3,109 @@
## Simple

```py
def f() -> "int":
return 1

reveal_type(f()) # revealed: int
def f(v: "int"):
reveal_type(v) # revealed: int
```

## Nested

```py
def f() -> "'int'":
return 1

reveal_type(f()) # revealed: int
def f(v: "'int'"):
reveal_type(v) # revealed: int
```

## Type expression

```py
def f1() -> "int | str":
return 1

def f2() -> "tuple[int, str]":
return 1

reveal_type(f1()) # revealed: int | str
reveal_type(f2()) # revealed: tuple[int, str]
def f1(v: "int | str", w: "tuple[int, str]"):
reveal_type(v) # revealed: int | str
reveal_type(w) # revealed: tuple[int, str]
```

## Partial

```py
def f() -> tuple[int, "str"]:
return 1

reveal_type(f()) # revealed: tuple[int, str]
def f(v: tuple[int, "str"]):
reveal_type(v) # revealed: tuple[int, str]
```

## Deferred

```py
def f() -> "Foo":
return Foo()

class Foo:
pass
def f(v: "Foo"):
reveal_type(v) # revealed: Foo

reveal_type(f()) # revealed: Foo
class Foo: ...
```

## Deferred (undefined)

```py
# error: [unresolved-reference]
def f() -> "Foo":
pass

reveal_type(f()) # revealed: Unknown
def f(v: "Foo"):
reveal_type(v) # revealed: Unknown
```

## Partial deferred

```py
def f() -> int | "Foo":
return 1

class Foo:
pass
def f(v: int | "Foo"):
reveal_type(v) # revealed: int | Foo

reveal_type(f()) # revealed: int | Foo
class Foo: ...
```

## `typing.Literal`

```py
from typing import Literal

def f1() -> Literal["Foo", "Bar"]:
return "Foo"

def f2() -> 'Literal["Foo", "Bar"]':
return "Foo"
def f1(v: Literal["Foo", "Bar"], w: 'Literal["Foo", "Bar"]'):
reveal_type(v) # revealed: Literal["Foo", "Bar"]
reveal_type(w) # revealed: Literal["Foo", "Bar"]

class Foo:
pass

reveal_type(f1()) # revealed: Literal["Foo", "Bar"]
reveal_type(f2()) # revealed: Literal["Foo", "Bar"]
class Foo: ...
```

## Various string kinds

```py
# error: [annotation-raw-string] "Type expressions cannot use raw string literal"
def f1() -> r"int":
return 1

# error: [annotation-f-string] "Type expressions cannot use f-strings"
def f2() -> f"int":
return 1

# error: [annotation-byte-string] "Type expressions cannot use bytes literal"
def f3() -> b"int":
return 1

def f4() -> "int":
return 1

# error: [annotation-implicit-concat] "Type expressions cannot span multiple string literals"
def f5() -> "in" "t":
return 1

# error: [annotation-escape-character] "Type expressions cannot contain escape characters"
def f6() -> "\N{LATIN SMALL LETTER I}nt":
return 1

# error: [annotation-escape-character] "Type expressions cannot contain escape characters"
def f7() -> "\x69nt":
return 1

def f8() -> """int""":
return 1

# error: [annotation-byte-string] "Type expressions cannot use bytes literal"
def f9() -> "b'int'":
return 1

reveal_type(f1()) # revealed: Unknown
reveal_type(f2()) # revealed: Unknown
reveal_type(f3()) # revealed: Unknown
reveal_type(f4()) # revealed: int
reveal_type(f5()) # revealed: Unknown
reveal_type(f6()) # revealed: Unknown
reveal_type(f7()) # revealed: Unknown
reveal_type(f8()) # revealed: int
reveal_type(f9()) # revealed: Unknown
def f1(
# error: [annotation-raw-string] "Type expressions cannot use raw string literal"
a: r"int",
# error: [annotation-f-string] "Type expressions cannot use f-strings"
b: f"int",
# error: [annotation-byte-string] "Type expressions cannot use bytes literal"
c: b"int",
d: "int",
# error: [annotation-implicit-concat] "Type expressions cannot span multiple string literals"
e: "in" "t",
# error: [annotation-escape-character] "Type expressions cannot contain escape characters"
f: "\N{LATIN SMALL LETTER I}nt",
# error: [annotation-escape-character] "Type expressions cannot contain escape characters"
g: "\x69nt",
h: """int""",
# error: [annotation-byte-string] "Type expressions cannot use bytes literal"
i: "b'int'",
):
reveal_type(a) # revealed: Unknown
reveal_type(b) # revealed: Unknown
reveal_type(c) # revealed: Unknown
reveal_type(d) # revealed: int
reveal_type(e) # revealed: Unknown
reveal_type(f) # revealed: Unknown
reveal_type(g) # revealed: Unknown
reveal_type(h) # revealed: int
reveal_type(i) # revealed: Unknown
```

## Various string kinds in `typing.Literal`

```py
from typing import Literal

def f() -> Literal["a", r"b", b"c", "d" "e", "\N{LATIN SMALL LETTER F}", "\x67", """h"""]:
return "normal"

reveal_type(f()) # revealed: Literal["a", "b", "de", "f", "g", "h"] | Literal[b"c"]
def f(v: Literal["a", r"b", b"c", "d" "e", "\N{LATIN SMALL LETTER F}", "\x67", """h"""]):
reveal_type(v) # revealed: Literal["a", "b", "de", "f", "g", "h"] | Literal[b"c"]
```

## Class variables
Expand All @@ -175,8 +132,7 @@ c: "Foo"
# error: [invalid-assignment] "Object of type `Literal[1]` is not assignable to `Foo`"
d: "Foo" = 1

class Foo:
pass
class Foo: ...

c = Foo()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,20 +78,10 @@ c: tuple[str | int, str] = ([], "foo")
## PEP-604 annotations are supported

```py
def foo() -> str | int | None:
return None

reveal_type(foo()) # revealed: str | int | None

def bar() -> str | str | None:
return None

reveal_type(bar()) # revealed: str | None

def baz() -> str | str:
return "Hello, world!"

reveal_type(baz()) # revealed: str
def foo(v: str | int | None, w: str | str | None, x: str | str):
reveal_type(v) # revealed: str | int | None
reveal_type(w) # revealed: str | None
reveal_type(x) # revealed: str
```

## Attribute expressions in type annotations are understood
Expand All @@ -118,8 +108,7 @@ from __future__ import annotations

x: Foo

class Foo:
pass
class Foo: ...

x = Foo()
reveal_type(x) # revealed: Foo
Expand All @@ -130,8 +119,7 @@ reveal_type(x) # revealed: Foo
```pyi path=main.pyi
x: Foo

class Foo:
pass
class Foo: ...

x = Foo()
reveal_type(x) # revealed: Foo
Expand Down
Loading

0 comments on commit 88d2fc3

Please sign in to comment.