summaryrefslogtreecommitdiff
path: root/astroid/helpers.py
diff options
context:
space:
mode:
Diffstat (limited to 'astroid/helpers.py')
-rw-r--r--astroid/helpers.py35
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.