|
From: Robin M. <rob...@gm...> - 2006-06-07 22:24:48
|
On 6/6/06, Fuzzyman <fuz...@vo...> wrote: > Rick Kier wrote: > > >Hi Robin et all, > > > >Monday, June 05, 2006, Robin Munn wrote: > >RM> There's one other behavior of the interpolation that was surprising to > >RM> me: the fact that interpolated variables are *only* allowed to refer > >RM> to values in the [DEFAULT] section. That means that I can't do: > > > >Agree 100% on this. > > > >We don't use interpolation due to the current behavior > > > > > I don't use string substitution at all, so I am willing to listen to the > views of users on this. > > It could theoretically break behaviour for others. > > Anyone else got opinions ? > > Fuzzyman > http://www.voidspace.org.uk/python/index.shtml After giving it some more thought, I'm starting to believe the best interpolation behavior is going to be eager-interpolation, pulling values from anywhere in the current section, its DEFAULTs, or its parents and their DEFAULTs. So the algorithm looks like this: When a string interpolation (in either "%(foo)s" or "$foo" syntax) is seen, immediately try to interpret it as follows: 1. Look for name "foo" in current section. If found, exit loop. 2. Look for name "foo" in current section's DEFAULTs. If found, exit loop. 3. Move "current section" reference to parent. If no parent, raise NotFoundException. 4. Repeat from step 1. Advantages of this approach: 1. No need for special-case "Stop when a $$ is seen" code. Special-case code usually makes me uncomfortable unless there's a darn good reason for it, and this one smells like a workaround. 2. The scoping rules work like I would have expected them to work in the first place: specifically-given values override default values, and parent namespaces are consulted all the way up to the top. 3. No need for recursive evaluation, or any maximumum-nesting-depth parameters. Since whatever $foo expands to has *already* been evaluated (or else the "foo" name wouldn't exist), any interpolations in the "foo" value have already been expanded. So we just replace "$foo" with the value and we're done. Disadvantages of this approach: 1. How do we round-trip? E.g., if we have "foo = 3" and "bar = $foo", after we load the config file, the value of "bar" is 3, and so when we write it out we'll get "foo = 3" and "bar = 3". Solution: if interpolation happens, keep the value of the original string around for use when we write out the config file. Question: where to keep that original string? 2. Values modified after the config file is parsed won't propagate their changes "upwards" to anything that includes them. If after parsing the file, we set "foo" to 4, "bar" will still be 3. This may not be the desired behavior for some people: they might want to change the "path_root" value and have that change propagate throughout their config structure. Solution: since we kept the original values around, when "foo" changes, we can re-evaluate whatever depends on "foo". (This would be a perfect place to use PyCells, once that project is complete). Or we could simply re-evaluate the entire config structure to be safe. Note: Some people may *not* want the value of "bar" to be changed when "foo" is modified. We should make this an option somewhere -- perhaps a "propagate_changes=False" keyword to a function call, or a "propagate_changes" attribute in the ConfigObj instance. Haven't thought about this one deeply yet. Summary: I propose eager evaluation of interpolated values, with lexical scoping for finding values. The original, non-interpolated strings should be saved for the purposes of configfile round-tripping and, optionally, post-evaluation propagation of changes to dependent values (e.g., changing the value of "bar = $foo" when "foo" is modified). -- Robin Munn Rob...@gm... GPG key 0xD6497014 |