| .. _extending-distutils: | |
| ******************* | |
| Extending Distutils | |
| ******************* | |
| Distutils can be extended in various ways. Most extensions take the form of new | |
| commands or replacements for existing commands. New commands may be written to | |
| support new types of platform-specific packaging, for example, while | |
| replacements for existing commands may be made to modify details of how the | |
| command operates on a package. | |
| Most extensions of the distutils are made within :file:`setup.py` scripts that | |
| want to modify existing commands; many simply add a few file extensions that | |
| should be copied into packages in addition to :file:`.py` files as a | |
| convenience. | |
| Most distutils command implementations are subclasses of the | |
| :class:`distutils.cmd.Command` class. New commands may directly inherit from | |
| :class:`Command`, while replacements often derive from :class:`Command` | |
| indirectly, directly subclassing the command they are replacing. Commands are | |
| required to derive from :class:`Command`. | |
| .. % \section{Extending existing commands} | |
| .. % \label{extend-existing} | |
| .. % \section{Writing new commands} | |
| .. % \label{new-commands} | |
| .. % \XXX{Would an uninstall command be a good example here?} | |
| Integrating new commands | |
| ======================== | |
| There are different ways to integrate new command implementations into | |
| distutils. The most difficult is to lobby for the inclusion of the new features | |
| in distutils itself, and wait for (and require) a version of Python that | |
| provides that support. This is really hard for many reasons. | |
| The most common, and possibly the most reasonable for most needs, is to include | |
| the new implementations with your :file:`setup.py` script, and cause the | |
| :func:`distutils.core.setup` function use them:: | |
| from distutils.command.build_py import build_py as _build_py | |
| from distutils.core import setup | |
| class build_py(_build_py): | |
| """Specialized Python source builder.""" | |
| # implement whatever needs to be different... | |
| setup(cmdclass={'build_py': build_py}, | |
| ...) | |
| This approach is most valuable if the new implementations must be used to use a | |
| particular package, as everyone interested in the package will need to have the | |
| new command implementation. | |
| Beginning with Python 2.4, a third option is available, intended to allow new | |
| commands to be added which can support existing :file:`setup.py` scripts without | |
| requiring modifications to the Python installation. This is expected to allow | |
| third-party extensions to provide support for additional packaging systems, but | |
| the commands can be used for anything distutils commands can be used for. A new | |
| configuration option, ``command_packages`` (command-line option | |
| :option:`!--command-packages`), can be used to specify additional packages to be | |
| searched for modules implementing commands. Like all distutils options, this | |
| can be specified on the command line or in a configuration file. This option | |
| can only be set in the ``[global]`` section of a configuration file, or before | |
| any commands on the command line. If set in a configuration file, it can be | |
| overridden from the command line; setting it to an empty string on the command | |
| line causes the default to be used. This should never be set in a configuration | |
| file provided with a package. | |
| This new option can be used to add any number of packages to the list of | |
| packages searched for command implementations; multiple package names should be | |
| separated by commas. When not specified, the search is only performed in the | |
| :mod:`distutils.command` package. When :file:`setup.py` is run with the option | |
| ``--command-packages distcmds,buildcmds``, however, the packages | |
| :mod:`distutils.command`, :mod:`distcmds`, and :mod:`buildcmds` will be searched | |
| in that order. New commands are expected to be implemented in modules of the | |
| same name as the command by classes sharing the same name. Given the example | |
| command line option above, the command :command:`bdist_openpkg` could be | |
| implemented by the class :class:`distcmds.bdist_openpkg.bdist_openpkg` or | |
| :class:`buildcmds.bdist_openpkg.bdist_openpkg`. | |
| Adding new distribution types | |
| ============================= | |
| Commands that create distributions (files in the :file:`dist/` directory) need | |
| to add ``(command, filename)`` pairs to ``self.distribution.dist_files`` so that | |
| :command:`upload` can upload it to PyPI. The *filename* in the pair contains no | |
| path information, only the name of the file itself. In dry-run mode, pairs | |
| should still be added to represent what would have been created. | |