# Example of Pythran Usage Within a Full Project

This notebook covers the creation of a simple, distutils-powered, project that ships a pythran kernel.

But first some cleanup

    [1]:

    !rm -rf hello setup.py && mkdir hello

## Project layout

The Pythran file is really dumb. The expected layout is:

    setup.py
    hello/
      +---- __init__.py
      +---- hello.py

    [2]:

    %%file hello/hello.py

    #pythran export hello()

    def hello():
        """
        Wave hello.
        """
        print("Hello from Pythran o/")

    Writing hello/hello.py

And so is the `__init__.py` file.

    [3]:

    %%file hello/__init__.py
    """
    Hello package, featuring a Pythran kernel.
    """
    from hello import hello

    Writing hello/__init__.py

The `setup.py` file contains the classical metadata, plus a special header. this header basically states if pythran is available, use it, otherwise fallback to the python file.

    [4]:

    %%file setup.py
    from distutils.core import setup

    try:
        from pythran.dist import PythranExtension, PythranBuildExt
        setup_args = {
            'cmdclass': {"build_ext": PythranBuildExt},
            'ext_modules': [PythranExtension('hello.hello', sources = ['hello/hello.py'])],
        }
    except ImportError:
        print("Not building Pythran extension")
        setup_args = {}

    setup(name = 'hello',
          version = '1.0',
          description = 'Yet another demo package',
          packages = ['hello'],
          **setup_args)

    Writing setup.py

## Running `setup.py`

With the described configuration, the normal `python setup.py` targets should « just work ».

If pythran is in the path, it is used to generate the alternative c++ extension when building a source release. Note the `hello.cpp`!

    [5]:

    %%sh
    rm -rf build dist
    python setup.py sdist 2>/dev/null 1>/dev/null
    tar tf dist/hello-1.0.tar.gz | grep -E 'hello/hello.(py|cpp)' -o | sort

    hello/hello.cpp
    hello/hello.py

But if pythran is no longer in the `PYTHONPATH`, the installation does not fail: the regular Python source can still be used.

    [6]:

    %%sh
    rm -rf build dist
    PYTHONPATH= python setup.py sdist 2>/dev/null 1>/dev/null
    tar tf dist/hello-1.0.tar.gz | grep -E 'hello/hello.py' -o

    hello/hello.py

In case of binary distribution, the native module is generated alongside the original source.

    [7]:

    %%sh
    rm -rf build dist
    python setup.py bdist 2>/dev/null 1>/dev/null
    tar tf dist/hello-1.0.linux-x86_64.tar.gz | grep -E 'hello/hello.(py|cpp)' -o

    hello/hello.py

And if pythran is not in the `PYTHONPATH`, this still work `\o/`

    [8]:

    %%sh
    rm -rf build dist
    PYTHONPATH= python setup.py bdist 2>/dev/null 1>/dev/null
    tar tf dist/hello-1.0.linux-x86_64.tar.gz | grep -E 'hello/hello.py' -o

    hello/hello.py