I would like to share a short update on nml-tools, a small Python tool that generates Fortran namelist modules from YAML/JSON schema-like files.
The idea is to describe each namelist once and generate the repetitive pieces from that description: Fortran declarations, init / set / from_file helpers, validation, Markdown documentation, template namelist files, and optionally f2py/Python wrapper code.
It is available on PyPI:
pip install nml-tools
Basic Example
A schema describes the namelist block and its entries:
title: Optimization settings
x-fortran-namelist: optimization
type: object
required: [max_iter]
properties:
max_iter:
type: integer
x-fortran-kind: i4
default: 100
method:
type: string
x-fortran-len: 16
enum: [bfgs, nelder_mead]
default: bfgs
With a small project config, nml-tools generate --config nml-config.toml can emit the Fortran module, documentation, and a template namelist.
The config can be a standalone nml-config.toml file or a [tool.nml-tools] section inside pyproject.toml, which is convenient for Python/f2py packages.
Reusable Schema Definitions
Version 0.3 adds $defs / $ref support, so common field definitions can be shared between namelists:
$defs:
positive_count:
type: integer
minimum: 1
x-fortran-kind: i4
properties:
n_steps:
$ref: "#/$defs/positive_count"
description: Number of time steps.
References can also point to local YAML/JSON files next to the schema, which is useful for larger applications with several namelists.
One-Level Derived Types
nml-tools can now model one level of Fortran derived-type fields. A type can be generated into the helper module or imported from an application module:
properties:
period:
type: object
x-fortran-type: period_t
required: [start_year, end_year]
properties:
start_year:
type: integer
end_year:
type: integer
Generated namelist input uses normal Fortran component syntax:
&run
period%start_year = 2001
period%end_year = 2010
/
For now this is deliberately conservative: derived-type members must be scalar intrinsic values, and nested derived types or array members are not supported.
f2py/Python Wrappers
For projects that expose Fortran configuration to Python, v0.3 can generate f2py-facing wrapper code and a small Python shim. The Python API keeps derived values natural:
cfg.set(
period={"start_year": 2001, "end_year": 2010},
method="bfgs",
)
Internally the f2py ABI stays intrinsic-only, avoiding derived-type dummy arguments across the Python/Fortran boundary. The generated wrapper works with Fortran-owned configuration objects through opaque integer handles, so Python does not need to know the layout of the generated Fortran type.
File Profiles And Templates
There is also better support for projects where one physical namelist file contains several namelist blocks:
[[namelists]]
name = "run"
schema = "schemas/run.yml"
[[namelists]]
name = "physics"
schema = "schemas/physics.yml"
[[file_profiles]]
name = "main"
default_file = "run.nml"
namelists = ["run", "physics"]
[[templates]]
path = "templates/run.nml"
profile = "main"
doc_mode = "documented"
value_mode = "filled"
This lets generated templates and validation operate on the same named file layout.
The repository contains small reference examples for the main workflows, including plain Fortran generation, f2py packaging, $ref reuse, derived types, and multi-namelist file profiles.
Feedback from Fortran users would be very welcome, especially around the schema syntax, derived-type restrictions, and what a convenient namelist editing workflow should look like.