.. doctest docs/dev/setup.rst .. _dev.setup_info: ==================================== 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 :xfile:`setup.py` file of your project. The problem with this layout is that this :xfile:`setup.py` file is not available at runtime. For example the **version number**. You need it of course in the :xfile:`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 :xfile:`setup_info.py` and which we load ("execute") from both our :xfile:`setup.py` and our packages's main :xfile:`__init__.py` file. That's why the :xfile:`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 :file:`__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 Related files ============= These are the files we are talking about here. .. xfile:: setup.py A file named :xfile:`setup.py` is part of the `minimal structure `__ of every Python project. It is in the root directory of a project and contains information about the project, e.g. the **version number** or the **dependencies** (i.e. which other Python packages must be installed when using your package). The information in this file is used for running test suites, installing the project in different environments, etc... .. xfile:: setup_info.py The file which *actually* contains the information for Python's :xfile:`setup.py` script. It is imported from both the :xfile:`setup.py` and the packages's main :xfile:`__init__.py` file and usually defines a global variable `SETUP_INFO`, a dict of keyword arguments to be passed to the :func:`setup` function. It is located in the directory that contains the main package of your project. E.g. for the :ref:`xl` project it is in :file:`lino_xl/setup_info.py`. the main package of a project is specified in the :xfile:`tasks.py`. .. xfile:: README.rst A file named ``README`` (or some variant thereof) should be in the root directory of every public code repository and should contain a description of your project, links to more detailed documentation, ... In Atelier projects this file is automatically generated from the :ref:`long_description` by the :cmd:`inv bd`. .. xfile:: MANIFEST.in TODO .. xfile:: test_packages.py A file in the test suite of a repository that runs :meth:`run_packages_test `. Setup information ================= The :func:`setup` function has a lot of keyword parameters which are documented elsewhere. .. _install_requires: install_requires ---------------- See http://python-packaging.readthedocs.io/en/latest/dependencies.html .. _tests_require: tests_require ------------- See http://python-packaging.readthedocs.io/en/latest/dependencies.html .. _long_description: long_description ---------------- This contains the description to be published on PyPI. Some projects insert this in the :xfile:`api/index.rst` file of their docs tree. This is also used by :cmd:`inv bd` as the source text for generating the project's :xfile:`README.rst`. How to suggest changes to a README file ======================================= We assume that you have installed a development environment as explained in :ref:`dev.install`. Open the :xfile:`setup_info.py` file of your project and find the `long_description`. Edit its content. Run :cmd:`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 :xfile:`README.rst` file and check that it contains your changes. Submit a pull request with the two modified files :xfile:`setup_info.py` and :xfile:`README.rst`.