I am currently looking for a convenient module to implement
configuration files with and I stumbled upon [1]. This allows config
fields to reference other config fields, e.g.
messages: [{
stream : 'sys.stderr'
message: 'Welcome'
} {
stream : $messages[0].stream
message: 'Bienvenue'
}]
where $messages[0].stream evaluates to 'sys.stderr'.
The JSON-like syntax makes it look rather ugly - especially compared
to RSON - but that referencing feature can be really handy. Is
something similar available for RSON?
Regards
Malte
Not at the moment (at least not directly). YAML supports
backreferences, but I thought the YAML syntax for doing this was quite
ugly, and I didn't have a use-case at the time.
I like this much better, and I think it could be bolted on quite
easily. For your use-case, would the $ always be at the outside like
this, or would you be doing stuff like $foo[$bar] ?
Regards,
Pat
For my current use-case the simpler version would be sufficient, but for
the sake of genericness I'd opt for the latter version. I guess it isn't
much harder to define a concrete parser syntax that also covers the
latter case. Maybe also $foo.$bar ...
While we are at it ... that config module also has an include feature,
enabling one to split a config file into several files, e.g.
# file public.cfg
public: {
foo: 'boo'
max: '9'
}
auth: @'..//private.cfg'
# file private.cfg
user: 'user1'
password: 'Wurstdurst'
public.cfg could than be put under version control whereas private.cfg
remains local.
Unfortunately, that config module currently only supports string
literals after the @, e.g.
@'/path/to/foo.cfg'
works, but
@$paths.root'/foo.cfg'
or
@($paths.root'/foo.cfg')
doesn't. One more reason to move to RSON :-)
Regards,
Malte
> Unfortunately, that config module currently only supports string literals
> after the @, e.g.
>
> @'/path/to/foo.cfg'
>
> works, but
>
> @$paths.root'/foo.cfg'
>
> or
>
> @($paths.root'/foo.cfg')
>
> doesn't. One more reason to move to RSON :-)
I think this is quite doable. The RSON parser is designed to be quite
configurable, and to have a minimal number of special characters, but
I think we only need to treat @ and $ specially inside non-quoted
strings. So that could be a subclass of the non-quoted string
handler. The only slight wrinkle I have to think a bit more about is
how $x gets processed when 'x' hasn't really yet been defined (the
current parser gathers up everything in a dictionary, then builds the
dictionary).
I think the syntax for combining includes and macros would have to be
something like:
@$(paths.root)/foo.cfg
(you wouldn't need the () in the case below)
@$pathroot/foo.cfg
(but if you had it, it would be a no-op and be fine:
@$(pathroot)/foo.cfg
but you wouldn't have quotes on the non-macro part, because the whole
purpose of macros is to inject code into strings, so by definition,
the $xxx would be inside a string.
Does that make sense?
Thanks,
Pat
OK, I've put a prototype script that does this in subversion. Due to
the way I originally built the parser, it has an, uh, interesting
restriction. If I have, for example:
foo:
stuff
stuff
bar:
stuff
stuff
then foo and bar are considered separate top-level objects. If
something inside bar references something else inside bar (e.g.
$bar.xxxxx) then a proxy object is generated. You can take str() on
the proxy object to get the real object. Something inside bar can
reference something inside foo (because foo parsing is finished when
bar parsing starts) without generating a proxy object.
Among other things, this means that if you are going to use a macro
inside an include file name (e.g. @$foo.xxxx), then you could do the
include from inside bar as long as the macro was defined inside foo
(because it comes earlier).
Anyway, if this restriction is too severe, we could reorganize the
parser a bit, but I'm not up for that for the next few weeks. (The
good news is that, if the proxy is acceptable, stuff inside foo can
actually reference stuff inside bar...)
To see this in action, check out the latest subversion from
http://rson.googlecode.com/svn/trunk/py2x and then go to the
py2x/tools directory and run the rsonmac.py script.
Regards,
Pat
Does this mean that using a macro always yields a string? E.g. would
prefix: 10
max: $(prefix)123
max be of type string here?
Ok, I'll give it a try soon to see if I can replace my current
configuration module with RSON.
Thanks for the quick reaction!
Malte
Yes and no. Right now, that would always be a string (unless it
breaks because I didn't use str() -- always a possibility :-), but
$(prefix) by itself wouldn't be.
You're welcome. BTW, I figured out how to remove the restrictions
fairly cleanly (by deproxifying on the way out of loads) but it will
be a week or two before I can implement it.
Regards,
Pat
Nevermind, I fixed it this morning :-)
I believe that now the example script works fine. In fact the test
data looks like:
fnames: []
ignore me
$(fnames[3]).txt
ignore me too
$lastname
foobar: @$fnames[1]
messages:
{}
stream: sys.stderr
message: Welcome
{}
stream : $messages[0].stream
message: Bienvenue
lastname: foobar
So you can have nested references, back references, forward
references, etc. (But if you try to do mutual references, you'll get
a stack overflow.)
Regards,
Pat