diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2014-05-07 17:14:48 +0300 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2014-05-07 17:14:48 +0300 |
commit | cd08d8724ec41f4630b143a62f0d4e5479ab0607 (patch) | |
tree | 436e1040e9de8e5f9f4dc58aa72dce1811deac9a /scoped_nodes.py | |
parent | b13ef13e8365348b957e77105fdeeeb5bde69c49 (diff) | |
download | astroid-git-cd08d8724ec41f4630b143a62f0d4e5479ab0607.tar.gz |
Function nodes can detect if they are decorated with subclasses of builtin descriptors when determining their type (`classmethod` and `staticmethod`).
--HG--
branch : classmethod_subclasses
Diffstat (limited to 'scoped_nodes.py')
-rw-r--r-- | scoped_nodes.py | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/scoped_nodes.py b/scoped_nodes.py index 20bb664f..889baa0e 100644 --- a/scoped_nodes.py +++ b/scoped_nodes.py @@ -31,13 +31,13 @@ except ImportError: from cStringIO import StringIO as BytesIO from logilab.common.compat import builtins -from logilab.common.decorators import cached +from logilab.common.decorators import cached, cachedproperty from astroid.exceptions import NotFoundError, \ AstroidBuildingException, InferenceError from astroid.node_classes import Const, DelName, DelAttr, \ Dict, From, List, Pass, Raise, Return, Tuple, Yield, YieldFrom, \ - LookupMixIn, const_factory as cf, unpack_infer + LookupMixIn, const_factory as cf, unpack_infer, Name from astroid.bases import NodeNG, InferenceContext, Instance,\ YES, Generator, UnboundMethod, BoundMethod, _infer_stmts, copy_context, \ BUILTINS @@ -476,6 +476,34 @@ else: """class representing a ListComp node""" # Function ################################################################### + +def _function_type(self): + """ + Function type, possible values are: + method, function, staticmethod, classmethod. + """ + # Can't infer that this node is decorated + # with a subclass of `classmethod` where `type` is first set, + # so do it here. + if self.decorators: + for node in self.decorators.nodes: + if not isinstance(node, Name): + continue + try: + for infered in node.infer(): + if not isinstance(infered, Class): + continue + for ancestor in infered.ancestors(): + if isinstance(ancestor, Class): + if (ancestor.name == 'classmethod' and + ancestor.root().name == BUILTINS): + return 'classmethod' + elif (ancestor.name == 'staticmethod' and + ancestor.root().name == BUILTINS): + return 'staticmethod' + except InferenceError: + pass + return self._type class Lambda(LocalsDictNodeNG, FilterStmtsMixin): @@ -539,6 +567,8 @@ class Function(Statement, Lambda): # attributes below are set by the builder module or by raw factories blockstart_tolineno = None decorators = None + _type = "function" + type = cachedproperty(_function_type) def __init__(self, name, doc): self.locals = {} |