File: DEVGUIDE.rst

package info (click to toggle)
pythran 0.17.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 12,700 kB
  • sloc: cpp: 65,021; python: 41,083; sh: 137; makefile: 87
file content (192 lines) | stat: -rw-r--r-- 7,049 bytes parent folder | download | duplicates (2)
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
Developer Guide
###############

Do not hang around in Pythran code base without your developer guide! It is
the compass that will guide you in the code jungle!

Disclaimer
----------

This document is a never ending work-in-progress draft. Please contribute!

Configuration
-------------

Pythran can be configured with a rc file. An example is found in `pythran/pythran.cfg`.
Look at it! To customize it::

    $> cp pythran/pythran.cfg ~/.pythranrc

In particular, you may want to add ``-g -O0`` to the ``cxxflags``.

Coding Style
------------

All Python code must be conform to the PEP 8, and the ``flake8`` command must not
yield any message when run on our database. Additionally, avoid backslashes,
and try to make your code as concise as possible.

    $> flake8 pythran/*.py pythran/*/*.py --exclude="pythran/tests/test*.py,__init__.py"

C++ code use spaces (no tabs) and a tab width of 4.

File Hierarchy
--------------

Listing the top level directory yields the following entries:

setup.py
    The files that describes what gets installed, that holds ``PyPI`` entries
    and such.

docs/
    If you're reading this document, you know what it's all about!  ``MANUAL``
    is the user documentation and ``DEVGUIDE`` is the developer documentation.

    Use ``make`` from this directory to produce the static website.

LICENSE
    Boring but important stuff.

MANIFEST.in
    Describe additional stuff to package there.

README.rst
    Quick introduction and description of _pythran_.

pythran/
    The source of all things.

pythran/tests/
    The source of all issues.

pythran/pythonic/
    Where C++ back-end lies.


Validation
----------

``pythran`` uses the ``unittest`` module and the `pytest
<http://pytest.org/latest/>`_ package to manage test cases.

All requirements are listed in ``pythran/tests/requirements.txt``.


The whole validation suite is run through the command::

    $> python -m pytest pythran/tests

To run it faster we use the ``pytest`` extension `xdist
<https://pypi.org/project/pytest-xdist/>`_, the test suite will run using all
available cores. Otherwise it might run **very** slowly, something like four
hours on a decent laptop :'(.

Note that it is possible to use the ``pytest`` module to pass a subset of the
test suite::

    $> pytest -n 8 pythran/tests/test_list.py

runs all the tests found in ``pythran/tests/test_list.py``.

There are two kinds of tests in ``pythran``:

1. unit tests that test a specific feature of the implementation. Such tests
   are listed as method of a class deriving from ``test_env.TestEnv`` and must
   call the ``run_test(function_to_translate, *effective_parameters,
   **name_to_signature)`` method [1]_.  It translates ``function_to_translate``
   into a native function using the type annotations given in the
   ``name_to_signature`` dictionary, runs both the python and the native
   version with ``effective_parameters`` as arguments and asserts the results
   are the same.

   .. [1] See examples in ``pythran/tests/test_base.py`` for more details.

2. test cases that are just plain python modules to be converted in native
   module by ``pythran``. It is used to test complex situations, codes or
   benchmarks found on the web etc. They are just translated, not run. These
   test cases lie in ``pythran/tests/cases/`` and are listed in
   ``pythran/tests/test_cases.py``.


C++ runtime
-----------

The C++ code generated by ``pythran`` relies on a specific back-end,
``pythonic``. It is a set of headers that mimics Python's intrinsics and
collections behavior in C++. It lies in ``pythran/pythonic/``. There is one
directory per module, e.g. ``pythran/pythonic/numpy`` for the ``numpy`` module,
and one file per function, e.g. ``pythran/pythonic/numpy/ones.hpp`` for the
``numpy.ones`` function. Type definitions are stored in the seperate
``pythran/pythonic/types`` directory, one header per type. Each function header
must be ``#includ``-able independently, i.e. it itself includes all the type
and function definition it needs. This helps keeping compilation time low.

All Pythran functions and types live in the ``pythonic`` namespace. Each extra
module defines a new namespace, like ``pythonic::math`` or
``pythonic::random``, and each type is defined in the ``pythonic::types``
namespace. The ``DECLARE_FUNCTOR`` and ``DEFINE_FUNCTOR`` macros from
``pythonic/utils/functor.hpp`` is commonly used to convert functions into
functors and put them into the mandatory ``functor`` namespace.

The pythonic runtime can be used without Python support, so it is important to
protect all Python-specific stuff inside ``ENABLE_PYTHON_MODULE`` guard.

All methods are represented by functions in Pythran. The associated
pseudo-modules are prefixed and suffixed by a double underscore ``__``, as in
``pythran/pythonic/__list__``.


Benchmarking and Testing
------------------------

Stand-alone algorithms are put into ``pythran/tests/cases``. They must be valid
Pythran input (including spec annotations). To be taken into account by the
validation suite, they must be listed in ``pythran/tests/test_cases.py``. To be
taken into account by the benchmarking suite, they must have a line starting
with the ``#runas`` directive. Check ``pythran/tests/matmul.py`` for a complete
example.

To run the benchmark suite, one can rely on::

    $> python setup.py bench --mode=<mode>

where *<mode>* is one among:

python
    Uses the interpreter used to run ``setup.py``.

pythran
    Uses the Pythran compiler.

pythran+omp
    Uses the Pythran compiler in OpenMP mode.

All measurements are made using the ``timeit`` module. The number of iterations
is customizable through the ``--nb-iter`` switch.

How to
------

:Add support for a new module:
    1. Provide its C++ implementation in ``pythran/pythonic++/<mymodule>``.
           ``pythran/pythonic++/math/*.hpp`` and
           ``pythran/pythonic++/__list__/*.hpp`` are good example to referer to.
    2. Provide its description in ``pythran/tables.py``. Each function, method
           or variable must be listed there with the appropriate description.
    3. Provide its test suite in ``pythran/tests/`` under the name
           ``test_my_module.py``. One test case per function, method or variable
           is great.

:Add a new analysis:
    1. Subclass one of ``ModuleAnalysis``, ``FunctionAnalysis`` or ``NodeAnalysis``.
    2. List analysis required by yours in the parent constructor, they will be built automatically and stored in the attribute with the corresponding uncameled name.
    3. Write your analysis as a regular ``ast.NodeVisitor``. The analysis result must be stored in ``self.result``.
    4. Use it either from another pass's constructor, or through the ``passmanager.gather`` function.


:Push changes into the holy trunk:
    1. Use the ``github`` interface and the pull/push requests features
    2. Make your dev available on the web and asks for a merge on the IRC
           channel ``#pythran`` on ``irc.oftc.net``
           (via your browser: https://webchat.oftc.net)