diff options
Diffstat (limited to 'nodes.py')
-rw-r--r-- | nodes.py | 197 |
1 files changed, 0 insertions, 197 deletions
@@ -475,206 +475,9 @@ def real_name(node, asname): if asname == _asname: return name raise NotFoundError(asname) - From.real_name = real_name Import.real_name = real_name -def infer_name_module(node, name): - context = InferenceContext(node) - context.lookupname = name - return node.infer(context, asname=False) -Import.infer_name_module = infer_name_module - - -# special inference objects ################################################### - -class Yes(object): - """a yes object""" - def __repr__(self): - return 'YES' - def __getattribute__(self, name): - return self - def __call__(self, *args, **kwargs): - return self - -YES = Yes() - -class Proxy(Proxy_): - """a simple proxy object""" - _proxied = None - - def __init__(self, proxied=None): - if proxied is not None: - self._proxied = proxied - - def __getattr__(self, name): - if name == '_proxied': - return getattr(self.__class__, '_proxied') - if name in self.__dict__: - return self.__dict__[name] - return getattr(self._proxied, name) - - def infer(self, context=None): - yield self - - -class InstanceMethod(Proxy): - """a special node representing a function bound to an instance""" - def __repr__(self): - instance = self._proxied.parent.frame() - return '<Bound method %s of %s.%s at 0x%s' % (self._proxied.name, - instance.root().name, - instance.name, - id(self)) - __str__ = __repr__ - - def is_bound(self): - return True - - -class Instance(Proxy): - """a special node representing a class instance""" - def getattr(self, name, context=None, lookupclass=True): - try: - return self._proxied.instance_attr(name, context) - except NotFoundError: - if name == '__class__': - return [self._proxied] - if name == '__name__': - # access to __name__ gives undefined member on class - # instances but not on class objects - raise NotFoundError(name) - if lookupclass: - return self._proxied.getattr(name, context) - raise NotFoundError(name) - - def igetattr(self, name, context=None): - """infered getattr""" - try: - # XXX frame should be self._proxied, or not ? - return _infer_stmts( - self._wrap_attr(self.getattr(name, context, lookupclass=False)), - context, frame=self) - except NotFoundError: - try: - # fallback to class'igetattr since it has some logic to handle - # descriptors - return self._wrap_attr(self._proxied.igetattr(name, context)) - except NotFoundError: - raise InferenceError(name) - - def _wrap_attr(self, attrs): - """wrap bound methods of attrs in a InstanceMethod proxies""" - # Guess which attrs are used in inference. - def wrap(attr): - if isinstance(attr, Function) and attr.type == 'method': - return InstanceMethod(attr) - else: - return attr - return imap(wrap, attrs) - - def infer_call_result(self, caller, context=None): - """infer what's a class instance is returning when called""" - infered = False - for node in self._proxied.igetattr('__call__', context): - for res in node.infer_call_result(caller, context): - infered = True - yield res - if not infered: - raise InferenceError() - - def __repr__(self): - return '<Instance of %s.%s at 0x%s>' % (self._proxied.root().name, - self._proxied.name, - id(self)) - def __str__(self): - return 'Instance of %s.%s' % (self._proxied.root().name, - self._proxied.name) - - def callable(self): - try: - self._proxied.getattr('__call__') - return True - except NotFoundError: - return False - - def pytype(self): - return self._proxied.qname() - -class Generator(Proxy): - """a special node representing a generator""" - def callable(self): - return True - - def pytype(self): - return '__builtin__.generator' - -CONST_NAME_TRANSFORMS = {'None': (Const, None), - 'True': (Const, True), - 'False': (Const, False)} - - -# inference utilities ######################################################### - -class InferenceContext(object): - __slots__ = ('startingfrom', 'path', 'lookupname', 'callcontext', 'boundnode') - - def __init__(self, node=None, path=None): - self.startingfrom = node # XXX useful ? - if path is None: - self.path = [] - else: - self.path = path - self.lookupname = None - self.callcontext = None - self.boundnode = None - - def push(self, node): - name = self.lookupname - if (node, name) in self.path: - raise StopIteration() - self.path.append( (node, name) ) - - def pop(self): - return self.path.pop() - - def clone(self): - # XXX copy lookupname/callcontext ? - clone = InferenceContext(self.startingfrom, self.path) - clone.callcontext = self.callcontext - clone.boundnode = self.boundnode - return clone - - -def _infer_stmts(stmts, context, frame=None): - """return an iterator on statements infered by each statement in <stmts> - """ - stmt = None - infered = False - if context is not None: - name = context.lookupname - context = context.clone() - else: - name = None - context = InferenceContext() - for stmt in stmts: - if stmt is YES: - yield stmt - infered = True - continue - context.lookupname = stmt._infer_name(frame, name) - try: - for infered in stmt.infer(context): - yield infered - infered = True - except UnresolvableName: - continue - except InferenceError: - yield YES - infered = True - if not infered: - raise InferenceError(str(stmt)) - def repr_tree(node, indent='', _done=None): if _done is None: |