diff options
author | hippo91 <guillaume.peillex@gmail.com> | 2021-01-19 20:46:30 +0100 |
---|---|---|
committer | hippo91 <guillaume.peillex@gmail.com> | 2021-01-19 20:46:30 +0100 |
commit | f184c8af7581b6d1c56270f1eb66254175978595 (patch) | |
tree | 270051e58f9b62b3febf4db1c2d15645e7281af0 | |
parent | c89ccb7396e89557925ab2972611b93367f400c3 (diff) | |
download | astroid-git-f184c8af7581b6d1c56270f1eb66254175978595.tar.gz |
Adds doc
-rw-r--r-- | astroid/brain/brain_type.py | 45 | ||||
-rw-r--r-- | tests/unittest_brain.py | 9 |
2 files changed, 45 insertions, 9 deletions
diff --git a/astroid/brain/brain_type.py b/astroid/brain/brain_type.py index f32c6c77..951d6bf3 100644 --- a/astroid/brain/brain_type.py +++ b/astroid/brain/brain_type.py @@ -1,4 +1,21 @@ # -*- coding: utf-8 -*- +""" +Astroid hooks for type support. + +Starting from python3.9, type object behaves as it had __class_getitem__ method. +However it was not possible to simply add this method inside type's body, otherwise +all types would also have this method. In this case it would have been possible +to write str[int]. +Guido Van Rossum proposed a hack to handle this in the interpreter: +https://github.com/python/cpython/blob/master/Objects/abstract.c#L186-L189 + +This brain follows the same logic. It is no wise to add permanently the __class_getitem__ method +to the type object. Instead we choose to add it only in the case of a subscript node +which inside name node is type. +Doing this type[int] is allowed whereas str[int] is not. + +Thanks to Lukasz Langa for fruitful discussion. +""" import sys from astroid import ( @@ -10,20 +27,30 @@ from astroid import ( def _looks_like_type_subscript(node): - """Try to figure out if a Subscript node *might* be a typing-related subscript""" - if isinstance(node, nodes.Name): + """ + Try to figure out if a Name node is used inside a type related subscript + + :param node: node to check + :type node: nodes.Name + :return: true if the node is a Name node inside a type related subscript + :rtype: bool + """ + if isinstance(node, nodes.Name) and isinstance(node.parent, nodes.Subscript): return node.name == "type" - if isinstance(node, nodes.Subscript): - if isinstance(node.value, Name) and node.value.name == "type": - return True return False def infer_type_sub(node, context=None): - """Infer a typing.X[...] subscript""" - sub_node = node.parent - if not isinstance(sub_node, nodes.Subscript): - raise UseInferenceDefault + """ + Infer a type[...] subscript + + :param node: node to infer + :type node: astroid.node_classes.NodeNG + :param context: inference context + :type context: astroid.context.InferenceContext + :return: the inferred node + :rtype: nodes.NodeNG + """ class_src = """ class type: def __class_getitem__(cls, key): diff --git a/tests/unittest_brain.py b/tests/unittest_brain.py index 0190ed3f..443fcb49 100644 --- a/tests/unittest_brain.py +++ b/tests/unittest_brain.py @@ -940,6 +940,10 @@ class IOBrainTest(unittest.TestCase): @test_utils.require_version("3.9") class TypeBrain(unittest.TestCase): def test_type_subscript(self): + """ + Check that type object has the __class_getitem__ method + when it is used as a subscript + """ src = builder.extract_node( """ a: type[int] = int @@ -952,6 +956,11 @@ class TypeBrain(unittest.TestCase): self.assertIsInstance(meth_inf, astroid.FunctionDef) def test_invalid_type_subscript(self): + """ + Check that a type (str for example) that inherits + from type does not have __class_getitem__ method even + when it is used as a subscript + """ src = builder.extract_node( """ a: str[int] = "abc" |