Skip to content

migrate object model from attrs to pydantic - #367

Draft
wpbonelli wants to merge 6 commits into
modflowpy:developfrom
wpbonelli:pydantic-plan
Draft

wpbonelli wants to merge 6 commits into
modflowpy:developfrom
wpbonelli:pydantic-plan

Conversation

@wpbonelli

Copy link
Copy Markdown
Member

#282

This PR can live for some time while we refine it and evaluate whether the switch is worth it

wpbonelli and others added 4 commits September 23, 2026 08:37
Squash of the pydantic-plan branch (backup: pydantic-plan-backup):

- docs: revised attrs->pydantic object-model plan and prototypes (Dis,
  list-heavy package, Record/Item, keystring-union-arm coercion)
- Stage 1: Record/Item on pydantic.dataclasses.dataclass
- Stages 2-3.5: Component, Package, and remaining hand-written
  Component-tree classes
- Stage 4: codegen emits pydantic dataclasses
- Stage 5: regenerate the 61 codegen-generated package files
- Stages 6-7: consumer surface and fixes from real-corpus and full
  test-suite runs
- codegen: drop maxbound from G-variant packages (replaces the interim
  auto_from restore), with docs recording the fix

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Untrack the pydantic planning doc and prototypes (kept locally)
- Drop the hardcoded maxbound -> auto_from fallback in codegen; G-variant
  maxbound is a plain optional field again (devtools modflowpy#366), and generated
  packages now match develop apart from the dataclass decorator
- Remove leftover attrs: drop attrs/cattrs deps, rename attrs_xarray to
  dataclass_xarray, port test_uio, rewrite attrs-history comments, update
  the cattrs references in sdd.md
- Fix equality: subclass-generated __eq__ overrode Component's, so _parent
  and dims were compared; use compare=False on _parent instead
- Make Component.dims a construction-only InitVar threaded through the
  __post_init__ chain, rather than a stored field

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Add pydantic_fields() and field_meta() helpers; pydantic doesn't declare
  __pydantic_fields__ on decorated classes, and types json_schema_extra
  as a JSON dict or callable, so direct access fails type checking
- Route all field and metadata reads through them
- Drop dead array-coercion branches in the Disv __post_init__s (the field
  validators already coerce) and give Tdis perlen/nstp/tsmult array
  defaults so their declared types hold
- Smaller narrowing fixes surfaced once field types became visible

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- name: str with a subclass-aware default via a field validator
  (validate_default=True), replacing the post-init fill-in; drops the
  now-unneeded attr-defined ignores on .name
- workspace property returns Path and raises if read before it's resolved;
  Context checks use isinstance instead of hasattr

mypy flopy4 is now clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@wpbonelli wpbonelli added this to the MMP milestone Sep 23, 2026
@wpbonelli wpbonelli added question Information or decisions required refactor labels Sep 23, 2026
wpbonelli and others added 2 commits September 23, 2026 13:54
- filename is Optional[Path] (str still accepted): it's a workspace-relative
  path, and name-file entries can include subdirectories
- Every path written into an input file uses as_posix() so files are
  portable across platforms: name-file bindings, DFN file records, list
  rows, records, scalar options, and OPEN/CLOSE array references
- Drop the str() workarounds from the frenchman-flat example

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
_coerce_griddata looked up a "dfn_type" metadata key that nothing sets,
so layered griddata was always cast to float64. A scalar idomain was
then written as a float CONSTANT, which the macOS mf6 build rejects.
Resolve the dtype from the field annotation, as Package does.

The netcdf integration tests compared against str(path), which fails
on Windows now that written paths use POSIX separators.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JhSQ3nPJL9HXGAS6LmbMVw

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

question Information or decisions required refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant