summaryrefslogtreecommitdiff
path: root/doc/source/inference.rst
blob: bf67993f03da81400d4a1e07a748fee2069dfac0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
.. _inference:

===================================
  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 :meth:`NodeNG.infer` method
of the AST nodes which is defined in :class:`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 chek this :func:`infer` is monkey-patched point

The :meth:`NodeNG.infer` method either delegates the actual inference
to the instance specific method :meth:`NodeNG._explicit_inference`
when not `None` or to the overloaded :meth:`_infer` method. The
important point to note is that the :meth:`_infer` is *not* defined in
the nodes classes but is instead *monkey-patched* in the
:file:`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
          :func:`path_wrapper` which update the inference context.

In both cases the :meth:`infer` returns a *generator* which iterates
through the various *values* the node could take.

.. todo:: introduce the :func:`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 :class:`_Yes`,
:class:`Instance`,etc. Those classes are defined in :file:`bases.py`.

Namely, the special singleton :obj:`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 :class:`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 :meth:`infer` methods rely
on several more global objects, mainly :

:obj:`MANAGER`
    is a unique global instance of the class :class:`AstroidManager`,
    it helps managing and reusing inference needed / done somewhere
    else than the current invocation node.

:class:`InferenceContext`
    Instances of this class can be passed to the :meth:`infer` methods
    to convey aditionnal information on the context of the current
    node, and especially the current scope.

.. todo:: Write something about :class:`Scope` objects and
          :meth:`NodeNG.lookup` method.


API documentation
=================

Here is the annotaded API documentation extracted from the source code
of the :mod:`inference`.

.. todo:: actually annotate the doc to structure its approach

.. automodule:: inference
   :members:
   :undoc-members:
.. :special-members: in autodoc/sphinx 1.1