Branch merge

This commit is contained in:
Éric Araujo 2011-05-29 17:57:29 +02:00
commit 8c0c9d2641
2 changed files with 97 additions and 84 deletions

View File

@ -147,11 +147,11 @@ setup script). Indirectly provides the :class:`distutils.dist.Distribution` and
In addition, the :mod:`distutils.core` module exposed a number of classes that In addition, the :mod:`distutils.core` module exposed a number of classes that
live elsewhere. live elsewhere.
* :class:`Extension` from :mod:`distutils.extension` * :class:`~distutils.extension.Extension` from :mod:`distutils.extension`
* :class:`Command` from :mod:`distutils.cmd` * :class:`~distutils.cmd.Command` from :mod:`distutils.cmd`
* :class:`Distribution` from :mod:`distutils.dist` * :class:`~distutils.dist.Distribution` from :mod:`distutils.dist`
A short description of each of these follows, but see the relevant module for A short description of each of these follows, but see the relevant module for
the full reference. the full reference.
@ -1679,8 +1679,8 @@ lines, and joining lines with backslashes.
=================================================================== ===================================================================
.. module:: distutils.cmd .. module:: distutils.cmd
:synopsis: This module provides the abstract base class Command. This class is subclassed :synopsis: This module provides the abstract base class Command. This class
by the modules in the distutils.command subpackage. is subclassed by the modules in the distutils.command subpackage.
This module supplies the abstract base class :class:`Command`. This module supplies the abstract base class :class:`Command`.
@ -1690,20 +1690,84 @@ This module supplies the abstract base class :class:`Command`.
Abstract base class for defining command classes, the "worker bees" of the Abstract base class for defining command classes, the "worker bees" of the
Distutils. A useful analogy for command classes is to think of them as Distutils. A useful analogy for command classes is to think of them as
subroutines with local variables called *options*. The options are declared in subroutines with local variables called *options*. The options are declared
:meth:`initialize_options` and defined (given their final values) in in :meth:`initialize_options` and defined (given their final values) in
:meth:`finalize_options`, both of which must be defined by every command class. :meth:`finalize_options`, both of which must be defined by every command
The distinction between the two is necessary because option values might come class. The distinction between the two is necessary because option values
from the outside world (command line, config file, ...), and any options might come from the outside world (command line, config file, ...), and any
dependent on other options must be computed after these outside influences have options dependent on other options must be computed after these outside
been processed --- hence :meth:`finalize_options`. The body of the subroutine, influences have been processed --- hence :meth:`finalize_options`. The body
where it does all its work based on the values of its options, is the of the subroutine, where it does all its work based on the values of its
:meth:`run` method, which must also be implemented by every command class. options, is the :meth:`run` method, which must also be implemented by every
command class.
The class constructor takes a single argument *dist*, a :class:`Distribution` The class constructor takes a single argument *dist*, a :class:`Distribution`
instance. instance.
Creating a new Distutils command
================================
This section outlines the steps to create a new Distutils command.
A new command lives in a module in the :mod:`distutils.command` package. There
is a sample template in that directory called :file:`command_template`. Copy
this file to a new module with the same name as the new command you're
implementing. This module should implement a class with the same name as the
module (and the command). So, for instance, to create the command
``peel_banana`` (so that users can run ``setup.py peel_banana``), you'd copy
:file:`command_template` to :file:`distutils/command/peel_banana.py`, then edit
it so that it's implementing the class :class:`peel_banana`, a subclass of
:class:`distutils.cmd.Command`.
Subclasses of :class:`Command` must define the following methods.
.. method:: Command.initialize_options()
Set default values for all the options that this command supports. Note that
these defaults may be overridden by other commands, by the setup script, by
config files, or by the command-line. Thus, this is not the place to code
dependencies between options; generally, :meth:`initialize_options`
implementations are just a bunch of ``self.foo = None`` assignments.
.. method:: Command.finalize_options()
Set final values for all the options that this command supports. This is
always called as late as possible, ie. after any option assignments from the
command-line or from other commands have been done. Thus, this is the place
to to code option dependencies: if *foo* depends on *bar*, then it is safe to
set *foo* from *bar* as long as *foo* still has the same value it was
assigned in :meth:`initialize_options`.
.. method:: Command.run()
A command's raison d'etre: carry out the action it exists to perform, controlled
by the options initialized in :meth:`initialize_options`, customized by other
commands, the setup script, the command-line, and config files, and finalized in
:meth:`finalize_options`. All terminal output and filesystem interaction should
be done by :meth:`run`.
.. attribute:: Command.sub_commands
*sub_commands* formalizes the notion of a "family" of commands,
e.g. ``install`` as the parent with sub-commands ``install_lib``,
``install_headers``, etc. The parent of a family of commands defines
*sub_commands* as a class attribute; it's a list of 2-tuples ``(command_name,
predicate)``, with *command_name* a string and *predicate* a function, a
string or ``None``. *predicate* is a method of the parent command that
determines whether the corresponding command is applicable in the current
situation. (E.g. ``install_headers`` is only applicable if we have any C
header files to install.) If *predicate* is ``None``, that command is always
applicable.
*sub_commands* is usually defined at the *end* of a class, because
predicates can be methods of the class, so they must already have been
defined. The canonical example is the :command:`install` command.
:mod:`distutils.command` --- Individual Distutils commands :mod:`distutils.command` --- Individual Distutils commands
========================================================== ==========================================================
@ -1926,61 +1990,15 @@ This is described in more detail in :pep:`301`.
.. % todo .. % todo
Creating a new Distutils command :mod:`distutils.command.check` --- Check the meta-data of a package
================================ ===================================================================
This section outlines the steps to create a new Distutils command. .. module:: distutils.command.check
:synopsis: Check the metadata of a package
A new command lives in a module in the :mod:`distutils.command` package. There
is a sample template in that directory called :file:`command_template`. Copy
this file to a new module with the same name as the new command you're
implementing. This module should implement a class with the same name as the
module (and the command). So, for instance, to create the command
``peel_banana`` (so that users can run ``setup.py peel_banana``), you'd copy
:file:`command_template` to :file:`distutils/command/peel_banana.py`, then edit
it so that it's implementing the class :class:`peel_banana`, a subclass of
:class:`distutils.cmd.Command`.
Subclasses of :class:`Command` must define the following methods.
.. method:: Command.initialize_options() The ``check`` command performs some tests on the meta-data of a package.
For example, it verifies that all required meta-data are provided as
the arguments passed to the :func:`setup` function.
Set default values for all the options that this command supports. Note that .. % todo
these defaults may be overridden by other commands, by the setup script, by
config files, or by the command-line. Thus, this is not the place to code
dependencies between options; generally, :meth:`initialize_options`
implementations are just a bunch of ``self.foo = None`` assignments.
.. method:: Command.finalize_options()
Set final values for all the options that this command supports. This is
always called as late as possible, ie. after any option assignments from the
command-line or from other commands have been done. Thus, this is the place
to to code option dependencies: if *foo* depends on *bar*, then it is safe to
set *foo* from *bar* as long as *foo* still has the same value it was
assigned in :meth:`initialize_options`.
.. method:: Command.run()
A command's raison d'etre: carry out the action it exists to perform, controlled
by the options initialized in :meth:`initialize_options`, customized by other
commands, the setup script, the command-line, and config files, and finalized in
:meth:`finalize_options`. All terminal output and filesystem interaction should
be done by :meth:`run`.
*sub_commands* formalizes the notion of a "family" of commands, eg. ``install``
as the parent with sub-commands ``install_lib``, ``install_headers``, etc. The
parent of a family of commands defines *sub_commands* as a class attribute; it's
a list of 2-tuples ``(command_name, predicate)``, with *command_name* a string
and *predicate* an unbound method, a string or None. *predicate* is a method of
the parent command that determines whether the corresponding command is
applicable in the current situation. (Eg. we ``install_headers`` is only
applicable if we have any C header files to install.) If *predicate* is None,
that command is always applicable.
*sub_commands* is usually defined at the \*end\* of a class, because predicates
can be unbound methods, so they must already have been defined. The canonical
example is the :command:`install` command.

View File

@ -17,7 +17,7 @@ class BuildPyTestCase(support.TempdirManager,
support.LoggingSilencer, support.LoggingSilencer,
unittest.TestCase): unittest.TestCase):
def _setup_package_data(self): def test_package_data(self):
sources = self.mkdtemp() sources = self.mkdtemp()
f = open(os.path.join(sources, "__init__.py"), "w") f = open(os.path.join(sources, "__init__.py"), "w")
try: try:
@ -57,20 +57,15 @@ class BuildPyTestCase(support.TempdirManager,
self.assertEqual(len(cmd.get_outputs()), 3) self.assertEqual(len(cmd.get_outputs()), 3)
pkgdest = os.path.join(destination, "pkg") pkgdest = os.path.join(destination, "pkg")
files = os.listdir(pkgdest) files = os.listdir(pkgdest)
return files self.assertIn("__init__.py", files)
self.assertIn("README.txt", files)
# XXX even with -O, distutils writes pyc, not pyo; bug?
if sys.dont_write_bytecode:
self.assertNotIn("__init__.pyc", files)
else:
self.assertIn("__init__.pyc", files)
def test_package_data(self): def test_empty_package_dir(self):
files = self._setup_package_data()
self.assertTrue("__init__.py" in files)
self.assertTrue("README.txt" in files)
@unittest.skipIf(sys.flags.optimize >= 2,
"pyc files are not written with -O2 and above")
def test_package_data_pyc(self):
files = self._setup_package_data()
self.assertTrue("__init__.pyc" in files)
def test_empty_package_dir (self):
# See SF 1668596/1720897. # See SF 1668596/1720897.
cwd = os.getcwd() cwd = os.getcwd()
@ -118,7 +113,7 @@ class BuildPyTestCase(support.TempdirManager,
finally: finally:
sys.dont_write_bytecode = old_dont_write_bytecode sys.dont_write_bytecode = old_dont_write_bytecode
self.assertTrue('byte-compiling is disabled' in self.logs[0][1]) self.assertIn('byte-compiling is disabled', self.logs[0][1])
def test_suite(): def test_suite():
return unittest.makeSuite(BuildPyTestCase) return unittest.makeSuite(BuildPyTestCase)