diff options
author | Claudiu Popa <cpopa@cloudbasesolutions.com> | 2015-06-26 22:50:55 +0300 |
---|---|---|
committer | Claudiu Popa <cpopa@cloudbasesolutions.com> | 2015-06-26 22:50:55 +0300 |
commit | e067d1526985ded7f64b12e0c4c277f700d0ca43 (patch) | |
tree | 2f4b5aeb2b78b54b422f1f7d10183897f379b9aa /astroid/helpers.py | |
parent | c3769fe82efadc93e691fda1235533734c3080a2 (diff) | |
download | astroid-git-e067d1526985ded7f64b12e0c4c277f700d0ca43.tar.gz |
Add helpers.is_supertype and helpers.is_subtype, two functions for checking if an object is a super/sub type of another.
Diffstat (limited to 'astroid/helpers.py')
-rw-r--r-- | astroid/helpers.py | 93 |
1 files changed, 77 insertions, 16 deletions
diff --git a/astroid/helpers.py b/astroid/helpers.py index 5996c7c7..fa941d94 100644 --- a/astroid/helpers.py +++ b/astroid/helpers.py @@ -1,19 +1,19 @@ -# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along +# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of astroid.
+#
+# astroid is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 2.1 of the License, or (at your
+# option) any later version.
+#
+# astroid is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see <http://www.gnu.org/licenses/>.
"""
@@ -93,3 +93,64 @@ def object_type(node, context=None): if len(types) > 1:
return bases.YES
return list(types)[0]
+
+
+def safe_infer(node, context=None):
+ """Return the inferred value for the given node.
+
+ Return None if inference failed or if there is some ambiguity (more than
+ one node has been inferred).
+ """
+ try:
+ inferit = node.infer(context=context)
+ value = next(inferit)
+ except exceptions.InferenceError:
+ return
+ try:
+ next(inferit)
+ return # None if there is ambiguity on the inferred node
+ except exceptions.InferenceError:
+ return # there is some kind of ambiguity
+ except StopIteration:
+ return value
+
+
+def has_known_bases(klass, context=None):
+ """Return true if all base classes of a class could be inferred."""
+ try:
+ return klass._all_bases_known
+ except AttributeError:
+ pass
+ for base in klass.bases:
+ result = safe_infer(base, context=context)
+ # TODO: check for A->B->A->B pattern in class structure too?
+ if (not isinstance(result, scoped_nodes.Class) or
+ result is klass or
+ not has_known_bases(result, context=context)):
+ klass._all_bases_known = False
+ return False
+ klass._all_bases_known = True
+ return True
+
+
+def _type_check(type1, type2):
+ if not all(map(has_known_bases, (type1, type2))):
+ return bases.YES
+
+ if not all([type1.newstyle, type2.newstyle]):
+ return False
+ try:
+ return type1 in type2.mro()[:-1]
+ except exceptions.MroError:
+ # The MRO is invalid.
+ return bases.YES
+
+
+def is_subtype(type1, type2):
+ """Check if *type1* is a subtype of *typ2*."""
+ return _type_check(type2, type1)
+
+
+def is_supertype(type1, type2):
+ """Check if *type2* is a supertype of *type1*."""
+ return _type_check(type1, type2)
|