[Distutils] patch for build_ext and a suggestion

Bastian Kleineidam calvin@cs.uni-sb.de
Sun, 12 Mar 2000 13:50:02 +0100 (CET)


Hello,

I have a patch for distutils-20000204.tar.gz.

patch for command/build_ext.py:
1. use correct name 'libs' instead of 'libraries' in build_ext options
2. adjust a String argument in BuildExt.libs to a list
77d76
<
88d86
<
105a104,106
>         # because fancy_getopts assigns strings
>         if type(self.libs)==StringType:
>             self.libs = [self.libs]
235c236
<             libraries = build_info.get ('libraries')
---
>             libraries = build_info.get ('libs')

The second thing is a suggestion.
Bug number 2 occurs on several more places in the distutils code.
Everytime the option type is list, the fancy_getopt method stores a
string instead.
So there are two restrictions for options:
1) An option is allowed only once and 
2) an option value type has to be a string.
Both restrictions are not necessary. What I want to have is that if I 
supply mulitple --libs options, each option value gets added to a list.

In the current implementation, subsequent option calls override the old
value. If I call
# ./setup.py build_ext --libs=ssl --libs=crypto
the ssl library value gets overridden.
Here is the code snippet from fancy_getopt.py thats responsible:
        attr = attr_name[opt]
        if takes_arg[opt]:
            setattr (object, attr, val)

Solution: instead of setattr, you should call the "set_option" function
of the object with "val" as argument.
So in the example above, this is
        attr = attr_name[opt]
        if takes_arg[opt]:
            object.set_option(attr, val)

Lets look now at the set_option function. The initial implementation 
is given in class Command:
    def set_option (self, option, value):
        """Set the value of a single option for this command.  Raise
           DistutilsOptionError if 'option' is not known."""
        if not hasattr (self, option):
            raise DistutilsOptionError, \
                  "command '%s': no such option '%s'" % \
                  (self.get_command_name(), option)
        if value is not None:
            setattr (self, option, value)

This is okay if I am happy with the above mentioned restrictions. To
extend this function, you override it in a subclass, for example in the
BuildExt class:
    # somewhere in the init function is this statement:
    self.list_value_options = ["libs", "include_dirs"] # and some more
    
    # now the new set_option
    def set_option(self, option, value):
        if option in self.list_value_options:
	    getattr(self, option).append(value)
        else:
	    Command.set_option(self, option, value)

Of course the above changes need some further refinement: you have to
initialize the list_value_options with the empty list, but then a
check "self.libs is None" will fail. Use "not self.libs" instead.
Then you have to ensure that every object we supply in fancy_getopt has
this set_option method.
And so on.

What do you think of my suggestion?

Greetings,

  Bastian Kleineidam