Skip to content

Commit af8dc52

Browse files
committed
refactor(params): consolidate codegen, eliminate duplicate description/namelist systems
- Delete namelist_targets.py: NAMELIST_VARS moved to definitions.py (one file to edit when adding a param); CASE_OPT_EXCLUDE was a duplicate of CASE_OPT_PARAMS - Delete _FALLBACK_PARAMS (380 hardcoded lines) in namelist_parser.py: replaced by _fallback_params() that derives the same data from NAMELIST_VARS at runtime - Delete _SIMPLE_DESCS (145 lines) and _auto_describe in definitions.py: _r() now populates ParamDef.description from descriptions.get_description() so callers can read param.description directly; three callers (docs_gen, json_schema_gen, params_cmd) migrated off the external get_description() import - Delete _PREFIX_DESCS and _ATTR_DESCS (113 lines) in definitions.py: dead code after _auto_describe was removed - Add resolve_namelist_content() and TARGET_FROM_DIR to fortran_gen.py: single canonical helper for the detect-generated-include pattern duplicated across namelist_parser.py and lint_param_docs.py - Consolidate NAMELIST_VARS to use _nv() helper: 200-line explicit dict replaced by grouped calls (~75 lines); cmake_gen.py refactored to use get_generated_files() - Switch test runner from hardcoded unittest module list to pytest discover; add pytest to pyproject.toml; move three orphaned test files into params_tests/ - CMake: stamp-based caching so Fortran codegen only reruns when inputs change - Extract _format_constraints_cell() in docs_gen.py: 5-line pattern duplicated across pattern-view and full-table rendering paths - Inline 4 single-use wrapper functions in case_dicts.py Net vs master: -564 lines
1 parent bdd386a commit af8dc52

18 files changed

Lines changed: 282 additions & 1381 deletions

CMakeLists.txt

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -464,16 +464,37 @@ endmacro()
464464
# Generate Fortran parameter namelist/decl includes into the per-target build
465465
# include directories before HANDLE_SOURCES globs them for Fypp.
466466
find_package(Python3 REQUIRED COMPONENTS Interpreter)
467-
execute_process(
468-
COMMAND "${Python3_EXECUTABLE}"
469-
"${CMAKE_CURRENT_SOURCE_DIR}/toolchain/mfc/params/generators/cmake_gen.py"
470-
"${CMAKE_BINARY_DIR}"
471-
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
472-
RESULT_VARIABLE _mfc_gen_result
473-
ERROR_VARIABLE _mfc_gen_error
467+
set(_mfc_gen_stamp "${CMAKE_BINARY_DIR}/mfc_params_gen.stamp")
468+
set(_mfc_gen_inputs
469+
"${CMAKE_CURRENT_SOURCE_DIR}/toolchain/mfc/params/generators/cmake_gen.py"
470+
"${CMAKE_CURRENT_SOURCE_DIR}/toolchain/mfc/params/generators/fortran_gen.py"
471+
"${CMAKE_CURRENT_SOURCE_DIR}/toolchain/mfc/params/namelist_targets.py"
472+
"${CMAKE_CURRENT_SOURCE_DIR}/toolchain/mfc/params/definitions.py"
474473
)
475-
if(NOT _mfc_gen_result EQUAL 0)
476-
message(FATAL_ERROR "Fortran param generation failed:\n${_mfc_gen_error}")
474+
set(_mfc_needs_regen FALSE)
475+
if(NOT EXISTS "${_mfc_gen_stamp}")
476+
set(_mfc_needs_regen TRUE)
477+
else()
478+
foreach(_input IN LISTS _mfc_gen_inputs)
479+
if("${_input}" IS_NEWER_THAN "${_mfc_gen_stamp}")
480+
set(_mfc_needs_regen TRUE)
481+
break()
482+
endif()
483+
endforeach()
484+
endif()
485+
if(_mfc_needs_regen)
486+
execute_process(
487+
COMMAND "${Python3_EXECUTABLE}"
488+
"${CMAKE_CURRENT_SOURCE_DIR}/toolchain/mfc/params/generators/cmake_gen.py"
489+
"${CMAKE_BINARY_DIR}"
490+
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
491+
RESULT_VARIABLE _mfc_gen_result
492+
ERROR_VARIABLE _mfc_gen_error
493+
)
494+
if(NOT _mfc_gen_result EQUAL 0)
495+
message(FATAL_ERROR "Fortran param generation failed:\n${_mfc_gen_error}")
496+
endif()
497+
file(TOUCH "${_mfc_gen_stamp}")
477498
endif()
478499

479500
HANDLE_SOURCES(pre_process ON)

src/simulation/m_global_parameters.fpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,6 @@ module m_global_parameters
7070
integer :: num_dims !< Number of spatial dimensions
7171
integer :: num_vels !< Number of velocity components (different from num_dims for mhd)
7272
#:endif
73-
! mpp_lim, time_stepper, prim_vars_wrt now in generated_decls.fpp
74-
7573
#:if MFC_CASE_OPTIMIZATION
7674
integer, parameter :: recon_type = ${recon_type}$ !< Reconstruction type
7775
integer, parameter :: weno_polyn = ${weno_polyn}$ !< Degree of the WENO polynomials (polyn)

toolchain/bootstrap/lint.sh

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,8 @@ ruff check benchmarks/*/case.py
3232
if [ "$RUN_TESTS" = true ]; then
3333
log "(venv) Running$MAGENTA unit tests$COLOR_RESET on$MAGENTA MFC$COLOR_RESET's $MAGENTA""toolchain$COLOR_RESET."
3434

35-
# Run tests as modules from the toolchain directory to resolve relative imports
3635
cd toolchain
37-
python3 -m unittest mfc.params_tests.test_registry mfc.params_tests.test_definitions mfc.params_tests.test_validate mfc.params_tests.test_integration -v
38-
python3 -m unittest mfc.cli.test_cli -v
39-
python3 -m unittest mfc.viz.test_viz -v
40-
python3 -m unittest mfc.run.test_archive -v
36+
python3 -m pytest . -v
4137
cd - > /dev/null
4238
fi
4339

toolchain/mfc/lint_param_docs.py

Lines changed: 2 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -80,49 +80,6 @@ def _param_appears_in_case_md(param_base: str, tokens: set[str], text: str) -> b
8080
return False
8181

8282

83-
def _parse_namelist_params(fpp_path: Path) -> set[str]:
84-
"""Parse parameter names from a namelist /user_inputs/ block in an fpp file."""
85-
text = fpp_path.read_text(encoding="utf-8")
86-
87-
# If the namelist is in a #:include'd generated file, generate in-memory.
88-
if re.search(r"#:include\s+'generated_namelist\.fpp'", text):
89-
_target_map = {"pre_process": "pre", "simulation": "sim", "post_process": "post"}
90-
short = _target_map.get(fpp_path.parent.name)
91-
if short:
92-
from mfc.params.generators.fortran_gen import generate_namelist_fpp
93-
94-
text = generate_namelist_fpp(short)
95-
96-
params = set()
97-
98-
in_namelist = False
99-
accum = ""
100-
for line in text.splitlines():
101-
stripped = line.strip()
102-
if stripped.startswith("!") or stripped.startswith("#:") or stripped.startswith("#"):
103-
continue
104-
lower = stripped.lower()
105-
if "namelist /user_inputs/" in lower:
106-
idx = lower.index("/user_inputs/") + len("/user_inputs/")
107-
accum += " " + stripped[idx:]
108-
in_namelist = accum.rstrip().endswith("&")
109-
continue
110-
if in_namelist:
111-
if stripped.startswith("&"):
112-
stripped = stripped[1:]
113-
accum += " " + stripped
114-
if not accum.rstrip().endswith("&"):
115-
in_namelist = False
116-
117-
accum = accum.replace("&", " ")
118-
for raw_token in accum.split(","):
119-
name = raw_token.strip()
120-
if name and re.match(r"^[a-zA-Z_]\w*$", name):
121-
params.add(name)
122-
123-
return params
124-
125-
12683
def check_descriptions_in_case_md(repo_root: Path) -> list[str]:
12784
"""Tier 1, Check 1+2: Params with DESCRIPTIONS entries should appear in case.md."""
12885
REGISTRY, DESCRIPTIONS = _import_registry(repo_root)
@@ -185,13 +142,14 @@ def _is_derived_type_parent_or_field(name: str, all_params: dict) -> bool:
185142
def check_namelist_registry_sync(repo_root: Path) -> list[str]:
186143
"""Tier 2: Unknown Fortran namelist params must be in REGISTRY (blocking)."""
187144
REGISTRY, _ = _import_registry(repo_root)
145+
from mfc.params.namelist_parser import parse_namelist_from_file
188146

189147
errors = []
190148
startup_files = sorted((repo_root / "src").rglob("m_start_up.fpp"))
191149
all_params = REGISTRY.all_params
192150

193151
for fpp in startup_files:
194-
nl_params = _parse_namelist_params(fpp)
152+
nl_params = parse_namelist_from_file(fpp)
195153
rel = fpp.relative_to(repo_root)
196154

197155
for p in sorted(nl_params):

0 commit comments

Comments
 (0)