Skip to content

Commit 26f5f27

Browse files
committed
meh
1 parent e3710d0 commit 26f5f27

File tree

2 files changed

+67
-4
lines changed

2 files changed

+67
-4
lines changed

flopy4/mf6/codec/reader/transformer.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ def start(self, items: list[Any]) -> dict:
7676
if not isinstance(item, dict):
7777
continue
7878
for block_name, block_data in item.items():
79+
# Pluralize indexed blocks (e.g., period -> periods)
80+
if isinstance(block_data, dict) and all(isinstance(k, int) for k in block_data.keys()):
81+
# This is an indexed block, use plural form
82+
if not block_name.endswith('s'):
83+
block_name = block_name + 's'
84+
7985
if block_name not in merged:
8086
merged[block_name] = block_data
8187
else:
@@ -163,12 +169,27 @@ def filename(self, items: list[Any]) -> Path:
163169
def string(self, items: list[Any]) -> str:
164170
return items[0].strip("\"'")
165171

172+
def simple_string(self, items: list[Any]) -> str:
173+
"""Handle simple string (unquoted word or escaped string)."""
174+
return str(items[0]).strip("\"'")
175+
166176
def integer(self, items: list[Any]) -> int:
167177
return int(items[0])
168178

169179
def double(self, items: list[Any]) -> float:
170180
return float(items[0])
171181

182+
def number(self, items: list[Any]) -> int | float:
183+
"""Handle generic number (could be int or float)."""
184+
value = str(items[0])
185+
try:
186+
if "." in value or "e" in value.lower():
187+
return float(value)
188+
else:
189+
return int(value)
190+
except ValueError:
191+
return float(value)
192+
172193
def data(self, items: list[Any]) -> np.ndarray:
173194
return np.array(items)
174195

@@ -222,6 +243,10 @@ def block_index(self, items: list[Any]) -> int:
222243
"""Extract block index (e.g., period number)."""
223244
return items[0]
224245

246+
def stress_period_data(self, items: list[Any]) -> list[Any]:
247+
"""Handle stress period data (list of values for a single record)."""
248+
return items
249+
225250
@staticmethod
226251
def try_create_dataarray(array_info: dict) -> dict:
227252
control = array_info["control"]
@@ -251,6 +276,12 @@ def __default__(self, data, children, meta):
251276
# Unexpected structure, fall back to default
252277
return super().__default__(data, children, meta)
253278
elif data.endswith("_fields"):
279+
# Check if this is a period_fields which contains list data (stress_period_data)
280+
# rather than named field tuples
281+
if children and not isinstance(children[0], tuple):
282+
# This is list data (e.g., stress_period_data records)
283+
# Return as stress_period_data key
284+
return {"stress_period_data": children}
254285
return {item[0].lower(): item[1] for item in children}
255286
elif (field := self.fields.get(data, None)) is not None:
256287
if field.type == "keyword":

test/test_mf6_reader.py

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,10 @@ def test_transform_full_component():
162162
grammar = """
163163
start: block*
164164
block: options_block | arrays_block
165-
options_block: "begin"i "options"i options_vars "end"i "options"i
166-
arrays_block: "begin"i "arrays"i arrays_vars "end"i "arrays"i
167-
options_vars: (r2d2 | b | c | p)*
168-
arrays_vars: (x | y | z)*
165+
options_block: "begin"i "options"i options_fields "end"i "options"i
166+
arrays_block: "begin"i "arrays"i arrays_fields "end"i "arrays"i
167+
options_fields: (r2d2 | b | c | p)*
168+
arrays_fields: (x | y | z)*
169169
r2d2: "r2d2"i // keyword
170170
b: "b"i string
171171
c: "c"i integer
@@ -314,3 +314,35 @@ def test_transform_gwf_ic_file(model_workspace):
314314
assert isinstance(result, dict)
315315
assert "griddata" in result # IC has griddata block
316316
assert "strt" in result["griddata"] # Starting heads
317+
318+
319+
@pytest.mark.parametrize("model_workspace", ["mf6/example/ex-gwf-bcf2ss-p01a"], indirect=True)
320+
def test_transform_gwf_wel_file(model_workspace):
321+
"""Test transforming a parsed GWF WEL file into structured data."""
322+
323+
# Load the DFN for WEL
324+
dfns = load_flat("../modflow-devtools/autotest/temp/dfn/toml")
325+
wel_dfn = dfns["gwf-wel"]
326+
327+
# Find the WEL file
328+
wel_files = list(model_workspace.rglob("*.wel"))
329+
330+
# Skip if no WEL files (not all models have wells)
331+
if len(wel_files) == 0:
332+
pytest.skip("No WEL files found in this model")
333+
334+
wel_file = wel_files[0]
335+
parser = get_typed_parser("gwf-wel")
336+
transformer = TypedTransformer(dfn=wel_dfn)
337+
338+
# Read, parse, and transform
339+
with open(wel_file, "r") as f:
340+
content = f.read()
341+
342+
tree = parser.parse(content)
343+
result = transformer.transform(tree)
344+
345+
# Check structure
346+
assert isinstance(result, dict)
347+
assert "periods" in result # WEL has periods
348+
assert len(result["periods"]) > 0 # Should have at least one period

0 commit comments

Comments
 (0)