f90nml icon indicating copy to clipboard operation
f90nml copied to clipboard

Allow to remove items while patching

Open letmaik opened this issue 6 years ago • 5 comments

I have the use case where I'd like to remove an existing key by somehome indicating this in the patch dictionary. I tried "key": None but that doesn't have any effect. How about introducing a special object that can be used for this purpose, like "key": f90nml.Delete?

letmaik avatar May 28 '18 09:05 letmaik

I'm guessing your use case is that you want to remove an entry while keeping the whitespace/comments in place, is that right? If so then I agree, this does not seem to be possible at the moment.

Namelists have some concept of null values, for example this is a valid namelist:

&test
   x=
/

which leaves x unchanged, so unfortunately 'key': None is not an option here. (Edit: In case it wasn't clear, I use None to indicate these null values.)

~~I'm reluctant to add special strings like f90nml.Delete to trigger certain actions, since they could (however unlikely) be valid namelists.~~ But we could add something like '_delete': ['x', 'y', ...] since tags starting with _ are not valid Fortran variables. (Edit: Sorry, I see you were suggesting specific objects, which is also a good idea.)

I've been adding these special tags to support other things like complex variables and starting index, so it ought not be a problem.

marshallward avatar May 28 '18 09:05 marshallward

I had a few mistakes in my last post, which I've edited, sorry about that.

I think that I'd probably prefer the special tag approach, since it would be more usable with the command line tool and more consistent with other convertible formats, e.g. JSON.

Would that work for you?

marshallward avatar May 28 '18 09:05 marshallward

I agree, yes, it makes more sense to use _delete.

letmaik avatar May 28 '18 11:05 letmaik

I have a workaround for this. I add '_delete' to my patch and iterate through the namelist deleting members contained in _delete and then removing '_delete' from the patch. Then I can patch like usual:

patch = {
    'time_control': {
        '_delete': ['debug_level']
        'field_to_set': 0
    }
}

keys = [(group, member) for group in patch for member in patch[group]]
for group, member in keys:
    if member == '_delete':
        for member_to_delete in patch[group][member]:
            del namelist[group][member_to_delete]
        del patch[group][member]

namelist.patch(patch)

This is a hack, but maybe it could it be a start for a proper feature addition?

sd-joseph avatar Jun 27 '19 23:06 sd-joseph

The long term plan (now very very long term) was to integrate this feature in to the new parser, but that's been in hold for a very long time.

So I'd say that if you have something that works then it'd be most welcome :).

marshallward avatar Jun 29 '19 14:06 marshallward