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
9 changes: 6 additions & 3 deletions flopy4/mf6/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,20 @@ class WriteError(Exception):
pass


def _load_mf6(path: Path) -> Component:
def _load_mf6(cls, path: Path) -> Component:
"""Load MF6 format file into a component instance."""
with open(path, "r") as fp:
return structure(load_mf6(fp), path)


def _load_json(path: Path) -> Component:
def _load_json(cls, path: Path) -> Component:
"""Load JSON format file into a component instance."""
with open(path, "r") as fp:
return structure(load_json(fp), path)


def _load_toml(path: Path) -> Component:
def _load_toml(cls, path: Path) -> Component:
"""Load TOML format file into a component instance."""
with open(path, "rb") as fp:
return structure(load_toml(fp), path)

Expand Down
13 changes: 5 additions & 8 deletions flopy4/mf6/component.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from abc import ABC
from collections.abc import MutableMapping
from os import PathLike
from pathlib import Path
from typing import Any, ClassVar, Optional

Expand Down Expand Up @@ -132,16 +133,12 @@ def get_dfn(cls) -> Dfn:
blocks=blocks,
)

def load(self, format: str = MF6) -> None:
@classmethod
def load(cls, path: str | PathLike, format: str = MF6) -> None:
"""Load the component and any children."""
# TODO: setting filename is a temp hack to get the parent's
# name as this component's filename stem, if it has one. an
# actual solution is to auto-set the filename when children
# are attached to parents.
self.filename = self.filename or self.default_filename()
self._load(format=format)
self = cls._load(path, format=format) # Get the instance
for child in self.children.values(): # type: ignore
child.load(format=format)
child.__class__.load(child.path, format=format)

def write(self, format: str = MF6, context: Optional[WriteContext] = None) -> None:
"""
Expand Down
18 changes: 15 additions & 3 deletions flopy4/mf6/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,21 @@ def path(self) -> Path:
self.filename = self.filename or self.default_filename()
return self.workspace / self.filename

def load(self, format=MF6):
with cd(self.workspace):
super().load(format=format)
@classmethod
def load(cls, path, format=MF6):
"""
Load the context component and children.

Children are loaded relative to the parent's workspace directory,
so their paths are resolved within that workspace.
"""
# Load the instance first
instance = cls._load(path, format=format)

# Load children within the workspace context
with cd(instance.workspace):
for child in instance.children.values(): # type: ignore
child.__class__.load(child.path, format=format)

def write(self, format=MF6, context=None):
with cd(self.workspace):
Expand Down
12 changes: 6 additions & 6 deletions flopy4/uio.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ def register_writer(self, cls, format, function):
raise ValueError(f"Writer for format {format} already registered.")
self._writers[cls, format] = function

def load(self, cls, instance, *args, format=None, **kwargs):
def load(self, cls, *args, format=None, **kwargs):
_load = self.get_loader(cls, format)
return _load(instance, *args, **kwargs)
return _load(cls, *args, **kwargs)

def write(self, cls, instance, *args, format=None, **kwargs):
_write = self.get_writer(cls, format)
Expand All @@ -76,16 +76,16 @@ class IO(property):
See the `astropy` source for more details/motivation.
"""

def __get__(self, instance, owner_cls):
return self.fget(instance, owner_cls)
def __get__(self, instance, cls):
return self.fget(instance, cls)


class IODescriptor:
"""Base class for file IO operation descriptors."""

def __init__(self, instance, cls, op: Op, registry: Registry | None = None):
self._registry = registry or DEFAULT_REGISTRY
self._instance = instance
self._instance = instance # None for loaders
self._cls = cls
self._op: Op = op

Expand All @@ -111,7 +111,7 @@ def __init__(self, instance, cls):
super().__init__(instance, cls, "load", registry=DEFAULT_REGISTRY)

def __call__(self, *args, **kwargs):
return self.registry.load(self._cls, self._instance, *args, **kwargs)
return self.registry.load(self._cls, *args, **kwargs)


class Writer(IODescriptor):
Expand Down
Loading
Loading