diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2018-03-05 11:47:22 +0100 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2018-03-10 10:02:48 +0100 |
commit | 6ed8cb3a612f28da94664642aeed47d6a67202a4 (patch) | |
tree | bab8a952013d1cc2240e50827de5f133fb114caf /astroid/helpers.py | |
parent | da26488c8f88e04b6157149a163384de8dd3f9cd (diff) | |
download | astroid-git-6ed8cb3a612f28da94664642aeed47d6a67202a4.tar.gz |
Rewrite the object_isinstance and object_issubclass helpers to rely on common code
Diffstat (limited to 'astroid/helpers.py')
-rw-r--r-- | astroid/helpers.py | 58 |
1 files changed, 23 insertions, 35 deletions
diff --git a/astroid/helpers.py b/astroid/helpers.py index bce1a59f..21f7445f 100644 --- a/astroid/helpers.py +++ b/astroid/helpers.py @@ -83,39 +83,46 @@ def object_type(node, context=None): return list(types)[0] -def object_isinstance(node, class_or_seq, context=None): - """Check if a node 'isinstance' 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 - """ +def _object_type_is_subclass(obj_type, class_or_seq, context=None): if not isinstance(class_or_seq, (tuple, list)): class_seq = (class_or_seq,) else: class_seq = class_or_seq - obj_type = object_type(node, context) + if obj_type is util.Uninferable: return util.Uninferable # Instances are not types class_seq = [item if not isinstance(item, bases.Instance) else util.Uninferable for item in class_seq] - # strict compatibility with isinstance - # isinstance(1, (int, 1)) evaluates to true - # isinstance(1, (1, int)) raises TypeError + # strict compatibility with issubclass + # issubclass(1, (int, 1)) evaluates to true + # issubclass(1, (1, int)) raises TypeError for klass in class_seq: if klass is util.Uninferable: - raise exceptions.AstroidTypeError( - "isinstance() arg 2 must be a type or tuple of types") + raise exceptions.AstroidTypeError("arg 2 must be a type or tuple of types") + for obj_subclass in obj_type.mro(): if obj_subclass == klass: return True return False +def object_isinstance(node, class_or_seq, context=None): + """Check if a node 'isinstance' 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 + """ + obj_type = object_type(node, context) + if obj_type is util.Uninferable: + return util.Uninferable + return _object_type_is_subclass(obj_type, class_or_seq, context=context) + + def object_issubclass(node, class_or_seq, context=None): """Check if a type is a subclass of any node in class_or_seq @@ -127,28 +134,9 @@ def object_issubclass(node, class_or_seq, context=None): :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 + return _object_type_is_subclass(node, class_or_seq, context=context) def safe_infer(node, context=None): |