Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions flopy4/mf6/gwe/fmi.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# autogenerated file, do not modify
from pathlib import Path
from typing import ClassVar, Optional, Union

import attrs
import numpy as np

from flopy4.mf6.package import Package
from flopy4.mf6.schema import Column, Schema
from flopy4.mf6.spec import field
from flopy4.mf6.spec import field, path


@attrs.define(kw_only=True, slots=False)
Expand Down Expand Up @@ -42,7 +43,7 @@ class _PackagedataSchema(Schema):
@attrs.define
class PackagedataRow:
flowtype: Union[float, str]
fname: Union[float, str]
fname: Path = path(converter=Path, inout="filein")

def __iter__(self):
yield self.flowtype
Expand Down
5 changes: 3 additions & 2 deletions flopy4/mf6/gwe/ssm.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# autogenerated file, do not modify
from pathlib import Path
from typing import ClassVar, Optional, Union

import attrs
import numpy as np

from flopy4.mf6.package import Package
from flopy4.mf6.schema import Column, Schema
from flopy4.mf6.spec import field
from flopy4.mf6.spec import field, path


@attrs.define(kw_only=True, slots=False)
Expand Down Expand Up @@ -67,7 +68,7 @@ class _FileinputSchema(Schema):
@attrs.define
class FileinputRow:
pname: Union[float, str]
spc6_filename: Union[float, str]
spc6_filename: Path = path(converter=Path, inout="filein")
mixed: Optional[str] = None

def __iter__(self):
Expand Down
2 changes: 1 addition & 1 deletion flopy4/mf6/gwf/lak.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ class _TablesSchema(Schema):
@attrs.define
class TablesRow:
ifno: int
tab6_filename: Union[float, str]
tab6_filename: Path = path(converter=Path, inout="filein")

def __iter__(self):
yield self.ifno
Expand Down
5 changes: 3 additions & 2 deletions flopy4/mf6/gwt/fmi.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# autogenerated file, do not modify
from pathlib import Path
from typing import ClassVar, Optional, Union

import attrs
import numpy as np

from flopy4.mf6.package import Package
from flopy4.mf6.schema import Column, Schema
from flopy4.mf6.spec import field
from flopy4.mf6.spec import field, path


@attrs.define(kw_only=True, slots=False)
Expand Down Expand Up @@ -42,7 +43,7 @@ class _PackagedataSchema(Schema):
@attrs.define
class PackagedataRow:
flowtype: Union[float, str]
fname: Union[float, str]
fname: Path = path(converter=Path, inout="filein")

def __iter__(self):
yield self.flowtype
Expand Down
5 changes: 3 additions & 2 deletions flopy4/mf6/gwt/ssm.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# autogenerated file, do not modify
from pathlib import Path
from typing import ClassVar, Optional, Union

import attrs
import numpy as np

from flopy4.mf6.package import Package
from flopy4.mf6.schema import Column, Schema
from flopy4.mf6.spec import field
from flopy4.mf6.spec import field, path


@attrs.define(kw_only=True, slots=False)
Expand Down Expand Up @@ -67,7 +68,7 @@ class _FileinputSchema(Schema):
@attrs.define
class FileinputRow:
pname: Union[float, str]
spc6_filename: Union[float, str]
spc6_filename: Path = path(converter=Path, inout="filein")
mixed: Optional[str] = None

def __iter__(self):
Expand Down
6 changes: 6 additions & 0 deletions flopy4/mf6/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ def field(
oc_action: str | None = None,
oc_rtype: str | None = None,
time_series: bool = False,
pk: bool = False,
fk: str | None = None,
):
"""Define a codegen-v2 field: always a plain ``attrs.field()``.

Expand Down Expand Up @@ -92,6 +94,10 @@ def field(
metadata["oc_rtype"] = oc_rtype
if time_series:
metadata["time_series"] = True
if pk:
metadata["pk"] = True
if fk:
metadata["fk"] = fk
return attrs.field(
default=default,
validator=validator,
Expand Down
27 changes: 25 additions & 2 deletions flopy4/mf6/utils/codegen/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,29 @@ def _py_type(col: dict) -> str:
def _is_optional(col: dict) -> bool:
return bool(col.get("optional")) or col["role"] in ("boundname", "inline_keyword")

def _prefix_inout(col: dict) -> str:
"""MF6 inout direction implied by a row column's prefix tokens."""
return "fileout" if "FILEOUT" in (col.get("prefix") or "").upper().split() else "filein"

def _field_line(col: dict, *, optional: bool) -> str:
# File-reference columns (a fixed MF6 token or two before a filename,
# e.g. LAK tables' "TAB6 FILEIN <file>") are Path fields built via the
# same path() convention used for Package-level file fields, not the
# generic dtype-based Union[float, str] fallback below.
if col.get("prefix"):
inout = _prefix_inout(col)
if optional:
return (
f" {col['name']}: Optional[Path] = path(\n"
f' default=None, converter=_optional_path, inout="{inout}"\n'
f" )"
)
return f' {col["name"]}: Path = path(converter=Path, inout="{inout}")'
py_type = _py_type(col)
if optional:
return f" {col['name']}: Optional[{py_type}] = None"
return f" {col['name']}: {py_type}"

required = [col for col in schema_list if not _is_optional(col)]
optional = [col for col in schema_list if _is_optional(col)]
# Aux injection: only for period blocks. Standard stress packages (CHD,
Expand All @@ -689,11 +712,11 @@ def _is_optional(col: dict) -> bool:
lines = [" @attrs.define"]
lines.append(f" class {class_name}:")
for col in required:
lines.append(f" {col['name']}: {_py_type(col)}")
lines.append(_field_line(col, optional=False))
if has_positional_aux:
lines.append(" aux: tuple = ()")
for col in optional:
lines.append(f" {col['name']}: Optional[{_py_type(col)}] = None")
lines.append(_field_line(col, optional=True))
lines.append("")
lines.append(" def __iter__(self):")
for col in required:
Expand Down
13 changes: 9 additions & 4 deletions flopy4/mf6/utils/codegen/make.py
Original file line number Diff line number Diff line change
Expand Up @@ -608,11 +608,16 @@ def _new_codegen_imports(
has_union = any(
col.get("time_series") or col.get("dtype") == "np.object_"
for col in _all_schema_cols
if col.get("role") not in ("keystring_value", "boundname")
if col.get("role") not in ("keystring_value", "boundname") and not col.get("prefix")
)
# prefix= row columns (file references, e.g. LAK tables' TAB6 FILEIN)
# become Path fields via path() in row_class(), not Union[float, str].
_row_path_cols = [col for col in _all_schema_cols if col.get("prefix")]
has_row_path_cols = bool(_row_path_cols)
has_optional_row_path_cols = any(col.get("optional") for col in _row_path_cols)

stdlib: list[str] = []
if has_path or has_injected_paths or has_file_records:
if has_path or has_injected_paths or has_file_records or has_row_path_cols:
stdlib.append("from pathlib import Path")
typing_parts: list[str] = []
if has_classvar:
Expand Down Expand Up @@ -643,7 +648,7 @@ def _new_codegen_imports(
_spec_parts: list[str] = []
if has_field_call:
_spec_parts.append("field")
if has_path_call:
if has_path_call or has_row_path_cols:
_spec_parts.append("path")
if _spec_parts:
flopy4.append(f"from flopy4.mf6.spec import {', '.join(sorted(_spec_parts))}")
Expand All @@ -652,7 +657,7 @@ def _new_codegen_imports(
_types_parts.append("IntArrayLike")
if needs_float_arraylike:
_types_parts.append("FloatArrayLike")
if has_file_records or has_injected_paths:
if has_file_records or has_injected_paths or has_optional_row_path_cols:
_types_parts.append("_optional_path")
if _types_parts:
flopy4.append(f"from flopy4.mf6._types import {', '.join(sorted(_types_parts))}")
Expand Down
Loading