diff --git a/foamlib/_files/_io.py b/foamlib/_files/_io.py index 541678a..b33d1ef 100644 --- a/foamlib/_files/_io.py +++ b/foamlib/_files/_io.py @@ -43,13 +43,15 @@ def __exit__( self.__defer_io -= 1 if self.__defer_io == 0: assert self.__parsed is not None - if self.__parsed.modified or self.__missing: + if self.__parsed.modified: contents = self.__parsed.contents if self.path.suffix == ".gz": contents = gzip.compress(contents) self.path.write_bytes(contents) + self.__parsed.modified = False + self.__missing = False def _get_parsed(self, *, missing_ok: bool = False) -> Parsed: if not self.__defer_io: @@ -69,7 +71,7 @@ def _get_parsed(self, *, missing_ok: bool = False) -> Parsed: assert self.__parsed is not None assert self.__missing is not None - if self.__missing and not missing_ok: + if self.__missing and not self.__parsed.modified and not missing_ok: raise FileNotFoundError(self.path) return self.__parsed diff --git a/foamlib/_files/_parsing.py b/foamlib/_files/_parsing.py index 873a988..f0a0056 100644 --- a/foamlib/_files/_parsing.py +++ b/foamlib/_files/_parsing.py @@ -1,5 +1,4 @@ import array -import contextlib import sys from typing import Tuple, Union, cast @@ -273,22 +272,24 @@ def put( ) -> None: assert not isinstance(data, Mapping) - with contextlib.suppress(KeyError): - del self[keywords] - start, end = self.entry_location(keywords, missing_ok=True) - diff = len(content) - (end - start) - self._parsed[keywords] = (start, data, end + diff) + diff = len(content) - (end - start) for k, (s, d, e) in self._parsed.items(): if s > end: self._parsed[k] = (s + diff, d, e + diff) elif e > start: self._parsed[k] = (s, d, e + diff) + self._parsed[keywords] = (start, data, end + diff) + self.contents = self.contents[:start] + content + self.contents[end:] self.modified = True + for k in list(self._parsed): + if keywords != k and keywords == k[: len(keywords)]: + del self._parsed[k] + def __delitem__(self, keywords: Union[str, Tuple[str, ...]]) -> None: if isinstance(keywords, str): keywords = (keywords,) @@ -327,8 +328,9 @@ def entry_location( except KeyError: if missing_ok: if len(keywords) > 1: - _, _, end = self._parsed[keywords[:-1]] - end -= 1 + assert self[keywords[:-1]] is ... + start, end = self.entry_location(keywords[:-1]) + end = self.contents.rindex(b"}", start, end) else: end = len(self.contents)