Skip to content

Commit 116f27d

Browse files
authored
Merge branch 'master' into issue-17117
2 parents d49339a + ba6febc commit 116f27d

File tree

9 files changed

+73
-20
lines changed

9 files changed

+73
-20
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ jobs:
7474
- name: mypyc runtime tests with py39-macos
7575
python: '3.9.18'
7676
arch: x64
77-
os: macos-latest
77+
# TODO: macos-13 is the last one to support Python 3.9, change it to macos-latest when updating the Python version
78+
os: macos-13
7879
toxenv: py
7980
tox_extra_args: "-n 2 mypyc/test/test_run.py mypyc/test/test_external.py"
8081
- name: mypyc runtime tests with py38-debug-build-ubuntu

docs/source/common_issues.rst

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ once you add annotations:
4141
4242
def foo(a: str) -> str:
4343
return '(' + a.split() + ')'
44-
# error: Unsupported operand types for + ("str" and List[str])
44+
# error: Unsupported operand types for + ("str" and "list[str]")
4545
4646
If you don't know what types to add, you can use ``Any``, but beware:
4747

@@ -226,7 +226,7 @@ dict to a new variable, as mentioned earlier:
226226

227227
.. code-block:: python
228228
229-
a: List[int] = []
229+
a: list[int] = []
230230
231231
Without the annotation mypy can't always figure out the
232232
precise type of ``a``.
@@ -238,7 +238,7 @@ modification operation in the same scope (such as ``append`` for a list):
238238

239239
.. code-block:: python
240240
241-
a = [] # Okay because followed by append, inferred type List[int]
241+
a = [] # Okay because followed by append, inferred type list[int]
242242
for i in range(n):
243243
a.append(i * i)
244244
@@ -276,7 +276,7 @@ not support ``sort()``) as a list and sort it in-place:
276276
def f(x: Sequence[int]) -> None:
277277
# Type of x is Sequence[int] here; we don't know the concrete type.
278278
x = list(x)
279-
# Type of x is List[int] here.
279+
# Type of x is list[int] here.
280280
x.sort() # Okay!
281281
282282
See :ref:`type-narrowing` for more information.
@@ -296,8 +296,8 @@ unexpected errors when combined with type inference. For example:
296296
class A: ...
297297
class B(A): ...
298298
299-
lst = [A(), A()] # Inferred type is List[A]
300-
new_lst = [B(), B()] # inferred type is List[B]
299+
lst = [A(), A()] # Inferred type is list[A]
300+
new_lst = [B(), B()] # inferred type is list[B]
301301
lst = new_lst # mypy will complain about this, because List is invariant
302302
303303
Possible strategies in such situations are:
@@ -306,7 +306,7 @@ Possible strategies in such situations are:
306306

307307
.. code-block:: python
308308
309-
new_lst: List[A] = [B(), B()]
309+
new_lst: list[A] = [B(), B()]
310310
lst = new_lst # OK
311311
312312
* Make a copy of the right hand side:
@@ -319,7 +319,7 @@ Possible strategies in such situations are:
319319

320320
.. code-block:: python
321321
322-
def f_bad(x: List[A]) -> A:
322+
def f_bad(x: list[A]) -> A:
323323
return x[0]
324324
f_bad(new_lst) # Fails
325325
@@ -489,7 +489,7 @@ understand how mypy handles a particular piece of code. Example:
489489

490490
.. code-block:: python
491491
492-
reveal_type((1, 'hello')) # Revealed type is "Tuple[builtins.int, builtins.str]"
492+
reveal_type((1, 'hello')) # Revealed type is "tuple[builtins.int, builtins.str]"
493493
494494
You can also use ``reveal_locals()`` at any line in a file
495495
to see the types of all local variables at once. Example:
@@ -622,16 +622,16 @@ instructions at the `mypyc wheels repo <https://github.com/mypyc/mypy_mypyc-whee
622622
Variables vs type aliases
623623
-------------------------
624624

625-
Mypy has both *type aliases* and variables with types like ``Type[...]``. These are
625+
Mypy has both *type aliases* and variables with types like ``type[...]``. These are
626626
subtly different, and it's important to understand how they differ to avoid pitfalls.
627627

628-
1. A variable with type ``Type[...]`` is defined using an assignment with an
628+
1. A variable with type ``type[...]`` is defined using an assignment with an
629629
explicit type annotation:
630630

631631
.. code-block:: python
632632
633633
class A: ...
634-
tp: Type[A] = A
634+
tp: type[A] = A
635635
636636
2. You can define a type alias using an assignment without an explicit type annotation
637637
at the top level of a module:
@@ -670,7 +670,7 @@ can't be defined conditionally (unless using
670670
# explicit "Type[...]" annotation
671671
Alias = B
672672
673-
tp: Type[object] # "tp" is a variable with a type object value
673+
tp: type[object] # "tp" is a variable with a type object value
674674
if random() > 0.5:
675675
tp = A
676676
else:

mypy/build.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2850,10 +2850,14 @@ def skipping_ancestor(manager: BuildManager, id: str, path: str, ancestor_for: S
28502850
def log_configuration(manager: BuildManager, sources: list[BuildSource]) -> None:
28512851
"""Output useful configuration information to LOG and TRACE"""
28522852

2853+
config_file = manager.options.config_file
2854+
if config_file:
2855+
config_file = os.path.abspath(config_file)
2856+
28532857
manager.log()
28542858
configuration_vars = [
28552859
("Mypy Version", __version__),
2856-
("Config File", (manager.options.config_file or "Default")),
2860+
("Config File", (config_file or "Default")),
28572861
("Configured Executable", manager.options.python_executable or "None"),
28582862
("Current Executable", sys.executable),
28592863
("Cache Dir", manager.options.cache_dir),

mypy/checkmember.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,8 +1139,8 @@ def analyze_enum_class_attribute_access(
11391139
# Skip these since Enum will remove it
11401140
if name in ENUM_REMOVED_PROPS:
11411141
return report_missing_attribute(mx.original_type, itype, name, mx)
1142-
# For other names surrendered by underscores, we don't make them Enum members
1143-
if name.startswith("__") and name.endswith("__") and name.replace("_", "") != "":
1142+
# Dunders and private names are not Enum members
1143+
if name.startswith("__") and name.replace("_", "") != "":
11441144
return None
11451145

11461146
enum_literal = LiteralType(name, fallback=itype)

mypy/semanal.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3979,7 +3979,12 @@ def analyze_name_lvalue(
39793979
existing = names.get(name)
39803980

39813981
outer = self.is_global_or_nonlocal(name)
3982-
if kind == MDEF and isinstance(self.type, TypeInfo) and self.type.is_enum:
3982+
if (
3983+
kind == MDEF
3984+
and isinstance(self.type, TypeInfo)
3985+
and self.type.is_enum
3986+
and not name.startswith("__")
3987+
):
39833988
# Special case: we need to be sure that `Enum` keys are unique.
39843989
if existing is not None and not isinstance(existing.node, PlaceholderNode):
39853990
self.fail(

mypy/typeanal.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,12 @@ def analyze_unbound_type_without_type_info(
868868
# If, in the distant future, we decide to permit things like
869869
# `def foo(x: Color.RED) -> None: ...`, we can remove that
870870
# check entirely.
871-
if isinstance(sym.node, Var) and sym.node.info and sym.node.info.is_enum:
871+
if (
872+
isinstance(sym.node, Var)
873+
and sym.node.info
874+
and sym.node.info.is_enum
875+
and not sym.node.name.startswith("__")
876+
):
872877
value = sym.node.name
873878
base_enum_short_name = sym.node.info.name
874879
if not defining_literal:

mypy/typeops.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,9 @@ class Status(Enum):
885885
# Skip these since Enum will remove it
886886
if name in ENUM_REMOVED_PROPS:
887887
continue
888+
# Skip private attributes
889+
if name.startswith("__"):
890+
continue
888891
new_items.append(LiteralType(name, typ))
889892
return make_simplified_union(new_items, contract_literals=False)
890893
elif typ.type.fullname == "builtins.bool":

test-data/unit/check-enum.test

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,10 @@ from enum import Enum
14251425
class Correct(Enum):
14261426
x = 'y'
14271427
y = 'x'
1428+
class Correct2(Enum):
1429+
x = 'y'
1430+
__z = 'y'
1431+
__z = 'x'
14281432
class Foo(Enum):
14291433
A = 1
14301434
A = 'a' # E: Attempted to reuse member name "A" in Enum definition "Foo" \
@@ -2105,3 +2109,32 @@ class AllPartialList(Enum):
21052109

21062110
def check(self) -> None:
21072111
reveal_type(self.value) # N: Revealed type is "builtins.list[Any]"
2112+
2113+
[case testEnumPrivateAttributeNotMember]
2114+
from enum import Enum
2115+
2116+
class MyEnum(Enum):
2117+
A = 1
2118+
B = 2
2119+
__my_dict = {A: "ham", B: "spam"}
2120+
2121+
# TODO: change the next line to use MyEnum._MyEnum__my_dict when mypy implements name mangling
2122+
x: MyEnum = MyEnum.__my_dict # E: Incompatible types in assignment (expression has type "Dict[int, str]", variable has type "MyEnum")
2123+
2124+
[case testEnumWithPrivateAttributeReachability]
2125+
# flags: --warn-unreachable
2126+
from enum import Enum
2127+
2128+
class MyEnum(Enum):
2129+
A = 1
2130+
B = 2
2131+
__my_dict = {A: "ham", B: "spam"}
2132+
2133+
e: MyEnum
2134+
if e == MyEnum.A:
2135+
reveal_type(e) # N: Revealed type is "Literal[__main__.MyEnum.A]"
2136+
elif e == MyEnum.B:
2137+
reveal_type(e) # N: Revealed type is "Literal[__main__.MyEnum.B]"
2138+
else:
2139+
reveal_type(e) # E: Statement is unreachable
2140+
[builtins fixtures/dict.pyi]

test-data/unit/check-literal.test

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2503,7 +2503,7 @@ class Color(Enum):
25032503
RED = 1
25042504
GREEN = 2
25052505
BLUE = 3
2506-
2506+
__ROUGE = RED
25072507
def func(self) -> int: pass
25082508

25092509
r: Literal[Color.RED]
@@ -2512,6 +2512,8 @@ b: Literal[Color.BLUE]
25122512
bad1: Literal[Color] # E: Parameter 1 of Literal[...] is invalid
25132513
bad2: Literal[Color.func] # E: Parameter 1 of Literal[...] is invalid
25142514
bad3: Literal[Color.func()] # E: Invalid type: Literal[...] cannot contain arbitrary expressions
2515+
# TODO: change the next line to use Color._Color__ROUGE when mypy implements name mangling
2516+
bad4: Literal[Color.__ROUGE] # E: Parameter 1 of Literal[...] is invalid
25152517

25162518
def expects_color(x: Color) -> None: pass
25172519
def expects_red(x: Literal[Color.RED]) -> None: pass

0 commit comments

Comments
 (0)