Skip to content

Commit f184c8a

Browse files
committed
Adds doc
1 parent c89ccb7 commit f184c8a

File tree

2 files changed

+45
-9
lines changed

2 files changed

+45
-9
lines changed

astroid/brain/brain_type.py

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,21 @@
11
# -*- coding: utf-8 -*-
2+
"""
3+
Astroid hooks for type support.
4+
5+
Starting from python3.9, type object behaves as it had __class_getitem__ method.
6+
However it was not possible to simply add this method inside type's body, otherwise
7+
all types would also have this method. In this case it would have been possible
8+
to write str[int].
9+
Guido Van Rossum proposed a hack to handle this in the interpreter:
10+
https://github.com/python/cpython/blob/master/Objects/abstract.c#L186-L189
11+
12+
This brain follows the same logic. It is no wise to add permanently the __class_getitem__ method
13+
to the type object. Instead we choose to add it only in the case of a subscript node
14+
which inside name node is type.
15+
Doing this type[int] is allowed whereas str[int] is not.
16+
17+
Thanks to Lukasz Langa for fruitful discussion.
18+
"""
219
import sys
320

421
from astroid import (
@@ -10,20 +27,30 @@
1027

1128

1229
def _looks_like_type_subscript(node):
13-
"""Try to figure out if a Subscript node *might* be a typing-related subscript"""
14-
if isinstance(node, nodes.Name):
30+
"""
31+
Try to figure out if a Name node is used inside a type related subscript
32+
33+
:param node: node to check
34+
:type node: nodes.Name
35+
:return: true if the node is a Name node inside a type related subscript
36+
:rtype: bool
37+
"""
38+
if isinstance(node, nodes.Name) and isinstance(node.parent, nodes.Subscript):
1539
return node.name == "type"
16-
if isinstance(node, nodes.Subscript):
17-
if isinstance(node.value, Name) and node.value.name == "type":
18-
return True
1940
return False
2041

2142

2243
def infer_type_sub(node, context=None):
23-
"""Infer a typing.X[...] subscript"""
24-
sub_node = node.parent
25-
if not isinstance(sub_node, nodes.Subscript):
26-
raise UseInferenceDefault
44+
"""
45+
Infer a type[...] subscript
46+
47+
:param node: node to infer
48+
:type node: astroid.node_classes.NodeNG
49+
:param context: inference context
50+
:type context: astroid.context.InferenceContext
51+
:return: the inferred node
52+
:rtype: nodes.NodeNG
53+
"""
2754
class_src = """
2855
class type:
2956
def __class_getitem__(cls, key):

tests/unittest_brain.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,10 @@ def test_sys_streams(self):
940940
@test_utils.require_version("3.9")
941941
class TypeBrain(unittest.TestCase):
942942
def test_type_subscript(self):
943+
"""
944+
Check that type object has the __class_getitem__ method
945+
when it is used as a subscript
946+
"""
943947
src = builder.extract_node(
944948
"""
945949
a: type[int] = int
@@ -952,6 +956,11 @@ def test_type_subscript(self):
952956
self.assertIsInstance(meth_inf, astroid.FunctionDef)
953957

954958
def test_invalid_type_subscript(self):
959+
"""
960+
Check that a type (str for example) that inherits
961+
from type does not have __class_getitem__ method even
962+
when it is used as a subscript
963+
"""
955964
src = builder.extract_node(
956965
"""
957966
a: str[int] = "abc"

0 commit comments

Comments
 (0)