tags:

views:

256

answers:

4

I would like to create a simple file format/DSL which would allow my users to input data. My system is in python and using python's parser is appealing. Syntax like this for defining a data element seems quite convenient.

Allocation(Param1 = Val1, Param2 = Val2 )

However, it does not support param names with spaces.

Allocation(Param 1 = Val1, Param 2 = Val2 )

Python parser friendly versions can look as follows, but not very user friendly.

Allocation(("Param 1",Val1), ("Param 2",Val1) )
Allocation(**{"Param 1":Val1, "Param 2":Val1} )

Is there a way to make this more readable in python?

A: 

You can do this:

def Allocation(**kwargs):
    print kwargs

myargs = {"Param 1":Val1, "Param 2":Val1}
Allocation(**myargs)

Edit: Your edit now includes my answer so no, there is no easier way to have spaces in keyword arguments.

Harley
A: 

Unless I am mistaking your basic premise here, there's nothing to stop you from writing a class that parses your own custom syntax, and then using that custom syntax as a single-argument string:

Allocation("Param 1=Check Up; Param 2=Mean Value Theorem;")

In this example, semicolons act as the name-value-pair separators, and equals represents the name-value separator. Moreover, you can easily configure your parser to accept custom delimiters as part of the object constructor.

If it seems too daunting to write a parser, consider that (for a syntax such as this) you could obtain your values by simply splitting the string on

/\s*;\s*/

and then on

/\s*=\s*/

to quickly obtain the name-value pairs. You also have the option to choose from any of several argument parsers already written for Python.

Admittedly, this does not use Python as the argument parser, which is a consideration you will have to balance against the simplicity of an approach such as this.

dreftymac
+2  A: 

I'd imagine that there would be some way to do it. But I feel compelled to ask, is there really a big enough difference in readability from this

Allocation(Param1 = Val1, Param2 = Val2 )

To this:

Allocation(Param 1 = Val1, Param 2 = Val2 )

to make that big a difference? I'm sure there's a way to do what you want to do, but my first concern is if the effort involved would be worth the result.

my goal is to provide a DSL which can be used for data entry into the system. In the above scenario, params would be people names and values would be percentages.

I have a better understanding of what you want to do now, but I still think that you might end up having to sacrifice some readability to get what you want. Personally, I would go with something like:

Allocation(
    { 'name1' : value1,
      'name1' : value2, }
)

If that's not something you can go with, then you might want to reconsider whether you want to use Python for your DSL or go with something home-grown. Allowing whitespace allows too many ambiguities for most programming languages to allow it.

If you still want to pursue this with using python, you might want to consider posting to the C-API SIG (SIGS) or maybe the python-dev list (as a last resort). The only way that I can see to do this would be to embed the python interpreter into a C/C++ program and do some kind of hacking with it (which can be difficult!).

Jason Baker
+1: param names with spaces isn't worth the agony, and doesn't really help. Use _'s instead of spaces.
S.Lott
my goal is to provide a DSL which can be used for data entry into the system. In the above scenario, params would be people names and values would be percentages.
Kozyarchuk
What's wrong with doing Allocation( name="some person", value=3.2 ) with one Allocation per person?
S.Lott
Yeah, I think that the way I'll do it. But seems a bit too verbose.
Kozyarchuk
+1  A: 

Here's my preference.

AllocationSet(
    Alloc( name="some name", value=1.23 ),
    Alloc( name="another name", value=2.34 ),
    Alloc( name="yet another name", value=4.56 ),
)

These are relatively easy class declarations to create. The resulting structure is pleasant to process, too.

S.Lott