summaryrefslogtreecommitdiff
path: root/astroid/helpers.py
diff options
context:
space:
mode:
authorClaudiu Popa <cpopa@cloudbasesolutions.com>2015-06-24 15:08:56 +0300
committerClaudiu Popa <cpopa@cloudbasesolutions.com>2015-06-24 15:08:56 +0300
commit51a41665cf0214f64869654afe1fe31385c20e3f (patch)
tree0eae51de3048d0d38b9176c7e2da0b55d7941496 /astroid/helpers.py
parent893bcc5d6e063e512e320122559703e4c1b15811 (diff)
downloadastroid-git-51a41665cf0214f64869654afe1fe31385c20e3f.tar.gz
Add astroid.helpers, a module of various useful utilities which don't belong yet into other components.
Added *object_type*, a function which can be used to obtain the type of almost any astroid object, similar to how the builtin *type* works.
Diffstat (limited to 'astroid/helpers.py')
-rw-r--r--astroid/helpers.py95
1 files changed, 95 insertions, 0 deletions
diff --git a/astroid/helpers.py b/astroid/helpers.py
new file mode 100644
index 00000000..5996c7c7
--- /dev/null
+++ b/astroid/helpers.py
@@ -0,0 +1,95 @@
+# 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/>.
+
+"""
+Various helper utilities.
+"""
+
+import six
+
+from astroid import bases
+from astroid import exceptions
+from astroid import manager
+from astroid import raw_building
+from astroid import scoped_nodes
+
+
+BUILTINS = six.moves.builtins.__name__
+
+
+def _build_proxy_class(cls_name, builtins):
+ proxy = raw_building.build_class(cls_name)
+ proxy.parent = builtins
+ return proxy
+
+
+def _function_type(function, builtins):
+ if isinstance(function, scoped_nodes.Lambda):
+ if function.root().name == BUILTINS:
+ cls_name = 'builtin_function_or_method'
+ else:
+ cls_name = 'function'
+ elif isinstance(function, bases.BoundMethod):
+ if six.PY2:
+ cls_name = 'instancemethod'
+ else:
+ cls_name = 'method'
+ elif isinstance(function, bases.UnboundMethod):
+ if six.PY2:
+ cls_name = 'instancemethod'
+ else:
+ cls_name = 'function'
+ return _build_proxy_class(cls_name, builtins)
+
+
+def _object_type(node, context=None):
+ astroid_manager = manager.AstroidManager()
+ builtins = astroid_manager.astroid_cache[BUILTINS]
+ context = context or bases.InferenceContext()
+
+ for inferred in node.infer(context=context):
+ if isinstance(inferred, scoped_nodes.Class):
+ if inferred.newstyle:
+ metaclass = inferred.metaclass()
+ if metaclass:
+ yield metaclass
+ continue
+ yield builtins.getattr('type')[0]
+ elif isinstance(inferred, (scoped_nodes.Lambda, bases.UnboundMethod)):
+ yield _function_type(inferred, builtins)
+ elif isinstance(inferred, scoped_nodes.Module):
+ yield _build_proxy_class('module', builtins)
+ else:
+ yield inferred._proxied
+
+
+def object_type(node, context=None):
+ """Obtain the type of the given node
+
+ The node will be inferred first, so this function can support all
+ sorts of objects, as long as they support inference. It will try to
+ retrieve the Python type, as returned by the builtin `type`.
+ """
+
+ try:
+ types = set(_object_type(node, context))
+ except exceptions.InferenceError:
+ return bases.YES
+ if len(types) > 1:
+ return bases.YES
+ return list(types)[0]