[Distutils] Name game for 0.2

Greg Ward gward@cnri.reston.va.us
Sun, 30 Jan 2000 16:19:31 -0500


Hi all --

the easiest change I want to make in Distutils 0.2 is to fix some bad
nomenclature in the command classes.  This will break a small amount of
existing code, in particular any setup script that extends the system by
defining new command classes or extending existing ones.  AFAIK, this
means just Numerical Python.  I'm perfectly happy to break code this
early in the game, but *we must get it right* this time.

Here's the background: every command class has four key elements.  No,
wait, five -- I just added one today.  OK, every command class has
*five* key elements:

  options - class attribute, lists command-line-settable options
  description - class attribute, a one-line description for the
    "--help-commands" option

  set_default_options() - method, initializes all command options
    (whether they can be set on the command-line or not)
  set_final_options() - method, decide on final values for all
    command options so we can go ahead and run the command with
    minimal logic
  run() - method, run the command

The bad news is I'm only happy with two of these names ('description'
and 'run()').  The goods news I *think* I know what I want to rename the
other three to.

'options' should be called 'user_options' for several reasons.  First,
it only describes a subset of the command's options, i.e. there are more
options dealt with in 'set_default_options()' and 'set_final_options()'
than are mentioned in the 'options' attribute.  The attribute just lists
options that can be set on the command-line -- but I don't want to
restrict myself to *just* the command-line; someday we'll have config
files too, and users will be able to set these options in config files
to boot.  The key is that *users* -- most importantly installers, but in
general anyone who runs the setup script -- can set the options listed
in the 'options' attribute.  Hence 'user_options'.  Easy decision, eh?

The second-easiest one is 'set_default_options()'.  The purpose of this
method is to assign initial values to *all* of the command's options,
not just the user-settable ones listed in the attribute soon to be
called 'user_options'.  A typical 'set_default_methods()' looks like
this (from the standard 'build' command):

    def set_default_options (self):
        self.build_base = 'build'
        self.build_lib = None
        self.build_platlib = None

Pretty simple: in fact, it looks a lot like a typical Python
constructor.  The only reason this isn't done in a constructor is that
Command, the base class for all Distutils commands, provides a perfectly
good constructor that happens to call 'set_default_options()' to do
command-specific initialization.  So I think the name for this method
should, pretty obviously, be 'initialize_options()'.  Nice "action-verb"
form there, much better than the current lame form.

Finally, 'set_final_options()'.  I've never much liked this name; it was
thought up in a rush when I suddenly realized the need for the method
and had to throw it in quickly to get things working.  In addition to
being the hardest to think of a good name for, this one is the hardest
to explain: it exists to decide on final option values for any options
that were not set by the user.  To clarify, here's how things typically
go for a given command in a Distutils run:

  * create command object
    - call 'set_default_options()' to initialize option values

[ * parse config files
    - set various command options from what's found in the config files ]
   [vapourware]

  * parse command line
    - set various command options from what's found on the command-line
      [overriding config-file option values, when that's possible]

  * call 'set_final_options()'

  * call 'run()'

The idea is that any option that's still None -- ie. wasn't touched by
the command-line, config files, or whatever -- by the time we reach
'set_final_options()' will be decided by the code in
'set_final_options()'.  For example, here's the 'build' command's
implementation of that method:

    def set_final_options (self):
        # 'build_lib' and 'build_platlib' just default to 'lib' and
        # 'platlib' under the base build directory
        if self.build_lib is None:
            self.build_lib = os.path.join (self.build_base, 'lib')
        if self.build_platlib is None:
            self.build_platlib = os.path.join (self.build_base, 'platlib')

For the 'build' command, 'build_base' is really only used to derive the
two "important" options, build_lib and build_platlib.  If the user
supplies one of those important options (eg. on the command line), then
we don't override their request -- we only compute a value if build_lib
or build_platlib are None.

So, some silly names for this method are:

  decide_final_option_values()
  settle_on_values_for_any_options_not_set_by_the_user()

and some not-so-silly, but not much better names, are:

  decide_options()
  finalize_options()
  finish_options()

Anyone have strong feelings about any of these?  I'm wary of "finalize"
because the Java people for some reason decided that "finalize" means
"clean up before destruction" (well, OK, I'm not sure if they're to
blame for this odd piece of jargon -- but it is established jargon, like
it or not).

The basic idea behind the method is to settle on a set of option values
that will drive how we run the command: once the option values are
decided, running the command should be relatively straightforward.  So
this really is a preparatory step, but it's the *final* preparatory
step.  If this gives you any great ideas for what to call the bloody
thing, please let me know, because I'm stumped.

Thanks --

        Greg