@@ -266,6 +266,15 @@ def update(self, other) -> NoReturn:
266266 "use `.copy()` first to get a mutable version of the input dataset."
267267 )
268268
269+ def set_close (self , close : Callable [[], None ] | None ) -> None :
270+ raise AttributeError ("cannot modify a DatasetView()" )
271+
272+ def close (self ) -> None :
273+ raise AttributeError (
274+ "cannot close a DatasetView(). Close the associated DataTree node "
275+ "instead"
276+ )
277+
269278 # FIXME https://github.com/python/mypy/issues/7328
270279 @overload # type: ignore[override]
271280 def __getitem__ (self , key : Mapping ) -> Dataset : # type: ignore[overload-overlap]
@@ -633,7 +642,7 @@ def to_dataset(self, inherit: bool = True) -> Dataset:
633642 None if self ._attrs is None else dict (self ._attrs ),
634643 dict (self ._indexes if inherit else self ._node_indexes ),
635644 None if self ._encoding is None else dict (self ._encoding ),
636- self . _close ,
645+ None ,
637646 )
638647
639648 @property
@@ -796,6 +805,29 @@ def _repr_html_(self):
796805 return f"<pre>{ escape (repr (self ))} </pre>"
797806 return datatree_repr_html (self )
798807
808+ def __enter__ (self ) -> Self :
809+ return self
810+
811+ def __exit__ (self , exc_type , exc_value , traceback ) -> None :
812+ self .close ()
813+
814+ # DatasetView does not support close() or set_close(), so we reimplement
815+ # these methods on DataTree.
816+
817+ def _close_node (self ) -> None :
818+ if self ._close is not None :
819+ self ._close ()
820+ self ._close = None
821+
822+ def close (self ) -> None :
823+ """Close any files associated with this tree."""
824+ for node in self .subtree :
825+ node ._close_node ()
826+
827+ def set_close (self , close : Callable [[], None ] | None ) -> None :
828+ """Set the closer for this node."""
829+ self ._close = close
830+
799831 def _replace_node (
800832 self : DataTree ,
801833 data : Dataset | Default = _default ,
0 commit comments