How Lino applications use setup.py

This document describes our trick for keeping the metadata about a Python package in a single place. It does not depend on Lino and we recommend it for any Python project which contains a package.

The classical layout is to store the setup information directly in the setup.py file of your project. The problem with this layout is that this setup.py file is not available at runtime.

For example the version number. You need it of course in the setup.py, but there are quite some projects which want to show somehow their version. So they need it at runtime as well. And that number can change quickly and can be critical. You don't want to store it in two different places.

Is there a way to have setup information both in a central place and* accessible at runtime?

It is an old problem, and e.g. Single-sourcing the package version describes a series of answers.

Our solution

To solve this problem, we store the setup information in a separate file which we usually name setup_info.py and which we load ("execute") from both our setup.py and our packages's main __init__.py file.

That's why the setup.py of a package "xxyyzz" contains just this:

from setuptools import setup
fn = 'xxyyzz/setup_info.py')
exec(compile(open(fn, "rb").read(), fn, 'exec'))
if __name__ == '__main__':
    setup(**SETUP_INFO)

And the __init__.py file of the main module contains this:

from os.path import join, dirname
fn = join(dirname(__file__), 'setup_info.py')
exec(compile(open(fn, "rb").read(), fn, 'exec'))
__version__ = SETUP_INFO.get('version')

Note that exec(compile(open(fn, "rb").read(), fn, 'exec')) is equivalent to execfile(fn), except that it works in both Python 2 and 3.

Usage example:

>>> from lino import SETUP_INFO
>>> print(SETUP_INFO['description'])
A framework for writing desktop-like web applications using Django and ExtJS or React
>>> from lino_xl import SETUP_INFO
>>> print(SETUP_INFO['description'])
Lino Extensions Library

Setup information

The setup() function has a lot of keyword parameters which are documented elsewhere.

long_description

This contains the description to be published on PyPI.

Some projects insert this in the api/index.rst file of their docs tree.

This is also used by inv bd as the source text for generating the project's README.rst.

How to suggest changes to a README file

We assume that you have installed a development environment as explained in Installing a Lino developer environment.

Open the setup_info.py file of your project and find the long_description.

Edit its content.

Run inv bd in the root of the project you want to make changes. This will ask you:

Overwrite /path/to/my/project/README.rst [Y,n]?

Hit ENTER.

Open the README.rst file and check that it contains your changes.

Submit a pull request with the two modified files setup_info.py and README.rst.