On Wed, 20 Oct 2004 08:25:34 -0700, Guido van Rossum email@example.com wrote:
The opt* property builders could be substituted by a single opt which took the default value as an argument:
opt(section_name, key_name, default_value)
What if I want the default to be None? Sometimes absence of a value is useful info. If you want a single factory function (not sure why) then maybe the type should be passed in (perhaps optional, only if no default is given).
I like the optional type idea:
opt(section_name, key_name, default_value, type)
So it can be written this way:
opt('section', 'key', None, StringType)
...but -- to answer your question -- the point here isn't really the 'singleness' of the factory function, but the fact that it is type-independent, which (in principle) would allow it to be extended to handle arbitrary types by delegating some functionality to the types themselves. IMHO, it's just a different way to design it: instead of writing a specialized property handler for each supported type, use a standard interface provided by types themselves to handle the conversion to & from the string representation that is used in the config file. Unfortunately, this generalization is not as practical as I thought it would be.
In my implementation, I used standard Python type constructors to convert string values to the desired object type. It works for str, int and float [see note #1], which solved nearly all cases in my own experience. However, this trick doesn't work for bool(), which is an important type. To solve it, I had to write my own adapt() method, which just handles str, int and float using the builtin types, and treats bool() as a particular case. User defined types have to expose special conversion methods (as they should anyway). As it is, it's a general solution, but it ended up being more confusing and convoluted that I would like it to be.
It works well as far as the option names are unique. In some cases, there are sections with a similar internal structure, and in this case the use of nested structures to represent sections is better.
"Better" is subjective. With my approach, you can give them different prefixes in the Python API independent from their names as seen by the user, and you only have to do this when there are actual conflicts (which are rare except when certain styles are used).
Agreed. It depends a lot on the particular application, and to some extent, on personal taste. My own bias come from some of the applications that I have written, where I feared that the use of prefixes would end up cluttering the namespace. Besides the above mentioned communications software example (where I had several communication ports, each one stored into a section), another real scenario is the configuration of user interface parameters for several UI elements -- for example, font selection and background colors for specific forms. The same parameters ('font', 'font-color', 'background-color', etc.) are repeated for several sections. But surely, my own experience is limited, and I can't speak for other people on this point.
-------- As an apart: I was *really* surprised when I first saw that this code worked:
The following test also worked, but I expected it to convert the value using an octal representation, but it didn't:
And finally, the bool test:
Which obviously don't work because the 'False' string converts to True, as any other non-empty string do :-P. But it seemed a little bit weird when a I first saw it, specially when compared to FloatType and IntType.