Inference on the AST in Astroid

Introduction

What/where is ‘inference’ ?

Well, not inference in general, but inference within astroid in particular... Basically this is extracting information about a node of the AST from the node’s context so as to make its description richer. For example it can be most useful to know that this identifier node toto can have values among 1, 2.0, and “yesterday”.

The inference process entry-point is the NodeNG.infer() method of the AST nodes which is defined in NodeNG the base class for AST nodes. This method return a generator which yields the successive inference for the node when going through the possible execution branches.

How does it work ?

Todo

double check this infer() is monkey-patched point

The NodeNG.infer() method either delegates the actual inference to the instance specific method NodeNG._explicit_inference() when not None or to the overloaded _infer() method. The important point to note is that the _infer() is not defined in the nodes classes but is instead monkey-patched in the inference.py so that the inference implementation is not scattered to the multiple node classes.

Note

The inference method are to be wrapped in decorators like path_wrapper() which update the inference context.

In both cases the infer() returns a generator which iterates through the various values the node could take.

Todo

introduce the inference.infer_end() method and terminal nodes along with the recursive call

In some case the value yielded will not be a node found in the AST of the node but an instance of a special inference class such as _Yes, Instance,etc. Those classes are defined in bases.py.

Namely, the special singleton YES() is yielded when the inference reaches a point where t can’t follow the code and is so unable to guess a value ; and instances of the Instance class are yielded when the current node is infered to be an instance of some known class.

What does it rely upon ?

In order to perform such an inference the infer() methods rely on several more global objects, mainly :

MANAGER
is a unique global instance of the class AstroidManager, it helps managing and reusing inference needed / done somewhere else than the current invocation node.
InferenceContext
Instances of this class can be passed to the infer() methods to convey additional information on the context of the current node, and especially the current scope.

Todo

Write something about Scope objects and NodeNG.lookup() method.