| .. _distutils_examples: |
| |
| ****************** |
| Distutils Examples |
| ****************** |
| |
| .. include:: ./_setuptools_disclaimer.rst |
| |
| This chapter provides a number of basic examples to help get started with |
| distutils. Additional information about using distutils can be found in the |
| Distutils Cookbook. |
| |
| |
| .. seealso:: |
| |
| `Distutils Cookbook <https://wiki.python.org/moin/Distutils/Cookbook>`_ |
| Collection of recipes showing how to achieve more control over distutils. |
| |
| |
| .. _pure-mod: |
| |
| Pure Python distribution (by module) |
| ==================================== |
| |
| If you're just distributing a couple of modules, especially if they don't live |
| in a particular package, you can specify them individually using the |
| ``py_modules`` option in the setup script. |
| |
| In the simplest case, you'll have two files to worry about: a setup script and |
| the single module you're distributing, :file:`foo.py` in this example:: |
| |
| <root>/ |
| setup.py |
| foo.py |
| |
| (In all diagrams in this section, *<root>* will refer to the distribution root |
| directory.) A minimal setup script to describe this situation would be:: |
| |
| from distutils.core import setup |
| setup(name='foo', |
| version='1.0', |
| py_modules=['foo'], |
| ) |
| |
| Note that the name of the distribution is specified independently with the |
| ``name`` option, and there's no rule that says it has to be the same as |
| the name of the sole module in the distribution (although that's probably a good |
| convention to follow). However, the distribution name is used to generate |
| filenames, so you should stick to letters, digits, underscores, and hyphens. |
| |
| Since ``py_modules`` is a list, you can of course specify multiple |
| modules, eg. if you're distributing modules :mod:`foo` and :mod:`bar`, your |
| setup might look like this:: |
| |
| <root>/ |
| setup.py |
| foo.py |
| bar.py |
| |
| and the setup script might be :: |
| |
| from distutils.core import setup |
| setup(name='foobar', |
| version='1.0', |
| py_modules=['foo', 'bar'], |
| ) |
| |
| You can put module source files into another directory, but if you have enough |
| modules to do that, it's probably easier to specify modules by package rather |
| than listing them individually. |
| |
| |
| .. _pure-pkg: |
| |
| Pure Python distribution (by package) |
| ===================================== |
| |
| If you have more than a couple of modules to distribute, especially if they are |
| in multiple packages, it's probably easier to specify whole packages rather than |
| individual modules. This works even if your modules are not in a package; you |
| can just tell the Distutils to process modules from the root package, and that |
| works the same as any other package (except that you don't have to have an |
| :file:`__init__.py` file). |
| |
| The setup script from the last example could also be written as :: |
| |
| from distutils.core import setup |
| setup(name='foobar', |
| version='1.0', |
| packages=[''], |
| ) |
| |
| (The empty string stands for the root package.) |
| |
| If those two files are moved into a subdirectory, but remain in the root |
| package, e.g.:: |
| |
| <root>/ |
| setup.py |
| src/ foo.py |
| bar.py |
| |
| then you would still specify the root package, but you have to tell the |
| Distutils where source files in the root package live:: |
| |
| from distutils.core import setup |
| setup(name='foobar', |
| version='1.0', |
| package_dir={'': 'src'}, |
| packages=[''], |
| ) |
| |
| More typically, though, you will want to distribute multiple modules in the same |
| package (or in sub-packages). For example, if the :mod:`foo` and :mod:`bar` |
| modules belong in package :mod:`foobar`, one way to layout your source tree is |
| :: |
| |
| <root>/ |
| setup.py |
| foobar/ |
| __init__.py |
| foo.py |
| bar.py |
| |
| This is in fact the default layout expected by the Distutils, and the one that |
| requires the least work to describe in your setup script:: |
| |
| from distutils.core import setup |
| setup(name='foobar', |
| version='1.0', |
| packages=['foobar'], |
| ) |
| |
| If you want to put modules in directories not named for their package, then you |
| need to use the ``package_dir`` option again. For example, if the |
| :file:`src` directory holds modules in the :mod:`foobar` package:: |
| |
| <root>/ |
| setup.py |
| src/ |
| __init__.py |
| foo.py |
| bar.py |
| |
| an appropriate setup script would be :: |
| |
| from distutils.core import setup |
| setup(name='foobar', |
| version='1.0', |
| package_dir={'foobar': 'src'}, |
| packages=['foobar'], |
| ) |
| |
| Or, you might put modules from your main package right in the distribution |
| root:: |
| |
| <root>/ |
| setup.py |
| __init__.py |
| foo.py |
| bar.py |
| |
| in which case your setup script would be :: |
| |
| from distutils.core import setup |
| setup(name='foobar', |
| version='1.0', |
| package_dir={'foobar': ''}, |
| packages=['foobar'], |
| ) |
| |
| (The empty string also stands for the current directory.) |
| |
| If you have sub-packages, they must be explicitly listed in ``packages``, |
| but any entries in ``package_dir`` automatically extend to sub-packages. |
| (In other words, the Distutils does *not* scan your source tree, trying to |
| figure out which directories correspond to Python packages by looking for |
| :file:`__init__.py` files.) Thus, if the default layout grows a sub-package:: |
| |
| <root>/ |
| setup.py |
| foobar/ |
| __init__.py |
| foo.py |
| bar.py |
| subfoo/ |
| __init__.py |
| blah.py |
| |
| then the corresponding setup script would be :: |
| |
| from distutils.core import setup |
| setup(name='foobar', |
| version='1.0', |
| packages=['foobar', 'foobar.subfoo'], |
| ) |
| |
| |
| .. _single-ext: |
| |
| Single extension module |
| ======================= |
| |
| Extension modules are specified using the ``ext_modules`` option. |
| ``package_dir`` has no effect on where extension source files are found; |
| it only affects the source for pure Python modules. The simplest case, a |
| single extension module in a single C source file, is:: |
| |
| <root>/ |
| setup.py |
| foo.c |
| |
| If the :mod:`foo` extension belongs in the root package, the setup script for |
| this could be :: |
| |
| from distutils.core import setup |
| from distutils.extension import Extension |
| setup(name='foobar', |
| version='1.0', |
| ext_modules=[Extension('foo', ['foo.c'])], |
| ) |
| |
| If the extension actually belongs in a package, say :mod:`foopkg`, then |
| |
| With exactly the same source tree layout, this extension can be put in the |
| :mod:`foopkg` package simply by changing the name of the extension:: |
| |
| from distutils.core import setup |
| from distutils.extension import Extension |
| setup(name='foobar', |
| version='1.0', |
| ext_modules=[Extension('foopkg.foo', ['foo.c'])], |
| ) |
| |
| Checking a package |
| ================== |
| |
| The ``check`` command allows you to verify if your package meta-data |
| meet the minimum requirements to build a distribution. |
| |
| To run it, just call it using your :file:`setup.py` script. If something is |
| missing, ``check`` will display a warning. |
| |
| Let's take an example with a simple script:: |
| |
| from distutils.core import setup |
| |
| setup(name='foobar') |
| |
| Running the ``check`` command will display some warnings: |
| |
| .. code-block:: shell-session |
| |
| $ python setup.py check |
| running check |
| warning: check: missing required meta-data: version, url |
| warning: check: missing meta-data: either (author and author_email) or |
| (maintainer and maintainer_email) should be supplied |
| |
| |
| If you use the reStructuredText syntax in the ``long_description`` field and |
| `docutils`_ is installed you can check if the syntax is fine with the |
| ``check`` command, using the ``restructuredtext`` option. |
| |
| For example, if the :file:`setup.py` script is changed like this:: |
| |
| from distutils.core import setup |
| |
| desc = """\ |
| My description |
| ============== |
| |
| This is the description of the ``foobar`` package. |
| """ |
| |
| setup(name='foobar', version='1', author='tarek', |
| author_email='tarek@ziade.org', |
| url='http://example.com', long_description=desc) |
| |
| Where the long description is broken, ``check`` will be able to detect it |
| by using the :mod:`docutils` parser: |
| |
| .. code-block:: shell-session |
| |
| $ python setup.py check --restructuredtext |
| running check |
| warning: check: Title underline too short. (line 2) |
| warning: check: Could not finish the parsing. |
| |
| Reading the metadata |
| ===================== |
| |
| The :func:`distutils.core.setup` function provides a command-line interface |
| that allows you to query the metadata fields of a project through the |
| ``setup.py`` script of a given project: |
| |
| .. code-block:: shell-session |
| |
| $ python setup.py --name |
| distribute |
| |
| This call reads the ``name`` metadata by running the |
| :func:`distutils.core.setup` function. Although, when a source or binary |
| distribution is created with Distutils, the metadata fields are written |
| in a static file called :file:`PKG-INFO`. When a Distutils-based project is |
| installed in Python, the :file:`PKG-INFO` file is copied alongside the modules |
| and packages of the distribution under :file:`NAME-VERSION-pyX.X.egg-info`, |
| where ``NAME`` is the name of the project, ``VERSION`` its version as defined |
| in the Metadata, and ``pyX.X`` the major and minor version of Python like |
| ``2.7`` or ``3.2``. |
| |
| You can read back this static file, by using the |
| :class:`distutils.dist.DistributionMetadata` class and its |
| :func:`read_pkg_file` method:: |
| |
| >>> from distutils.dist import DistributionMetadata |
| >>> metadata = DistributionMetadata() |
| >>> metadata.read_pkg_file(open('distribute-0.6.8-py2.7.egg-info')) |
| >>> metadata.name |
| 'distribute' |
| >>> metadata.version |
| '0.6.8' |
| >>> metadata.description |
| 'Easily download, build, install, upgrade, and uninstall Python packages' |
| |
| Notice that the class can also be instantiated with a metadata file path to |
| loads its values:: |
| |
| >>> pkg_info_path = 'distribute-0.6.8-py2.7.egg-info' |
| >>> DistributionMetadata(pkg_info_path).name |
| 'distribute' |
| |
| |
| .. % \section{Multiple extension modules} |
| .. % \label{multiple-ext} |
| |
| .. % \section{Putting it all together} |
| |
| |
| .. _docutils: http://docutils.sourceforge.net |