diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2018-03-05 11:17:35 +0100 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2018-03-10 10:02:48 +0100 |
commit | da26488c8f88e04b6157149a163384de8dd3f9cd (patch) | |
tree | fc0779d29fcde3f975043ca22aa88a92731b1afd /astroid/helpers.py | |
parent | 518e4a9dbff1ca041fa46a19c891a1d8a143f985 (diff) | |
download | astroid-git-da26488c8f88e04b6157149a163384de8dd3f9cd.tar.gz |
Add brain inference support for the `issubclass` builtin
This is in a similar vein with the `isinstance` builtin, with minor changes.
Diffstat (limited to 'astroid/helpers.py')
-rw-r--r-- | astroid/helpers.py | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/astroid/helpers.py b/astroid/helpers.py index d3522442..bce1a59f 100644 --- a/astroid/helpers.py +++ b/astroid/helpers.py @@ -116,6 +116,41 @@ def object_isinstance(node, class_or_seq, context=None): return False +def object_issubclass(node, class_or_seq, context=None): + """Check if a type is a subclass of any node in class_or_seq + + :param node: A given node + :param class_or_seq: Union[Nodes.NodeNG], Sequence[nodes.NodeNG]] + :rtype: bool + + :raises AstroidTypeError: if the given ``classes_or_seq`` are not types + :raises AstroidError: if the type of the given node cannot be inferred + or its type's mro doesn't work + """ + if not isinstance(class_or_seq, (tuple, list)): + class_seq = (class_or_seq,) + else: + class_seq = class_or_seq + + if not isinstance(node, nodes.ClassDef): + raise TypeError("{node} needs to be a ClassDef node".format(node=node)) + + # Instances are not types + class_seq = [item if not isinstance(item, bases.Instance) + else util.Uninferable for item in class_seq] + # strict compatibility with issubclass + # issubclass(int, (int, 1)) evaluates to true + # issubclass(int, (1, int)) raises TypeError + for klass in class_seq: + if klass is util.Uninferable: + raise exceptions.AstroidTypeError( + "issubclass() arg 2 must be a type or tuple of types") + for obj_subclass in node.mro(): + if obj_subclass == klass: + return True + return False + + def safe_infer(node, context=None): """Return the inferred value for the given node. |