f90nml: patching a repeated section on a namelist returns an unclear message

Related to esm-tools/esm_tools#843

Problem description

When loading a namelist with repeated sections, and then I try to patch one or several repeated sections, I get the following error:

AttributeError: 'Cogroup' object has no attribute 'update'

I understand it is not possible to update repeated sections, as it is not clear which one f90nml should patch. However, I find the error message misleading.

Example

To reproduce the error you can write the following fort.4 namelist:

&NAMDIM
    NPROMA = -8, 
/

&NAMPAR0
    LSTATS = true,
    LDETAILED_STATS = false,
    LSYNCSTATS = false,
    MP_TYPE = 2,
    MBX_SIZE = 32000000,
    NPROC = 144,      ! Number of MPI ranks (cores of no OpenMP)
    NOUTPUT = 1,
/

&NAEPHY
    LEPHYS = true,
    LERADI = true,
    LELAIV = false,
/

&NAERAD
    NRPROMA = -8, 
    CRTABLEDIR = "./rtables/",  ! Modify this for your installation, note trailing /
/

&NAMPAR0
/
&NAEPHY
/
&NAERAD
/

Then you can use the following python3 script to reproduce the error:

import f90nml

nml = f90nml.read("fort.4")

changes = { 
    "namdim": {
        "nproma": 0
    }   
}

nml.patch(changes)

print(nml)
print("Changing variables in non-repeated sections works!")
print()
print("Here comes the problem:")

changes = { 
    "nampar0": {
        "lstats": False
    },  
    "naephy": {
        "leradi": False
    },
    "naerad": {
        "nrproma": 0
    },
}

nml.patch(changes)

Suggested solution

Ideally, the user should be reported which variables are problematic in this context. I have sketched a very rough solution with the desired behaviour for these lines: https://github.com/marshallward/f90nml/blob/2a8663aa7dfc06a446fbab6aae20d928f694f3fb/f90nml/namelist.py#L649-L658

The rough solution:

    def patch(self, nml_patch):
        """Update the namelist from another partial or full namelist.

        This is different from the intrinsic `update()` method, which replaces
        a namelist section.  Rather, it updates the values within a section.
        """
+       conflicting_repeated_secs = [] 
        for sec in nml_patch:
            if sec not in self:
                self[sec] = Namelist()
-           self[sec].update(nml_patch[sec])
+           try: 
+               self[sec].update(nml_patch[sec])
+           except AttributeError:
+               conflicting_repeated_secs.append(sec)
+       if conflicting_repeated_secs:
+           raise AttributeError(
+               "The following sections are repeated in the namelist and cannot be "
+               f"updated: {conflicting_repeated_secs}"
+           )  

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 17 (9 by maintainers)

Most upvoted comments

I can reproduce this. This is due to the recent “Cogroup” support for repeated namelist groups.

Thanks for reporting this, I will look over your proposed solution.