astropy/astropy — pull request #39 by phn (2011-10-31 11:26:03+00:00)
Title: Cython extension discovery example: interface to Skycalc.

Cython extension discovery should be treated the same way as the regular C extension discovery currently implemented; explicitly asking the developer and not automatic discovery. These commits implement a Cython extension discovery scheme that gives developers control over the extension building process. The scenario implemented here is probably as involved as it can be. This is an example, and not intended for direct merging.

The code adds a new sub-package ``astropy.skypy``. This has two modules ``skyc`` and ``astrom``, both of which are Cython extension modules. The ``skyc`` extension calls functions in an external library Skycalc. The ``astrom`` extension is a standalone extension.

The Skycalc library source code is included in ``cextern/skycalc``. The user, one who is installing astropy, can set a few configuration options for ``skypy``, which will determine whether astropy will build ``skypy.skyc`` using the source code in ``cextern``, or using pre compiled library in the user's machine. Currently the setting is in ``skypy/setup_package.py``. In production this will be in ``~/.astropy/skypy.cfg`` or equivalent.

The developer defines one or both of ``get_cython_pyx_extensions()`` and ``get_cython_extensions()`` functions in ``skypy/setup_package.py``. The astropy ``setup.py`` file will call the former if the condition ``HAVE_CYTHON and not release`` is True, and the latter if the condition is False. In addition, astropy ``setup.py`` will add Cython.Distutils ``build_ext`` command to ``cmdclass`` dictionary if the above condition is satisfied.

In the ``get_cython_pyx_extensions()`` function, the developer will return setuptools ``Extension`` instances that directly use Cython ``pyx`` files. In the ``get_cython_extensions()`` function, the developer will return setuptools ``Extension`` instances that use Cython generated C files only. These ``Extension`` instances will be constructed with parameters consistent with user's library option.

With the current set of files we can perform the following:

$ python setup.py develop # Bundle of warnings from skycalc.c.
$ ipython
>>> import astropy
>>> astropy.test("skypy")
================================== test session starts ========
platform linux2 -- Python 2.6.6 -- pytest-2.1.3
collected 1 items

astropy/skypy/tests/test_simple.py .

=============================== 1 passed in 0.02 seconds ======
0
>>> from astropy import skypy
>>> skypy.astrom.hello("d")
Hello d!
>>> skypy.skyc.dow(2451545.0)
5.0

We can now clean up, set the ``USE_SIN_FUNC_LIB`` option in ``skypy/setup_package.py`` and re-run the command. This time the library in ``~/lib`` will be used. The header file ``skysub.h`` must also be in ``~/lib``.

The library can be created using

gcc -c skycalc.c -o skycalc.o
ar rcs libskycalc.a skycalc.o

Note: ``USE_SIN_FUNC_LIB`` is left over from test code; forgot to rename to ``USE_SKYCALC_LIB`` or something else.