Skip to content

Commit c92df4b

Browse files
committed
render literals better
1 parent c611db7 commit c92df4b

File tree

7 files changed

+36
-26
lines changed

7 files changed

+36
-26
lines changed

.mypy/baseline.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3726,7 +3726,7 @@
37263726
{
37273727
"code": "no-any-expr",
37283728
"column": 20,
3729-
"message": "Expression type contains \"Any\" (has type \"Literal[True] | str | Any | None\")",
3729+
"message": "Expression type contains \"Any\" (has type \"True | str | Any | None\")",
37303730
"offset": 1,
37313731
"target": "mypy.checkstrformat.StringFormatterChecker.check_specs_in_format_call"
37323732
},
@@ -5156,7 +5156,7 @@
51565156
{
51575157
"code": "no-any-expr",
51585158
"column": 24,
5159-
"message": "Expression type contains \"Any\" (has type \"Literal[False] | Any\")",
5159+
"message": "Expression type contains \"Any\" (has type \"False | Any\")",
51605160
"offset": 0,
51615161
"target": "mypy.config_parser.destructure_overrides"
51625162
},
@@ -11546,7 +11546,7 @@
1154611546
"code": "no-any-expr",
1154711547
"column": 30,
1154811548
"message": "Expression type contains \"Any\" (has type \"type[CallableType]\")",
11549-
"offset": 329,
11549+
"offset": 330,
1155011550
"target": "mypy.join.TypeJoinVisitor.visit_callable_type"
1155111551
},
1155211552
{
@@ -13460,7 +13460,7 @@
1346013460
"code": "no-any-expr",
1346113461
"column": 30,
1346213462
"message": "Expression type contains \"Any\" (has type \"type[CallableType]\")",
13463-
"offset": 272,
13463+
"offset": 277,
1346413464
"target": "mypy.messages.format_type_inner"
1346513465
},
1346613466
{
@@ -16472,7 +16472,7 @@
1647216472
{
1647316473
"code": "no-any-expr",
1647416474
"column": 20,
16475-
"message": "Expression type contains \"Any\" (has type \"Literal[True] | Any\")",
16475+
"message": "Expression type contains \"Any\" (has type \"True | Any\")",
1647616476
"offset": 2,
1647716477
"target": "mypy.semanal.SemanticAnalyzer._get_node_for_class_scoped_import"
1647816478
},
@@ -23263,7 +23263,7 @@
2326323263
{
2326423264
"code": "no-any-expr",
2326523265
"column": 11,
23266-
"message": "Expression type contains \"Any\" (has type \"Literal[False] | Untyped\")",
23266+
"message": "Expression type contains \"Any\" (has type \"False | Untyped\")",
2326723267
"offset": 107,
2326823268
"target": "mypy.test.testcheck.TypeCheckSuite.run_case_once"
2326923269
},
@@ -26694,7 +26694,7 @@
2669426694
"code": "no-any-expr",
2669526695
"column": 23,
2669626696
"message": "Expression type contains \"Any\" (has type \"type[CallableType]\")",
26697-
"offset": 95,
26697+
"offset": 97,
2669826698
"target": "mypy.types.strip_type"
2669926699
},
2670026700
{
@@ -32464,7 +32464,7 @@
3246432464
{
3246532465
"code": "no-any-expr",
3246632466
"column": 7,
32467-
"message": "Expression type contains \"Any\" (has type \"Literal[False] | Untyped\")",
32467+
"message": "Expression type contains \"Any\" (has type \"False | Untyped\")",
3246832468
"offset": 59,
3246932469
"target": "mypyc.test.testutil.assert_test_output"
3247032470
},

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## [Unreleased]
44
### Enhancements
55
- Unionize at type joins instead of common ancestor
6+
- Render Literal types better in output messages
67

78
## [1.4.0]
89
### Added

mypy/messages.py

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2252,8 +2252,13 @@ def format_literal_value(typ: LiteralType) -> str:
22522252
s = f"TypedDict({{{', '.join(items)}}})"
22532253
return s
22542254
elif isinstance(typ, LiteralType):
2255+
if mypy.options._based:
2256+
return format_literal_value(typ)
22552257
return f"Literal[{format_literal_value(typ)}]"
22562258
elif isinstance(typ, UnionType):
2259+
if mypy.options._based:
2260+
return " | ".join(format(item) for item in typ.items)
2261+
22572262
literal_items, union_items = separate_union_literals(typ)
22582263

22592264
# Coalesce multiple Literal[] members. This also changes output order.
@@ -2264,14 +2269,9 @@ def format_literal_value(typ: LiteralType) -> str:
22642269
)
22652270

22662271
if len(union_items) == 1 and isinstance(get_proper_type(union_items[0]), NoneType):
2267-
if mypy.options._based:
2268-
return f"{literal_str} | None"
2269-
else:
2270-
return f"Optional[{literal_str}]"
2272+
return f"Optional[{literal_str}]"
22712273
elif union_items:
2272-
if not mypy.options._based:
2273-
return f"Union[{format_list(union_items)}, {literal_str}]"
2274-
return f"{format_union(union_items)} | {literal_str}"
2274+
return f"Union[{format_list(union_items)}, {literal_str}]"
22752275
else:
22762276
return literal_str
22772277
else:
@@ -2282,15 +2282,9 @@ def format_literal_value(typ: LiteralType) -> str:
22822282
)
22832283
if print_as_optional:
22842284
rest = [t for t in typ.items if not isinstance(get_proper_type(t), NoneType)]
2285-
if mypy.options._based:
2286-
return f"{format(rest[0])} | None"
2287-
else:
2288-
return f"Optional[{format(rest[0])}]"
2285+
return f"Optional[{format(rest[0])}]"
22892286
else:
2290-
if mypy.options._based:
2291-
s = format_union(typ.items)
2292-
else:
2293-
s = f"Union[{format_list(typ.items)}]"
2287+
s = f"Union[{format_list(typ.items)}]"
22942288

22952289
return s
22962290
elif isinstance(typ, NoneType):

mypy/types.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3104,6 +3104,8 @@ def visit_raw_expression_type(self, t: RawExpressionType) -> str:
31043104
return repr(t.literal_value)
31053105

31063106
def visit_literal_type(self, t: LiteralType) -> str:
3107+
if mypy.options._based:
3108+
return t.value_repr()
31073109
return f"Literal[{t.value_repr()}]"
31083110

31093111
def visit_star_type(self, t: StarType) -> str:

test-data/unit/check-based-type-render.test

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,16 @@ a: list
2323
reveal_type(a) # N: Revealed type is "list[Untyped]"
2424
b: List[Any]
2525
reveal_type(b) # N: Revealed type is "list[Any]"
26+
27+
28+
[case testRenderBareLiterals]
29+
# flags: --python-version 3.10
30+
from typing import Literal
31+
32+
a: Literal['1'] = 2 # E: Incompatible types in assignment (expression has type "2", variable has type "'1'") [assignment]
33+
reveal_type(a) # N: Revealed type is "'1'"
34+
b: Literal[1, 2, 3] = 4 # E: Incompatible types in assignment (expression has type "4", variable has type "1 | 2 | 3") [assignment]
35+
reveal_type(b) # N: Revealed type is "1 | 2 | 3"
36+
c: Literal[1, 2, 3] | str = 4 # E: Incompatible types in assignment (expression has type "4", variable has type "1 | 2 | 3 | str") [assignment]
37+
reveal_type(c) # N: Revealed type is "1 | 2 | 3 | str"
38+
[typing fixtures/typing-medium.pyi]

test-data/unit/fixtures/tuple.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,6 @@ class list(Sequence[T], Generic[T]):
4343

4444
def isinstance(x: object, t: type) -> bool: pass
4545

46-
def sum(iterable: Iterable[T], start: T = ...) -> T: pass
46+
def sum(iterable: Iterable[T], start: T = None) -> T: pass # type: ignore[assignment, unused-ignore]
4747

4848
class BaseException: pass

test-data/unit/fixtures/typing-medium.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class Generator(Iterator[T], Generic[T, U, V]):
5252
def __iter__(self) -> 'Generator[T, U, V]': pass
5353

5454
class Sequence(Iterable[T_co]):
55-
def __getitem__(self, n: Any) -> T_co: pass
55+
def __getitem__(self, n: Any) -> T_co: pass # type: ignore[no-any-explicit, unused-ignore]
5656

5757
class Mapping(Iterable[T], Generic[T, T_co]):
5858
def __getitem__(self, key: T) -> T_co: pass
@@ -66,6 +66,6 @@ class SupportsFloat(Protocol):
6666
class ContextManager(Generic[T]):
6767
def __enter__(self) -> T: pass
6868
# Use Any because not all the precise types are in the fixtures.
69-
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> Any: pass
69+
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> Any: pass # type: ignore[no-any-explicit, unused-ignore]
7070

7171
TYPE_CHECKING = 1

0 commit comments

Comments
 (0)