foamlib 1.4.2__tar.gz → 1.4.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {foamlib-1.4.2 → foamlib-1.4.4}/PKG-INFO +2 -2
- {foamlib-1.4.2 → foamlib-1.4.4}/README.md +1 -1
- {foamlib-1.4.2 → foamlib-1.4.4}/pyproject.toml +1 -1
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_cases/base.py +1 -1
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_files/_parsing/_elements.py +61 -40
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_files/_parsing/parsing.py +80 -4
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_files/_serialization.py +5 -15
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_files/_typing.py +25 -4
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_files/files.py +240 -220
- {foamlib-1.4.2 → foamlib-1.4.4}/LICENSE.txt +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/__init__.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_cases/__init__.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_cases/_run.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_cases/_subprocess.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_cases/_util.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_cases/async_.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_cases/slurm.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_cases/sync.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_files/__init__.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_files/_common.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_files/_io.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_files/_parsing/__init__.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_files/_parsing/_grammar.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_files/_util.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/_files/types.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/postprocessing/__init__.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/postprocessing/load_tables.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/postprocessing/table_reader.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/preprocessing/__init__.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/preprocessing/case_modifier.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/preprocessing/grid_parameter_sweep.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/preprocessing/of_dict.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/preprocessing/parameter_study.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/preprocessing/system.py +0 -0
- {foamlib-1.4.2 → foamlib-1.4.4}/src/foamlib/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: foamlib
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.4
|
|
4
4
|
Summary: Pythonic interface for working with OpenFOAM
|
|
5
5
|
Author: Gabriel S. Gerlero
|
|
6
6
|
Author-email: Gabriel S. Gerlero <ggerlero@cimec.unl.edu.ar>
|
|
@@ -330,4 +330,4 @@ If you use **foamlib** in your research, please cite our paper:
|
|
|
330
330
|
|
|
331
331
|
## 👟 Footnotes
|
|
332
332
|
|
|
333
|
-
<a id="benchmark">[1]</a> foamlib 1.
|
|
333
|
+
<a id="benchmark">[1]</a> foamlib 1.4.4 vs. PyFoam 2023.7 (Python 3.11.13) on an M3 MacBook Air. [Benchmark script](https://github.com/gerlero/foamlib/blob/main/benchmark/benchmark.py).
|
|
@@ -285,4 +285,4 @@ If you use **foamlib** in your research, please cite our paper:
|
|
|
285
285
|
|
|
286
286
|
## 👟 Footnotes
|
|
287
287
|
|
|
288
|
-
<a id="benchmark">[1]</a> foamlib 1.
|
|
288
|
+
<a id="benchmark">[1]</a> foamlib 1.4.4 vs. PyFoam 2023.7 (Python 3.11.13) on an M3 MacBook Air. [Benchmark script](https://github.com/gerlero/foamlib/blob/main/benchmark/benchmark.py).
|
|
@@ -89,7 +89,7 @@ class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"], os.PathLike[str]):
|
|
|
89
89
|
@override
|
|
90
90
|
def __len__(self) -> int:
|
|
91
91
|
"""Return the number of field files in this time directory."""
|
|
92
|
-
return
|
|
92
|
+
return sum(1 for _ in iter(self))
|
|
93
93
|
|
|
94
94
|
def __delitem__(self, name: str, /) -> None:
|
|
95
95
|
"""Delete the field file with the given name in this time directory."""
|
|
@@ -31,11 +31,11 @@ from numpy.typing import DTypeLike
|
|
|
31
31
|
from .._common import dict_from_items
|
|
32
32
|
from .._typing import Dict, SubDict
|
|
33
33
|
|
|
34
|
+
_FLOAT_PATTERN = r"(?i:[+-]?(?:(?:\d+\.?\d*(?:e[+-]?\d+)?)|nan|inf(?:inity)?))"
|
|
35
|
+
_INT_PATTERN = r"-?\d+"
|
|
34
36
|
|
|
35
|
-
class ASCIINumericList(ParserElement):
|
|
36
|
-
_FLOAT_PATTERN = r"(?i:[+-]?(?:(?:\d+\.?\d*(?:e[+-]?\d+)?)|nan|inf(?:inity)?))"
|
|
37
|
-
_INT_PATTERN = r"-?\d+"
|
|
38
37
|
|
|
38
|
+
class ASCIINumericList(ParserElement):
|
|
39
39
|
def __init__(
|
|
40
40
|
self,
|
|
41
41
|
dtype: DTypeLike,
|
|
@@ -54,38 +54,41 @@ class ASCIINumericList(ParserElement):
|
|
|
54
54
|
def _generateDefaultName(self) -> str:
|
|
55
55
|
return self.name
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
self, instring: str, loc: int, do_actions: bool = True
|
|
57
|
+
def __parse(
|
|
58
|
+
self, instring: str, loc: int, *, assume_no_ignores: bool = False
|
|
60
59
|
) -> tuple[int, ParseResults]:
|
|
61
60
|
spacing_pattern = "|".join(re.escape(c) for c in self.whiteChars)
|
|
62
61
|
assert spacing_pattern
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
63
|
+
if assume_no_ignores:
|
|
64
|
+
ignore_pattern = ""
|
|
65
|
+
else:
|
|
66
|
+
assert all(
|
|
67
|
+
isinstance(ignore_expr, Suppress)
|
|
68
|
+
and isinstance(ignore_expr.expr, Regex)
|
|
69
|
+
for ignore_expr in self.ignoreExprs
|
|
70
|
+
)
|
|
71
|
+
ignore_pattern = "|".join(
|
|
72
|
+
ignore_expr.expr.re.pattern # ty: ignore[unresolved-attribute]
|
|
73
|
+
for ignore_expr in self.ignoreExprs
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
if ignore_pattern:
|
|
77
|
+
spacing_pattern = f"{spacing_pattern}|{ignore_pattern}"
|
|
75
78
|
|
|
76
79
|
if np.issubdtype(self._dtype, np.floating):
|
|
77
|
-
|
|
80
|
+
number_pattern = _FLOAT_PATTERN
|
|
78
81
|
elif np.issubdtype(self._dtype, np.integer):
|
|
79
|
-
|
|
82
|
+
number_pattern = _INT_PATTERN
|
|
80
83
|
else:
|
|
81
84
|
msg = f"Unsupported dtype {self._dtype}"
|
|
82
85
|
raise TypeError(msg)
|
|
83
86
|
|
|
84
87
|
if self._elshape:
|
|
85
88
|
(dim,) = self._elshape
|
|
86
|
-
element_pattern = rf"\((?:{spacing_pattern})*(?:{
|
|
89
|
+
element_pattern = rf"\((?:{spacing_pattern})*(?:{number_pattern}(?:{spacing_pattern})*){{{dim}}}\)"
|
|
87
90
|
else:
|
|
88
|
-
element_pattern =
|
|
91
|
+
element_pattern = number_pattern
|
|
89
92
|
|
|
90
93
|
regular_pattern = re.compile(
|
|
91
94
|
rf"(\d*)(?:{spacing_pattern})*\((?:{spacing_pattern})*((?:{element_pattern}(?:{spacing_pattern})*)*)\)"
|
|
@@ -158,6 +161,15 @@ class ASCIINumericList(ParserElement):
|
|
|
158
161
|
self,
|
|
159
162
|
)
|
|
160
163
|
|
|
164
|
+
@override
|
|
165
|
+
def parseImpl(
|
|
166
|
+
self, instring: str, loc: int, do_actions: bool = True
|
|
167
|
+
) -> tuple[int, ParseResults]:
|
|
168
|
+
try:
|
|
169
|
+
return self.__parse(instring, loc, assume_no_ignores=True)
|
|
170
|
+
except ParseException:
|
|
171
|
+
return self.__parse(instring, loc)
|
|
172
|
+
|
|
161
173
|
|
|
162
174
|
_EAGER_INTEGER = Word(nums).add_parse_action(
|
|
163
175
|
lambda tks: int(tks[0]), call_during_try=True
|
|
@@ -210,8 +222,6 @@ def binary_numeric_list(
|
|
|
210
222
|
|
|
211
223
|
|
|
212
224
|
class ASCIIFacesLikeList(ParserElement):
|
|
213
|
-
_INT_PATTERN = ASCIINumericList._INT_PATTERN
|
|
214
|
-
|
|
215
225
|
def __init__(self) -> None:
|
|
216
226
|
super().__init__()
|
|
217
227
|
self.name = "ASCIIFacesLikeList"
|
|
@@ -220,27 +230,29 @@ class ASCIIFacesLikeList(ParserElement):
|
|
|
220
230
|
def _generateDefaultName(self) -> str:
|
|
221
231
|
return self.name
|
|
222
232
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
self, instring: str, loc: int, do_actions: bool = True
|
|
233
|
+
def __parse(
|
|
234
|
+
self, instring: str, loc: int, *, assume_no_ignores: bool = False
|
|
226
235
|
) -> tuple[int, ParseResults]:
|
|
227
236
|
spacing_pattern = "|".join(re.escape(c) for c in self.whiteChars)
|
|
228
237
|
assert spacing_pattern
|
|
229
238
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
239
|
+
if assume_no_ignores:
|
|
240
|
+
ignore_pattern = ""
|
|
241
|
+
else:
|
|
242
|
+
assert all(
|
|
243
|
+
isinstance(ignore_expr, Suppress)
|
|
244
|
+
and isinstance(ignore_expr.expr, Regex)
|
|
245
|
+
for ignore_expr in self.ignoreExprs
|
|
246
|
+
)
|
|
247
|
+
ignore_pattern = "|".join(
|
|
248
|
+
ignore_expr.expr.re.pattern # ty: ignore[unresolved-attribute]
|
|
249
|
+
for ignore_expr in self.ignoreExprs
|
|
250
|
+
)
|
|
251
|
+
if ignore_pattern:
|
|
252
|
+
spacing_pattern = f"{spacing_pattern}|{ignore_pattern}"
|
|
253
|
+
|
|
254
|
+
three_face_pattern = rf"3(?:{spacing_pattern})*\((?:{spacing_pattern})*(?:{_INT_PATTERN}(?:{spacing_pattern})*){{3}}\)"
|
|
255
|
+
four_face_pattern = rf"4(?:{spacing_pattern})*\((?:{spacing_pattern})*(?:{_INT_PATTERN}(?:{spacing_pattern})*){{4}}\)"
|
|
244
256
|
|
|
245
257
|
face_pattern = rf"(?:{three_face_pattern})|(?:{four_face_pattern})"
|
|
246
258
|
|
|
@@ -291,6 +303,15 @@ class ASCIIFacesLikeList(ParserElement):
|
|
|
291
303
|
self,
|
|
292
304
|
)
|
|
293
305
|
|
|
306
|
+
@override
|
|
307
|
+
def parseImpl(
|
|
308
|
+
self, instring: str, loc: int, do_actions: bool = True
|
|
309
|
+
) -> tuple[int, ParseResults]:
|
|
310
|
+
try:
|
|
311
|
+
return self.__parse(instring, loc, assume_no_ignores=True)
|
|
312
|
+
except ParseException:
|
|
313
|
+
return self.__parse(instring, loc)
|
|
314
|
+
|
|
294
315
|
|
|
295
316
|
def list_of(entry: ParserElement) -> ParserElement:
|
|
296
317
|
return (
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import dataclasses
|
|
2
2
|
import sys
|
|
3
3
|
from collections.abc import Collection, Iterator, Sequence
|
|
4
|
-
from typing import cast
|
|
4
|
+
from typing import cast, overload
|
|
5
|
+
|
|
6
|
+
if sys.version_info >= (3, 11):
|
|
7
|
+
from typing import Never, Unpack
|
|
8
|
+
else:
|
|
9
|
+
from typing_extensions import Never, Unpack
|
|
5
10
|
|
|
6
11
|
if sys.version_info >= (3, 12):
|
|
7
12
|
from typing import override
|
|
@@ -116,20 +121,63 @@ class ParsedFile(
|
|
|
116
121
|
)
|
|
117
122
|
return ret
|
|
118
123
|
|
|
124
|
+
@overload
|
|
125
|
+
@with_default
|
|
126
|
+
def getall(self, keywords: tuple[()], /) -> Collection[StandaloneData]: ...
|
|
127
|
+
|
|
128
|
+
@overload
|
|
129
|
+
@with_default
|
|
130
|
+
def getall(
|
|
131
|
+
self, keywords: tuple[str, Unpack[tuple[str, ...]]], /
|
|
132
|
+
) -> Collection[Data | EllipsisType | None]: ...
|
|
133
|
+
|
|
119
134
|
@override
|
|
120
135
|
@with_default
|
|
121
136
|
def getall(
|
|
122
137
|
self, keywords: tuple[str, ...], /
|
|
123
|
-
) -> Collection[Data | StandaloneData | EllipsisType]:
|
|
138
|
+
) -> Collection[Data | StandaloneData | EllipsisType | None]:
|
|
124
139
|
return [entry.data for entry in self._parsed.getall(keywords)]
|
|
125
140
|
|
|
141
|
+
@overload
|
|
142
|
+
def __getitem__(self, keywords: tuple[()]) -> StandaloneData: ...
|
|
143
|
+
|
|
144
|
+
@overload
|
|
145
|
+
def __getitem__(
|
|
146
|
+
self, keywords: tuple[str, Unpack[tuple[str, ...]]]
|
|
147
|
+
) -> Data | EllipsisType | None: ...
|
|
148
|
+
|
|
126
149
|
@override
|
|
127
|
-
def
|
|
128
|
-
self,
|
|
150
|
+
def __getitem__(
|
|
151
|
+
self, keywords: tuple[str, ...]
|
|
152
|
+
) -> Data | StandaloneData | EllipsisType | None: # ty: ignore[invalid-method-override]
|
|
153
|
+
entry = self._parsed[keywords]
|
|
154
|
+
return entry.data
|
|
155
|
+
|
|
156
|
+
@override
|
|
157
|
+
def __setitem__( # ty: ignore[invalid-method-override]
|
|
158
|
+
self, key: Never, value: Never
|
|
129
159
|
) -> None: # pragma: no cover
|
|
130
160
|
msg = "Use 'put' method instead"
|
|
131
161
|
raise NotImplementedError(msg)
|
|
132
162
|
|
|
163
|
+
@overload
|
|
164
|
+
def put(
|
|
165
|
+
self,
|
|
166
|
+
keywords: tuple[()],
|
|
167
|
+
/,
|
|
168
|
+
data: StandaloneData,
|
|
169
|
+
content: bytes,
|
|
170
|
+
) -> None: ...
|
|
171
|
+
|
|
172
|
+
@overload
|
|
173
|
+
def put(
|
|
174
|
+
self,
|
|
175
|
+
keywords: tuple[str, Unpack[tuple[str, ...]]],
|
|
176
|
+
/,
|
|
177
|
+
data: Data | EllipsisType | None,
|
|
178
|
+
content: bytes,
|
|
179
|
+
) -> None: ...
|
|
180
|
+
|
|
133
181
|
def put(
|
|
134
182
|
self,
|
|
135
183
|
keywords: tuple[str, ...],
|
|
@@ -143,6 +191,24 @@ class ParsedFile(
|
|
|
143
191
|
self._parsed[keywords] = ParsedFile._Entry(data, start, start + len(content))
|
|
144
192
|
self._remove_child_entries(keywords)
|
|
145
193
|
|
|
194
|
+
@overload
|
|
195
|
+
def add(
|
|
196
|
+
self,
|
|
197
|
+
keywords: tuple[()],
|
|
198
|
+
data: StandaloneData,
|
|
199
|
+
content: bytes,
|
|
200
|
+
/,
|
|
201
|
+
) -> None: ...
|
|
202
|
+
|
|
203
|
+
@overload
|
|
204
|
+
def add(
|
|
205
|
+
self,
|
|
206
|
+
keywords: tuple[str, Unpack[tuple[str, ...]]],
|
|
207
|
+
data: Data | EllipsisType | None,
|
|
208
|
+
content: bytes,
|
|
209
|
+
/,
|
|
210
|
+
) -> None: ...
|
|
211
|
+
|
|
146
212
|
@override
|
|
147
213
|
def add( # ty: ignore[invalid-method-override]
|
|
148
214
|
self,
|
|
@@ -162,6 +228,16 @@ class ParsedFile(
|
|
|
162
228
|
self._parsed.add(keywords, ParsedFile._Entry(data, start, end))
|
|
163
229
|
self._update_content(start, end, content)
|
|
164
230
|
|
|
231
|
+
@overload
|
|
232
|
+
@with_default
|
|
233
|
+
def popone(self, keywords: tuple[()]) -> StandaloneData: ...
|
|
234
|
+
|
|
235
|
+
@overload
|
|
236
|
+
@with_default
|
|
237
|
+
def popone(
|
|
238
|
+
self, keywords: tuple[str, Unpack[tuple[str, ...]]]
|
|
239
|
+
) -> Data | EllipsisType | None: ...
|
|
240
|
+
|
|
165
241
|
@override
|
|
166
242
|
@with_default
|
|
167
243
|
def popone(
|
|
@@ -5,9 +5,9 @@ from typing import Literal, overload
|
|
|
5
5
|
from warnings import warn
|
|
6
6
|
|
|
7
7
|
if sys.version_info >= (3, 11):
|
|
8
|
-
from typing import Never, assert_never, assert_type
|
|
8
|
+
from typing import Never, Unpack, assert_never, assert_type
|
|
9
9
|
else:
|
|
10
|
-
from typing_extensions import Never, assert_never, assert_type
|
|
10
|
+
from typing_extensions import Never, Unpack, assert_never, assert_type
|
|
11
11
|
|
|
12
12
|
import numpy as np
|
|
13
13
|
|
|
@@ -44,7 +44,7 @@ def normalized(
|
|
|
44
44
|
data: DataLike,
|
|
45
45
|
/,
|
|
46
46
|
*,
|
|
47
|
-
keywords: tuple[str, ...] | None = ...,
|
|
47
|
+
keywords: tuple[str, Unpack[tuple[str, ...]]] | None = ...,
|
|
48
48
|
format_: Literal["ascii", "binary"] | None = ...,
|
|
49
49
|
) -> Data: ...
|
|
50
50
|
|
|
@@ -64,21 +64,11 @@ def normalized(
|
|
|
64
64
|
data: SubDictLike,
|
|
65
65
|
/,
|
|
66
66
|
*,
|
|
67
|
-
keywords: tuple[str, ...] = ...,
|
|
67
|
+
keywords: tuple[str, Unpack[tuple[str, ...]]] = ...,
|
|
68
68
|
format_: Literal["ascii", "binary"] | None = ...,
|
|
69
69
|
) -> SubDict: ...
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
@overload
|
|
73
|
-
def normalized(
|
|
74
|
-
data: DataLike,
|
|
75
|
-
/,
|
|
76
|
-
*,
|
|
77
|
-
keywords: tuple[str, ...] = ...,
|
|
78
|
-
format_: Literal["ascii", "binary"] | None = ...,
|
|
79
|
-
) -> Data: ...
|
|
80
|
-
|
|
81
|
-
|
|
82
72
|
@overload
|
|
83
73
|
def normalized(
|
|
84
74
|
data: DictLike,
|
|
@@ -94,7 +84,7 @@ def normalized(
|
|
|
94
84
|
data: None,
|
|
95
85
|
/,
|
|
96
86
|
*,
|
|
97
|
-
keywords: tuple[str, ...] = ...,
|
|
87
|
+
keywords: tuple[str, Unpack[tuple[str, ...]]] = ...,
|
|
98
88
|
format_: Literal["ascii", "binary"] | None = ...,
|
|
99
89
|
) -> None: ...
|
|
100
90
|
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import sys
|
|
1
2
|
from collections.abc import Mapping, Sequence
|
|
2
3
|
from typing import Literal, TypeAlias
|
|
3
4
|
|
|
5
|
+
if sys.version_info >= (3, 11):
|
|
6
|
+
from typing import Unpack
|
|
7
|
+
else:
|
|
8
|
+
from typing_extensions import Unpack
|
|
9
|
+
|
|
4
10
|
import numpy as np
|
|
5
11
|
from multicollections import MultiDict
|
|
6
12
|
|
|
@@ -38,8 +44,11 @@ DataEntryLike: TypeAlias = (
|
|
|
38
44
|
DataEntry | Sequence["DataEntryLike | KeywordEntryLike | DictLike"] | FieldLike
|
|
39
45
|
)
|
|
40
46
|
|
|
41
|
-
Data: TypeAlias = DataEntry | tuple[DataEntry, ...]
|
|
42
|
-
DataLike: TypeAlias =
|
|
47
|
+
Data: TypeAlias = DataEntry | tuple[DataEntry, DataEntry, Unpack[tuple[DataEntry, ...]]]
|
|
48
|
+
DataLike: TypeAlias = (
|
|
49
|
+
DataEntryLike
|
|
50
|
+
| tuple[DataEntryLike, DataEntryLike, Unpack[tuple[DataEntryLike, ...]]]
|
|
51
|
+
)
|
|
43
52
|
|
|
44
53
|
StandaloneDataEntry: TypeAlias = (
|
|
45
54
|
DataEntry
|
|
@@ -57,9 +66,21 @@ StandaloneDataEntryLike: TypeAlias = (
|
|
|
57
66
|
| Sequence[Sequence[int]]
|
|
58
67
|
)
|
|
59
68
|
|
|
60
|
-
StandaloneData: TypeAlias =
|
|
69
|
+
StandaloneData: TypeAlias = (
|
|
70
|
+
StandaloneDataEntry
|
|
71
|
+
| tuple[
|
|
72
|
+
StandaloneDataEntry,
|
|
73
|
+
StandaloneDataEntry,
|
|
74
|
+
Unpack[tuple[StandaloneDataEntry, ...]],
|
|
75
|
+
]
|
|
76
|
+
)
|
|
61
77
|
StandaloneDataLike: TypeAlias = (
|
|
62
|
-
StandaloneDataEntryLike
|
|
78
|
+
StandaloneDataEntryLike
|
|
79
|
+
| tuple[
|
|
80
|
+
StandaloneDataEntryLike,
|
|
81
|
+
StandaloneDataEntryLike,
|
|
82
|
+
Unpack[tuple[StandaloneDataEntryLike, ...]],
|
|
83
|
+
]
|
|
63
84
|
)
|
|
64
85
|
|
|
65
86
|
SubDict: TypeAlias = (
|
|
@@ -3,12 +3,12 @@ import os
|
|
|
3
3
|
import sys
|
|
4
4
|
from collections.abc import Collection, Iterable, Iterator, Mapping, Sequence
|
|
5
5
|
from copy import deepcopy
|
|
6
|
-
from typing import Literal, cast, overload
|
|
6
|
+
from typing import Literal, TypeVar, cast, overload
|
|
7
7
|
|
|
8
8
|
if sys.version_info >= (3, 11):
|
|
9
|
-
from typing import assert_never
|
|
9
|
+
from typing import Unpack, assert_never
|
|
10
10
|
else:
|
|
11
|
-
from typing_extensions import assert_never
|
|
11
|
+
from typing_extensions import Unpack, assert_never
|
|
12
12
|
|
|
13
13
|
if sys.version_info >= (3, 12):
|
|
14
14
|
from typing import override
|
|
@@ -21,7 +21,6 @@ from multicollections import MultiDict
|
|
|
21
21
|
from multicollections.abc import MutableMultiMapping, with_default
|
|
22
22
|
|
|
23
23
|
from .._files import _common
|
|
24
|
-
from ._common import dict_from_items
|
|
25
24
|
from ._io import FoamFileIO
|
|
26
25
|
from ._parsing import parse
|
|
27
26
|
from ._serialization import dumps, normalized
|
|
@@ -40,10 +39,12 @@ from ._typing import (
|
|
|
40
39
|
from ._util import SupportsKeysAndGetItem
|
|
41
40
|
from .types import Dimensioned, DimensionSet
|
|
42
41
|
|
|
42
|
+
_D = TypeVar("_D")
|
|
43
|
+
|
|
43
44
|
|
|
44
45
|
class FoamFile(
|
|
45
46
|
MutableMultiMapping[
|
|
46
|
-
str |
|
|
47
|
+
str | None,
|
|
47
48
|
"Data | StandaloneData | FoamFile.SubDict | None",
|
|
48
49
|
],
|
|
49
50
|
os.PathLike[str],
|
|
@@ -110,7 +111,8 @@ class FoamFile(
|
|
|
110
111
|
|
|
111
112
|
@override
|
|
112
113
|
def __len__(self) -> int:
|
|
113
|
-
|
|
114
|
+
with self._file:
|
|
115
|
+
return sum(1 for _ in iter(self))
|
|
114
116
|
|
|
115
117
|
@override
|
|
116
118
|
def __contains__(self, x: object) -> bool: # ty: ignore[invalid-method-override]
|
|
@@ -131,11 +133,17 @@ class FoamFile(
|
|
|
131
133
|
) -> Iterator["Data | StandaloneData | FoamFile.SubDict | None"]:
|
|
132
134
|
for k, v in self._file._get_parsed().items():
|
|
133
135
|
if k != ("FoamFile",) or self._include_header:
|
|
134
|
-
|
|
136
|
+
if v is ...:
|
|
137
|
+
assert k
|
|
138
|
+
k = cast("tuple[str, Unpack[tuple[str, ...]]]", k)
|
|
139
|
+
yield FoamFile.SubDict(self._file, k)
|
|
140
|
+
else:
|
|
141
|
+
yield v
|
|
135
142
|
|
|
136
143
|
@override
|
|
137
144
|
def __len__(self) -> int:
|
|
138
|
-
|
|
145
|
+
with self._file:
|
|
146
|
+
return sum(1 for _ in iter(self))
|
|
139
147
|
|
|
140
148
|
@override
|
|
141
149
|
def __contains__(self, value: object) -> bool:
|
|
@@ -151,29 +159,31 @@ class FoamFile(
|
|
|
151
159
|
file: "FoamFile",
|
|
152
160
|
*,
|
|
153
161
|
include_header: bool = False,
|
|
154
|
-
keywords: tuple[str, ...] = (),
|
|
155
162
|
) -> None:
|
|
156
|
-
assert keywords or include_header
|
|
157
163
|
self._file = file
|
|
158
164
|
self._include_header = include_header
|
|
159
|
-
self._keywords = keywords
|
|
160
165
|
|
|
161
166
|
@override
|
|
162
167
|
def __iter__(
|
|
163
168
|
self,
|
|
164
169
|
) -> Iterator[
|
|
165
|
-
tuple[str
|
|
170
|
+
tuple[str, "Data | FoamFile.SubDict | None"] | tuple[None, StandaloneData]
|
|
166
171
|
]:
|
|
167
172
|
for k, v in self._file._get_parsed().items():
|
|
168
173
|
if k != ("FoamFile",) or self._include_header:
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
174
|
+
if not k:
|
|
175
|
+
yield None, v
|
|
176
|
+
else:
|
|
177
|
+
k = cast("tuple[str, Unpack[tuple[str, ...]]]", k)
|
|
178
|
+
yield (
|
|
179
|
+
k[-1],
|
|
180
|
+
v if v is not ... else FoamFile.SubDict(self._file, k),
|
|
181
|
+
)
|
|
173
182
|
|
|
174
183
|
@override
|
|
175
184
|
def __len__(self) -> int:
|
|
176
|
-
|
|
185
|
+
with self._file:
|
|
186
|
+
return sum(1 for _ in iter(self))
|
|
177
187
|
|
|
178
188
|
@override
|
|
179
189
|
def __contains__(self, x: object) -> bool: # ty: ignore[invalid-method-override]
|
|
@@ -221,7 +231,8 @@ class FoamFile(
|
|
|
221
231
|
|
|
222
232
|
@override
|
|
223
233
|
def __len__(self) -> int:
|
|
224
|
-
|
|
234
|
+
with self._subdict._file:
|
|
235
|
+
return sum(1 for _ in iter(self))
|
|
225
236
|
|
|
226
237
|
@override
|
|
227
238
|
def __contains__(self, x: object) -> bool: # ty: ignore[invalid-method-override]
|
|
@@ -237,6 +248,7 @@ class FoamFile(
|
|
|
237
248
|
def __iter__(self) -> Iterator["Data | FoamFile.SubDict | None"]:
|
|
238
249
|
for k, v in self._subdict._file._get_parsed().items():
|
|
239
250
|
if k[:-1] == self._subdict._keywords:
|
|
251
|
+
k = cast("tuple[str, Unpack[tuple[str, ...]]]", k)
|
|
240
252
|
yield (
|
|
241
253
|
v
|
|
242
254
|
if v is not ...
|
|
@@ -245,7 +257,8 @@ class FoamFile(
|
|
|
245
257
|
|
|
246
258
|
@override
|
|
247
259
|
def __len__(self) -> int:
|
|
248
|
-
|
|
260
|
+
with self._subdict._file:
|
|
261
|
+
return sum(1 for _ in iter(self))
|
|
249
262
|
|
|
250
263
|
@override
|
|
251
264
|
def __contains__(self, value: object) -> bool:
|
|
@@ -263,8 +276,9 @@ class FoamFile(
|
|
|
263
276
|
) -> Iterator[tuple[str, "Data | FoamFile.SubDict | None"]]:
|
|
264
277
|
for k, v in self._subdict._file._get_parsed().items():
|
|
265
278
|
if k[:-1] == self._subdict._keywords:
|
|
279
|
+
k = cast("tuple[str, Unpack[tuple[str, ...]]]", k)
|
|
266
280
|
yield (
|
|
267
|
-
k[-1]
|
|
281
|
+
k[-1],
|
|
268
282
|
v
|
|
269
283
|
if v is not ...
|
|
270
284
|
else FoamFile.SubDict(self._subdict._file, k),
|
|
@@ -272,45 +286,29 @@ class FoamFile(
|
|
|
272
286
|
|
|
273
287
|
@override
|
|
274
288
|
def __len__(self) -> int:
|
|
275
|
-
|
|
289
|
+
with self._subdict._file:
|
|
290
|
+
return sum(1 for _ in iter(self))
|
|
276
291
|
|
|
277
292
|
@override
|
|
278
293
|
def __contains__(self, x: object) -> bool: # ty: ignore[invalid-method-override]
|
|
279
294
|
return any(i == x for i in iter(self))
|
|
280
295
|
|
|
281
|
-
def __init__(
|
|
296
|
+
def __init__(
|
|
297
|
+
self, _file: "FoamFile", _keywords: tuple[str, Unpack[tuple[str, ...]]]
|
|
298
|
+
) -> None:
|
|
282
299
|
self._file = _file
|
|
283
300
|
self._keywords = _keywords
|
|
284
301
|
|
|
285
302
|
@override
|
|
286
303
|
@with_default
|
|
287
|
-
def getall(
|
|
304
|
+
def getall(
|
|
305
|
+
self, keyword: str, /
|
|
306
|
+
) -> Collection["Data | FoamFile.SubDict | None"]:
|
|
288
307
|
return self._file.getall((*self._keywords, keyword))
|
|
289
308
|
|
|
290
|
-
@overload
|
|
291
|
-
def __getitem__(self, keyword: str) -> "Data | FoamFile.SubDict | None": ...
|
|
292
|
-
|
|
293
|
-
@overload
|
|
294
|
-
def __getitem__(
|
|
295
|
-
self, keyword: slice
|
|
296
|
-
) -> (
|
|
297
|
-
dict[str, "Data | FoamFile.SubDict | None"]
|
|
298
|
-
| MultiDict[str, "Data | FoamFile.SubDict | None"]
|
|
299
|
-
): ...
|
|
300
|
-
|
|
301
309
|
@override
|
|
302
|
-
def __getitem__(
|
|
303
|
-
self, keyword:
|
|
304
|
-
) -> "Data | FoamFile.SubDict | None | dict[str, Data | FoamFile.SubDict | None] | MultiDict[str, Data | FoamFile.SubDict | None]":
|
|
305
|
-
if keyword == slice(None):
|
|
306
|
-
return self.as_dict(deep=False)
|
|
307
|
-
|
|
308
|
-
if isinstance(keyword, slice):
|
|
309
|
-
msg = "Only empty slices (:) are supported"
|
|
310
|
-
raise ValueError(msg) # noqa: TRY004
|
|
311
|
-
|
|
312
|
-
ret = self._file[(*self._keywords, keyword)]
|
|
313
|
-
return cast("Data | FoamFile.SubDict | None", ret)
|
|
310
|
+
def __getitem__(self, keyword: str) -> "Data | FoamFile.SubDict | None":
|
|
311
|
+
return self._file[(*self._keywords, keyword)] # ty: ignore[invalid-return-type]
|
|
314
312
|
|
|
315
313
|
@overload
|
|
316
314
|
def __setitem__(
|
|
@@ -345,7 +343,7 @@ class FoamFile(
|
|
|
345
343
|
|
|
346
344
|
@override
|
|
347
345
|
@with_default
|
|
348
|
-
def popone(self, keyword: str) -> "Data | FoamFile.SubDict | None":
|
|
346
|
+
def popone(self, keyword: str, /) -> "Data | FoamFile.SubDict | None":
|
|
349
347
|
return self._file.popone((*self._keywords, keyword))
|
|
350
348
|
|
|
351
349
|
@override
|
|
@@ -372,7 +370,8 @@ class FoamFile(
|
|
|
372
370
|
|
|
373
371
|
@override
|
|
374
372
|
def __len__(self) -> int:
|
|
375
|
-
|
|
373
|
+
with self._file:
|
|
374
|
+
return sum(1 for _ in iter(self))
|
|
376
375
|
|
|
377
376
|
@override
|
|
378
377
|
def keys(self) -> "FoamFile.SubDict.KeysView":
|
|
@@ -428,42 +427,17 @@ class FoamFile(
|
|
|
428
427
|
def __repr__(self) -> str:
|
|
429
428
|
return f"{type(self).__qualname__}('{self._file}', {self._keywords})"
|
|
430
429
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
@overload
|
|
435
|
-
def as_dict(
|
|
436
|
-
self, *, deep: Literal[False] = ...
|
|
437
|
-
) -> (
|
|
438
|
-
dict[str, "Data | FoamFile.SubDict | None"]
|
|
439
|
-
| MultiDict[str, "Data | FoamFile.SubDict | None"]
|
|
440
|
-
): ...
|
|
441
|
-
|
|
442
|
-
def as_dict(
|
|
443
|
-
self, *, deep: bool = True
|
|
444
|
-
) -> (
|
|
445
|
-
SubDict
|
|
446
|
-
| dict[str, "Data | FoamFile.SubDict | None"]
|
|
447
|
-
| MultiDict[str, "Data | FoamFile.SubDict | None"]
|
|
448
|
-
):
|
|
449
|
-
"""
|
|
450
|
-
Return a dict representation of the sub-dictionary.
|
|
451
|
-
|
|
452
|
-
:param deep: Whether to return a nested representation by recursing into
|
|
453
|
-
nested sub-dictionaries.
|
|
454
|
-
"""
|
|
455
|
-
if deep:
|
|
456
|
-
file = self._file.as_dict(include_header=True)
|
|
430
|
+
def as_dict(self) -> SubDict:
|
|
431
|
+
"""Return a nested dict representation of the sub-dictionary."""
|
|
432
|
+
file = self._file.as_dict(include_header=True)
|
|
457
433
|
|
|
458
|
-
|
|
434
|
+
ret = file[self._keywords[0]]
|
|
435
|
+
assert isinstance(ret, Mapping)
|
|
436
|
+
for k in self._keywords[1:]:
|
|
437
|
+
ret = ret[k]
|
|
459
438
|
assert isinstance(ret, Mapping)
|
|
460
|
-
for k in self._keywords[1:]:
|
|
461
|
-
ret = ret[k]
|
|
462
|
-
assert isinstance(ret, Mapping)
|
|
463
|
-
|
|
464
|
-
return ret # ty: ignore[invalid-return-type]
|
|
465
439
|
|
|
466
|
-
return
|
|
440
|
+
return ret # ty: ignore[invalid-return-type]
|
|
467
441
|
|
|
468
442
|
@property
|
|
469
443
|
def version(self) -> float:
|
|
@@ -552,10 +526,21 @@ class FoamFile(
|
|
|
552
526
|
self.path.stem if self.path.suffix == ".gz" else self.path.name
|
|
553
527
|
)
|
|
554
528
|
|
|
529
|
+
@overload
|
|
555
530
|
def _update_class_for_field_if_needed(
|
|
556
531
|
self,
|
|
557
|
-
keywords: tuple[str, ...],
|
|
558
|
-
data: Data |
|
|
532
|
+
keywords: tuple[str, Unpack[tuple[str, ...]]],
|
|
533
|
+
data: Data | SubDict | None,
|
|
534
|
+
/,
|
|
535
|
+
) -> None: ...
|
|
536
|
+
|
|
537
|
+
@overload
|
|
538
|
+
def _update_class_for_field_if_needed(
|
|
539
|
+
self, keywords: tuple[()], data: StandaloneData, /
|
|
540
|
+
) -> None: ...
|
|
541
|
+
|
|
542
|
+
def _update_class_for_field_if_needed(
|
|
543
|
+
self, keywords: tuple[str, ...], data: Data | StandaloneData | SubDict, /
|
|
559
544
|
) -> None:
|
|
560
545
|
"""Update class field to appropriate field type if this is a field entry."""
|
|
561
546
|
try:
|
|
@@ -620,6 +605,26 @@ class FoamFile(
|
|
|
620
605
|
|
|
621
606
|
return before, after
|
|
622
607
|
|
|
608
|
+
@overload
|
|
609
|
+
def _perform_entry_operation(
|
|
610
|
+
self,
|
|
611
|
+
keywords: str | tuple[str, Unpack[tuple[str, ...]]],
|
|
612
|
+
data: DataLike | SubDictLike | None,
|
|
613
|
+
/,
|
|
614
|
+
*,
|
|
615
|
+
add: bool,
|
|
616
|
+
) -> None: ...
|
|
617
|
+
|
|
618
|
+
@overload
|
|
619
|
+
def _perform_entry_operation(
|
|
620
|
+
self,
|
|
621
|
+
keywords: None | tuple[()],
|
|
622
|
+
data: StandaloneDataLike,
|
|
623
|
+
/,
|
|
624
|
+
*,
|
|
625
|
+
add: bool,
|
|
626
|
+
) -> None: ...
|
|
627
|
+
|
|
623
628
|
def _perform_entry_operation(
|
|
624
629
|
self,
|
|
625
630
|
keywords: tuple[str, ...],
|
|
@@ -663,6 +668,7 @@ class FoamFile(
|
|
|
663
668
|
if not keywords:
|
|
664
669
|
msg = "Cannot set a mapping at the root level of a FoamFile\nUse update(), extend(), or merge() instead."
|
|
665
670
|
raise ValueError(msg)
|
|
671
|
+
keywords = cast("tuple[str, Unpack[tuple[str, ...]]]", keywords)
|
|
666
672
|
|
|
667
673
|
if keyword.startswith("#"):
|
|
668
674
|
msg = f"Cannot set a directive as the keyword for a dictionary: {keyword}"
|
|
@@ -688,6 +694,7 @@ class FoamFile(
|
|
|
688
694
|
self[(*keywords, k)] = v # ty: ignore[invalid-assignment]
|
|
689
695
|
|
|
690
696
|
elif keywords:
|
|
697
|
+
keywords = cast("tuple[str, Unpack[tuple[str, ...]]]", keywords)
|
|
691
698
|
val = dumps(data, keywords=keywords, format_=format_)
|
|
692
699
|
|
|
693
700
|
content = (
|
|
@@ -718,94 +725,121 @@ class FoamFile(
|
|
|
718
725
|
@overload
|
|
719
726
|
@with_default
|
|
720
727
|
def getall(
|
|
721
|
-
self,
|
|
728
|
+
self,
|
|
729
|
+
keywords: str | tuple[str, Unpack[tuple[str, ...]]],
|
|
730
|
+
/,
|
|
722
731
|
) -> Collection["Data | FoamFile.SubDict | None"]: ...
|
|
723
732
|
|
|
724
733
|
@overload
|
|
725
734
|
@with_default
|
|
726
|
-
def getall(self, keywords: None | tuple[()]) -> Collection[StandaloneData]: ...
|
|
727
|
-
|
|
728
|
-
@overload
|
|
729
|
-
@with_default
|
|
730
|
-
def getall(
|
|
731
|
-
self, keywords: tuple[str, ...]
|
|
732
|
-
) -> Collection["Data | StandaloneData | FoamFile.SubDict | None"]: ...
|
|
735
|
+
def getall(self, keywords: None | tuple[()], /) -> Collection[StandaloneData]: ...
|
|
733
736
|
|
|
734
737
|
@override
|
|
735
738
|
@with_default
|
|
736
739
|
def getall(
|
|
737
740
|
self,
|
|
738
741
|
keywords: str | tuple[str, ...] | None,
|
|
742
|
+
/,
|
|
739
743
|
) -> Collection["Data | StandaloneData | FoamFile.SubDict | None"]:
|
|
740
744
|
keywords = FoamFile._normalized_keywords(keywords)
|
|
745
|
+
keywords = cast("tuple[str, Unpack[tuple[str, ...]]] | tuple[()]", keywords)
|
|
741
746
|
|
|
742
747
|
parsed = self._get_parsed()
|
|
743
748
|
|
|
744
|
-
|
|
749
|
+
values = parsed.getall(keywords)
|
|
745
750
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
751
|
+
ret = []
|
|
752
|
+
for v in values:
|
|
753
|
+
if v is ...:
|
|
754
|
+
assert keywords
|
|
755
|
+
ret.append(FoamFile.SubDict(self, keywords))
|
|
756
|
+
else:
|
|
757
|
+
ret.append(deepcopy(v))
|
|
758
|
+
return ret
|
|
749
759
|
|
|
750
760
|
@overload
|
|
751
|
-
|
|
761
|
+
@with_default
|
|
762
|
+
def getone(
|
|
752
763
|
self,
|
|
753
|
-
keywords: str | tuple[str],
|
|
764
|
+
keywords: str | tuple[str, Unpack[tuple[str, ...]]],
|
|
765
|
+
/,
|
|
754
766
|
) -> "Data | FoamFile.SubDict | None": ...
|
|
755
767
|
|
|
756
768
|
@overload
|
|
757
|
-
|
|
769
|
+
@with_default
|
|
770
|
+
def getone(self, keywords: None | tuple[()], /) -> StandaloneData: ...
|
|
771
|
+
|
|
772
|
+
@override
|
|
773
|
+
@with_default
|
|
774
|
+
def getone(
|
|
775
|
+
self,
|
|
776
|
+
keywords: str | tuple[str, ...] | None,
|
|
777
|
+
/,
|
|
778
|
+
) -> "Data | StandaloneData | FoamFile.SubDict | None":
|
|
779
|
+
keywords = FoamFile._normalized_keywords(keywords)
|
|
780
|
+
|
|
781
|
+
parsed = self._get_parsed()
|
|
782
|
+
keywords = cast("tuple[str, Unpack[tuple[str, ...]]] | tuple[()]", keywords)
|
|
783
|
+
ret = parsed[keywords]
|
|
784
|
+
if ret is ...:
|
|
785
|
+
assert keywords
|
|
786
|
+
return FoamFile.SubDict(self, keywords)
|
|
787
|
+
return deepcopy(ret)
|
|
788
|
+
|
|
789
|
+
@overload
|
|
790
|
+
def get(
|
|
791
|
+
self,
|
|
792
|
+
keywords: str | tuple[str, Unpack[tuple[str, ...]]],
|
|
793
|
+
default: _D = ...,
|
|
794
|
+
/,
|
|
795
|
+
) -> "Data | FoamFile.SubDict | None | _D": ...
|
|
796
|
+
|
|
797
|
+
@overload
|
|
798
|
+
def get(
|
|
758
799
|
self,
|
|
759
800
|
keywords: None | tuple[()],
|
|
760
|
-
|
|
801
|
+
default: _D = ...,
|
|
802
|
+
/,
|
|
803
|
+
) -> StandaloneData | _D: ...
|
|
804
|
+
|
|
805
|
+
@override
|
|
806
|
+
def get( # ty: ignore[invalid-method-override]
|
|
807
|
+
self,
|
|
808
|
+
keywords: str | tuple[str, ...] | None,
|
|
809
|
+
default: _D = None, # ty: ignore[invalid-parameter-default]
|
|
810
|
+
/,
|
|
811
|
+
) -> "Data | StandaloneData | FoamFile.SubDict | None | _D":
|
|
812
|
+
return self.getone(keywords, default=default)
|
|
761
813
|
|
|
762
814
|
@overload
|
|
763
815
|
def __getitem__(
|
|
764
816
|
self,
|
|
765
|
-
keywords: tuple[str, ...],
|
|
766
|
-
) -> "Data |
|
|
817
|
+
keywords: str | tuple[str, Unpack[tuple[str, ...]]],
|
|
818
|
+
) -> "Data | FoamFile.SubDict | None": ...
|
|
767
819
|
|
|
768
820
|
@overload
|
|
769
821
|
def __getitem__(
|
|
770
822
|
self,
|
|
771
|
-
keywords:
|
|
772
|
-
) ->
|
|
773
|
-
dict[str | None, "Data | StandaloneData | FoamFile.SubDict | None"]
|
|
774
|
-
| MultiDict[str | None, "Data | StandaloneData | FoamFile.SubDict | None"]
|
|
775
|
-
): ...
|
|
823
|
+
keywords: None | tuple[()],
|
|
824
|
+
) -> StandaloneData: ...
|
|
776
825
|
|
|
777
826
|
@override
|
|
778
827
|
def __getitem__( # ty: ignore[invalid-method-override]
|
|
779
828
|
self,
|
|
780
|
-
keywords: str | tuple[str, ...] | None
|
|
781
|
-
) -> "Data | StandaloneData | FoamFile.SubDict | None
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
if keywords == slice(None):
|
|
785
|
-
return self.as_dict(deep=False)
|
|
786
|
-
|
|
787
|
-
assert not isinstance(keywords, slice)
|
|
788
|
-
parsed = self._get_parsed()
|
|
789
|
-
ret = parsed[keywords]
|
|
790
|
-
if ret is ...:
|
|
791
|
-
return FoamFile.SubDict(self, keywords)
|
|
792
|
-
return deepcopy(ret)
|
|
793
|
-
|
|
794
|
-
@overload
|
|
795
|
-
def __setitem__(
|
|
796
|
-
self, keywords: None | tuple[()], data: StandaloneDataLike
|
|
797
|
-
) -> None: ...
|
|
829
|
+
keywords: str | tuple[str, ...] | None,
|
|
830
|
+
) -> "Data | StandaloneData | FoamFile.SubDict | None":
|
|
831
|
+
return self.getone(keywords)
|
|
798
832
|
|
|
799
833
|
@overload
|
|
800
834
|
def __setitem__(
|
|
801
|
-
self,
|
|
835
|
+
self,
|
|
836
|
+
keywords: str | tuple[str, Unpack[tuple[str, ...]]],
|
|
837
|
+
data: DataLike | SubDictLike | None,
|
|
802
838
|
) -> None: ...
|
|
803
839
|
|
|
804
840
|
@overload
|
|
805
841
|
def __setitem__(
|
|
806
|
-
self,
|
|
807
|
-
keywords: tuple[str, ...],
|
|
808
|
-
data: DataLike | StandaloneDataLike | SubDictLike | None,
|
|
842
|
+
self, keywords: None | tuple[()], data: StandaloneDataLike
|
|
809
843
|
) -> None: ...
|
|
810
844
|
|
|
811
845
|
@overload
|
|
@@ -834,7 +868,7 @@ class FoamFile(
|
|
|
834
868
|
return
|
|
835
869
|
|
|
836
870
|
assert not isinstance(keywords, slice)
|
|
837
|
-
self._perform_entry_operation(keywords, data, add=False) # ty: ignore[invalid-argument-type]
|
|
871
|
+
self._perform_entry_operation(keywords, data, add=False) # ty: ignore[invalid-argument-type,no-matching-overload]
|
|
838
872
|
|
|
839
873
|
@override
|
|
840
874
|
def __delitem__(self, keywords: str | tuple[str, ...] | None | slice) -> None:
|
|
@@ -846,22 +880,52 @@ class FoamFile(
|
|
|
846
880
|
return
|
|
847
881
|
|
|
848
882
|
assert not isinstance(keywords, slice)
|
|
849
|
-
super().__delitem__(keywords)
|
|
850
883
|
|
|
851
|
-
|
|
884
|
+
with self:
|
|
885
|
+
del self._get_parsed()[keywords]
|
|
886
|
+
|
|
887
|
+
@overload
|
|
888
|
+
def add(
|
|
889
|
+
self,
|
|
890
|
+
keywords: str | tuple[str, Unpack[tuple[str, ...]]],
|
|
891
|
+
data: DataLike | SubDictLike | None,
|
|
892
|
+
) -> None: ...
|
|
893
|
+
|
|
894
|
+
@overload
|
|
852
895
|
def add(
|
|
896
|
+
self,
|
|
897
|
+
keywords: None | tuple[()],
|
|
898
|
+
data: StandaloneDataLike,
|
|
899
|
+
) -> None: ...
|
|
900
|
+
|
|
901
|
+
@override
|
|
902
|
+
def add( # ty: ignore[invalid-method-override]
|
|
853
903
|
self,
|
|
854
904
|
keywords: str | tuple[str, ...] | None,
|
|
855
905
|
data: DataLike | StandaloneDataLike | SubDictLike | None,
|
|
856
906
|
) -> None:
|
|
857
907
|
keywords = FoamFile._normalized_keywords(keywords)
|
|
858
|
-
|
|
908
|
+
keywords = cast("tuple[str, Unpack[tuple[str, ...]]] | tuple[()]", keywords)
|
|
859
909
|
self._perform_entry_operation(keywords, data, add=True)
|
|
860
910
|
|
|
911
|
+
@overload
|
|
861
912
|
@with_default
|
|
913
|
+
def popone(
|
|
914
|
+
self,
|
|
915
|
+
keywords: str | tuple[str, Unpack[tuple[str, ...]]],
|
|
916
|
+
/,
|
|
917
|
+
) -> "Data | FoamFile.SubDict | None": ...
|
|
918
|
+
|
|
919
|
+
@overload
|
|
920
|
+
@with_default
|
|
921
|
+
def popone(self, keywords: None | tuple[()], /) -> StandaloneData: ...
|
|
922
|
+
|
|
862
923
|
@override
|
|
924
|
+
@with_default
|
|
863
925
|
def popone(
|
|
864
|
-
self,
|
|
926
|
+
self,
|
|
927
|
+
keywords: str | tuple[str, ...] | None,
|
|
928
|
+
/,
|
|
865
929
|
) -> "Data | StandaloneData | FoamFile.SubDict | None":
|
|
866
930
|
keywords = FoamFile._normalized_keywords(keywords)
|
|
867
931
|
|
|
@@ -870,12 +934,15 @@ class FoamFile(
|
|
|
870
934
|
|
|
871
935
|
@overload
|
|
872
936
|
def _iter(
|
|
873
|
-
self,
|
|
937
|
+
self,
|
|
938
|
+
keywords: tuple[str, Unpack[tuple[str, ...]]],
|
|
939
|
+
*,
|
|
940
|
+
include_header: bool = ...,
|
|
874
941
|
) -> Iterator[str]: ...
|
|
875
942
|
|
|
876
943
|
@overload
|
|
877
944
|
def _iter(
|
|
878
|
-
self, keywords: tuple[()] =
|
|
945
|
+
self, keywords: tuple[()] = ..., *, include_header: bool = ...
|
|
879
946
|
) -> Iterator[str | None]: ...
|
|
880
947
|
|
|
881
948
|
def _iter(
|
|
@@ -905,7 +972,8 @@ class FoamFile(
|
|
|
905
972
|
@override
|
|
906
973
|
def __len__(self) -> int:
|
|
907
974
|
"""Return the number of top-level keywords in the FoamFile (excluding the FoamFile header if present)."""
|
|
908
|
-
|
|
975
|
+
with self:
|
|
976
|
+
return sum(1 for _ in self._iter())
|
|
909
977
|
|
|
910
978
|
@override
|
|
911
979
|
def keys(
|
|
@@ -950,12 +1018,12 @@ class FoamFile(
|
|
|
950
1018
|
def update( # ty: ignore[invalid-method-override]
|
|
951
1019
|
self,
|
|
952
1020
|
other: SupportsKeysAndGetItem[
|
|
953
|
-
str |
|
|
1021
|
+
str | None,
|
|
954
1022
|
DataLike | StandaloneDataLike | SubDictLike | None,
|
|
955
1023
|
]
|
|
956
1024
|
| Iterable[
|
|
957
1025
|
tuple[
|
|
958
|
-
str |
|
|
1026
|
+
str | None,
|
|
959
1027
|
DataLike | StandaloneDataLike | SubDictLike | None,
|
|
960
1028
|
]
|
|
961
1029
|
] = (),
|
|
@@ -969,12 +1037,12 @@ class FoamFile(
|
|
|
969
1037
|
def extend( # ty: ignore[invalid-method-override]
|
|
970
1038
|
self,
|
|
971
1039
|
other: SupportsKeysAndGetItem[
|
|
972
|
-
str |
|
|
1040
|
+
str | None,
|
|
973
1041
|
DataLike | StandaloneDataLike | SubDictLike | None,
|
|
974
1042
|
]
|
|
975
1043
|
| Iterable[
|
|
976
1044
|
tuple[
|
|
977
|
-
str |
|
|
1045
|
+
str | None,
|
|
978
1046
|
DataLike | StandaloneDataLike | SubDictLike | None,
|
|
979
1047
|
]
|
|
980
1048
|
] = (),
|
|
@@ -988,14 +1056,10 @@ class FoamFile(
|
|
|
988
1056
|
def merge( # ty: ignore[invalid-method-override]
|
|
989
1057
|
self,
|
|
990
1058
|
other: SupportsKeysAndGetItem[
|
|
991
|
-
str |
|
|
992
|
-
DataLike | StandaloneDataLike | SubDictLike | None,
|
|
1059
|
+
str | None, DataLike | StandaloneDataLike | SubDictLike | None
|
|
993
1060
|
]
|
|
994
1061
|
| Iterable[
|
|
995
|
-
tuple[
|
|
996
|
-
str | tuple[str, ...] | None,
|
|
997
|
-
DataLike | StandaloneDataLike | SubDictLike | None,
|
|
998
|
-
]
|
|
1062
|
+
tuple[str | None, DataLike | StandaloneDataLike | SubDictLike | None]
|
|
999
1063
|
] = (),
|
|
1000
1064
|
/,
|
|
1001
1065
|
**kwargs: DataLike | StandaloneDataLike | SubDictLike | None,
|
|
@@ -1020,40 +1084,16 @@ class FoamFile(
|
|
|
1020
1084
|
def __fspath__(self) -> str:
|
|
1021
1085
|
return str(self.path)
|
|
1022
1086
|
|
|
1023
|
-
|
|
1024
|
-
def as_dict(
|
|
1025
|
-
self, *, include_header: bool = ..., deep: Literal[True] = ...
|
|
1026
|
-
) -> File: ...
|
|
1027
|
-
|
|
1028
|
-
@overload
|
|
1029
|
-
def as_dict(
|
|
1030
|
-
self, *, include_header: bool = ..., deep: Literal[False] = ...
|
|
1031
|
-
) -> (
|
|
1032
|
-
dict[str | None, "Data | StandaloneData | FoamFile.SubDict | None"]
|
|
1033
|
-
| MultiDict[str | None, "Data | StandaloneData | FoamFile.SubDict | None"]
|
|
1034
|
-
): ...
|
|
1035
|
-
|
|
1036
|
-
def as_dict(
|
|
1037
|
-
self, *, include_header: bool = False, deep: bool = True
|
|
1038
|
-
) -> (
|
|
1039
|
-
File
|
|
1040
|
-
| dict[str | None, "Data | StandaloneData | FoamFile.SubDict | None"]
|
|
1041
|
-
| MultiDict[str | None, "Data | StandaloneData | FoamFile.SubDict | None"]
|
|
1042
|
-
):
|
|
1087
|
+
def as_dict(self, *, include_header: bool = False) -> File:
|
|
1043
1088
|
"""
|
|
1044
|
-
Return a dict representation of the file.
|
|
1089
|
+
Return a nested dict representation of the file.
|
|
1045
1090
|
|
|
1046
1091
|
:param include_header: Whether to include the "FoamFile" header in the output.
|
|
1047
|
-
:param deep: Whether to return a nested representation by recursing into
|
|
1048
|
-
nested sub-dictionaries.
|
|
1049
1092
|
"""
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
return deepcopy(d)
|
|
1055
|
-
|
|
1056
|
-
return dict_from_items(self.items(include_header=include_header), target=File) # ty: ignore[invalid-return-type]
|
|
1093
|
+
d = self._get_parsed().as_dict()
|
|
1094
|
+
if not include_header:
|
|
1095
|
+
d.pop("FoamFile", None)
|
|
1096
|
+
return deepcopy(d)
|
|
1057
1097
|
|
|
1058
1098
|
@staticmethod
|
|
1059
1099
|
def loads(
|
|
@@ -1135,14 +1175,14 @@ class FoamFile(
|
|
|
1135
1175
|
@overload
|
|
1136
1176
|
@staticmethod
|
|
1137
1177
|
def _normalized_keywords(
|
|
1138
|
-
keywords:
|
|
1139
|
-
) -> tuple[
|
|
1178
|
+
keywords: tuple[str, Unpack[tuple[str, ...]]], /, *, slice_ok: bool = ...
|
|
1179
|
+
) -> tuple[str, Unpack[tuple[str, ...]]]: ...
|
|
1140
1180
|
|
|
1141
1181
|
@overload
|
|
1142
1182
|
@staticmethod
|
|
1143
1183
|
def _normalized_keywords(
|
|
1144
|
-
keywords: tuple[
|
|
1145
|
-
) -> tuple[
|
|
1184
|
+
keywords: None | tuple[()], /, *, slice_ok: bool = ...
|
|
1185
|
+
) -> tuple[()]: ...
|
|
1146
1186
|
|
|
1147
1187
|
@overload
|
|
1148
1188
|
@staticmethod
|
|
@@ -1225,7 +1265,7 @@ class FoamFieldFile(FoamFile):
|
|
|
1225
1265
|
@override
|
|
1226
1266
|
@with_default
|
|
1227
1267
|
def getall(
|
|
1228
|
-
self, keyword: str
|
|
1268
|
+
self, keyword: str, /
|
|
1229
1269
|
) -> Collection["FoamFieldFile.BoundarySubDict | Data | None"]:
|
|
1230
1270
|
ret = super().getall(keyword)
|
|
1231
1271
|
for r in ret:
|
|
@@ -1273,23 +1313,17 @@ class FoamFieldFile(FoamFile):
|
|
|
1273
1313
|
@overload
|
|
1274
1314
|
@with_default
|
|
1275
1315
|
def getall(
|
|
1276
|
-
self, keywords: str | tuple[str]
|
|
1277
|
-
) -> Collection["Data | FoamFieldFile.
|
|
1316
|
+
self, keywords: str | tuple[str, Unpack[tuple[str, ...]]], /
|
|
1317
|
+
) -> Collection["Data | FoamFieldFile.SubDict | None"]: ...
|
|
1278
1318
|
|
|
1279
1319
|
@overload
|
|
1280
1320
|
@with_default
|
|
1281
|
-
def getall(self, keywords: None | tuple[()]) -> Collection[StandaloneData]: ...
|
|
1282
|
-
|
|
1283
|
-
@overload
|
|
1284
|
-
@with_default
|
|
1285
|
-
def getall(
|
|
1286
|
-
self, keywords: tuple[str, ...]
|
|
1287
|
-
) -> Collection["Data | StandaloneData | FoamFieldFile.SubDict | None"]: ...
|
|
1321
|
+
def getall(self, keywords: None | tuple[()], /) -> Collection[StandaloneData]: ...
|
|
1288
1322
|
|
|
1289
1323
|
@override
|
|
1290
1324
|
@with_default
|
|
1291
1325
|
def getall(
|
|
1292
|
-
self, keywords: str | tuple[str, ...] | None
|
|
1326
|
+
self, keywords: str | tuple[str, ...] | None, /
|
|
1293
1327
|
) -> Collection["Data | StandaloneData | FoamFieldFile.SubDict | None"]:
|
|
1294
1328
|
keywords = FoamFieldFile._normalized_keywords(keywords)
|
|
1295
1329
|
|
|
@@ -1299,8 +1333,10 @@ class FoamFieldFile(FoamFile):
|
|
|
1299
1333
|
for i, r in enumerate(ret):
|
|
1300
1334
|
if isinstance(r, FoamFile.SubDict):
|
|
1301
1335
|
if len(keywords) == 1:
|
|
1336
|
+
keywords = cast("tuple[str]", keywords)
|
|
1302
1337
|
ret[i] = FoamFieldFile.BoundariesSubDict(self, keywords)
|
|
1303
1338
|
elif len(keywords) == 2:
|
|
1339
|
+
keywords = cast("tuple[str, str]", keywords)
|
|
1304
1340
|
ret[i] = FoamFieldFile.BoundarySubDict(self, keywords)
|
|
1305
1341
|
|
|
1306
1342
|
return ret
|
|
@@ -1308,14 +1344,8 @@ class FoamFieldFile(FoamFile):
|
|
|
1308
1344
|
@overload
|
|
1309
1345
|
def __getitem__(
|
|
1310
1346
|
self,
|
|
1311
|
-
keywords: str | tuple[str],
|
|
1312
|
-
) -> "Data | FoamFieldFile.
|
|
1313
|
-
|
|
1314
|
-
@overload
|
|
1315
|
-
def __getitem__(
|
|
1316
|
-
self,
|
|
1317
|
-
keywords: tuple[str, str],
|
|
1318
|
-
) -> "Data | FoamFieldFile.BoundarySubDict | None": ...
|
|
1347
|
+
keywords: str | tuple[str, Unpack[tuple[str, ...]]],
|
|
1348
|
+
) -> "Data | FoamFieldFile.SubDict | None": ...
|
|
1319
1349
|
|
|
1320
1350
|
@overload
|
|
1321
1351
|
def __getitem__(
|
|
@@ -1323,35 +1353,25 @@ class FoamFieldFile(FoamFile):
|
|
|
1323
1353
|
keywords: None | tuple[()],
|
|
1324
1354
|
) -> StandaloneData: ...
|
|
1325
1355
|
|
|
1326
|
-
@overload
|
|
1327
|
-
def __getitem__(
|
|
1328
|
-
self,
|
|
1329
|
-
keywords: tuple[str, ...],
|
|
1330
|
-
) -> "Data | StandaloneData | FoamFieldFile.SubDict | None": ...
|
|
1331
|
-
|
|
1332
|
-
@overload
|
|
1333
|
-
def __getitem__(
|
|
1334
|
-
self,
|
|
1335
|
-
keywords: slice,
|
|
1336
|
-
) -> File: ...
|
|
1337
|
-
|
|
1338
1356
|
@override
|
|
1339
1357
|
def __getitem__( # ty: ignore[invalid-method-override]
|
|
1340
1358
|
self,
|
|
1341
|
-
keywords: str | tuple[str, ...] | None
|
|
1342
|
-
) -> "Data | StandaloneData | FoamFieldFile.SubDict | None
|
|
1343
|
-
keywords = FoamFieldFile._normalized_keywords(keywords
|
|
1344
|
-
|
|
1345
|
-
if keywords == slice(None):
|
|
1346
|
-
return self.as_dict(deep=False)
|
|
1359
|
+
keywords: str | tuple[str, ...] | None,
|
|
1360
|
+
) -> "Data | StandaloneData | FoamFieldFile.SubDict | None":
|
|
1361
|
+
keywords = FoamFieldFile._normalized_keywords(keywords)
|
|
1347
1362
|
|
|
1348
|
-
|
|
1349
|
-
ret = super().__getitem__(keywords)
|
|
1363
|
+
ret = super().__getitem__(keywords) # ty: ignore[no-matching-overload]
|
|
1350
1364
|
|
|
1351
|
-
if
|
|
1365
|
+
if (
|
|
1366
|
+
keywords
|
|
1367
|
+
and keywords[0] == "boundaryField"
|
|
1368
|
+
and isinstance(ret, FoamFile.SubDict)
|
|
1369
|
+
):
|
|
1352
1370
|
if len(keywords) == 1:
|
|
1371
|
+
keywords = cast("tuple[str]", keywords)
|
|
1353
1372
|
ret = FoamFieldFile.BoundariesSubDict(self, keywords)
|
|
1354
1373
|
elif len(keywords) == 2:
|
|
1374
|
+
keywords = cast("tuple[str, str]", keywords)
|
|
1355
1375
|
ret = FoamFieldFile.BoundarySubDict(self, keywords)
|
|
1356
1376
|
|
|
1357
1377
|
return ret
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|