foamlib 0.2.5__py3-none-any.whl → 0.2.7__py3-none-any.whl
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/__init__.py +5 -3
- foamlib/_cases.py +35 -82
- foamlib/_dictionaries/__init__.py +1 -1
- foamlib/_dictionaries/_base.py +14 -7
- foamlib/_dictionaries/_files.py +32 -30
- foamlib/_dictionaries/_parsing.py +10 -16
- foamlib/_dictionaries/_serialization.py +28 -14
- foamlib/_util.py +15 -8
- {foamlib-0.2.5.dist-info → foamlib-0.2.7.dist-info}/METADATA +1 -1
- foamlib-0.2.7.dist-info/RECORD +14 -0
- foamlib-0.2.5.dist-info/RECORD +0 -14
- {foamlib-0.2.5.dist-info → foamlib-0.2.7.dist-info}/LICENSE.txt +0 -0
- {foamlib-0.2.5.dist-info → foamlib-0.2.7.dist-info}/WHEEL +0 -0
- {foamlib-0.2.5.dist-info → foamlib-0.2.7.dist-info}/top_level.txt +0 -0
foamlib/__init__.py
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
|
1
|
+
"""A Python interface for interacting with OpenFOAM."""
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
__version__ = "0.2.7"
|
4
|
+
|
5
|
+
from ._cases import AsyncFoamCase, FoamCase, FoamCaseBase
|
6
|
+
from ._dictionaries import FoamDictionaryBase, FoamFieldFile, FoamFile
|
5
7
|
|
6
8
|
__all__ = [
|
7
9
|
"FoamCase",
|
foamlib/_cases.py
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
-
import sys
|
2
|
-
import os
|
3
1
|
import asyncio
|
4
2
|
import multiprocessing
|
3
|
+
import os
|
5
4
|
import shutil
|
6
|
-
|
7
|
-
from pathlib import Path
|
5
|
+
import sys
|
8
6
|
from contextlib import asynccontextmanager
|
7
|
+
from pathlib import Path
|
9
8
|
from typing import (
|
10
9
|
Optional,
|
11
10
|
Union,
|
@@ -14,22 +13,22 @@ from typing import (
|
|
14
13
|
|
15
14
|
if sys.version_info >= (3, 9):
|
16
15
|
from collections.abc import (
|
17
|
-
Collection,
|
18
|
-
Mapping,
|
19
|
-
Set,
|
20
|
-
Sequence,
|
21
16
|
AsyncGenerator,
|
22
17
|
Callable,
|
18
|
+
Collection,
|
23
19
|
Iterator,
|
20
|
+
Mapping,
|
21
|
+
Sequence,
|
22
|
+
Set,
|
24
23
|
)
|
25
24
|
else:
|
26
|
-
from typing import Collection, Mapping, Sequence, AsyncGenerator, Callable, Iterator
|
27
25
|
from typing import AbstractSet as Set
|
26
|
+
from typing import AsyncGenerator, Callable, Collection, Iterator, Mapping, Sequence
|
28
27
|
|
29
28
|
import aioshutil
|
30
29
|
|
31
|
-
from .
|
32
|
-
from .
|
30
|
+
from ._dictionaries import FoamFieldFile, FoamFile
|
31
|
+
from ._util import CalledProcessError, is_sequence, run_process, run_process_async
|
33
32
|
|
34
33
|
|
35
34
|
class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"]):
|
@@ -54,16 +53,12 @@ class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"]):
|
|
54
53
|
|
55
54
|
@property
|
56
55
|
def time(self) -> float:
|
57
|
-
"""
|
58
|
-
The time that corresponds to this directory.
|
59
|
-
"""
|
56
|
+
"""The time that corresponds to this directory."""
|
60
57
|
return float(self.path.name)
|
61
58
|
|
62
59
|
@property
|
63
60
|
def name(self) -> str:
|
64
|
-
"""
|
65
|
-
The name of this time directory.
|
66
|
-
"""
|
61
|
+
"""The name of this time directory."""
|
67
62
|
return self.path.name
|
68
63
|
|
69
64
|
def __getitem__(self, key: str) -> FoamFieldFile:
|
@@ -172,9 +167,7 @@ class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"]):
|
|
172
167
|
return ignore
|
173
168
|
|
174
169
|
def _clean_script(self) -> Optional[Path]:
|
175
|
-
"""
|
176
|
-
Return the path to the (All)clean script, or None if no clean script is found.
|
177
|
-
"""
|
170
|
+
"""Return the path to the (All)clean script, or None if no clean script is found."""
|
178
171
|
clean = self.path / "clean"
|
179
172
|
all_clean = self.path / "Allclean"
|
180
173
|
|
@@ -186,9 +179,7 @@ class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"]):
|
|
186
179
|
return None
|
187
180
|
|
188
181
|
def _run_script(self, *, parallel: Optional[bool]) -> Optional[Path]:
|
189
|
-
"""
|
190
|
-
Return the path to the (All)run script, or None if no run script is found.
|
191
|
-
"""
|
182
|
+
"""Return the path to the (All)run script, or None if no run script is found."""
|
192
183
|
run = self.path / "run"
|
193
184
|
run_parallel = self.path / "run-parallel"
|
194
185
|
all_run = self.path / "Allrun"
|
@@ -213,9 +204,7 @@ class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"]):
|
|
213
204
|
return None
|
214
205
|
|
215
206
|
def _env(self) -> Mapping[str, str]:
|
216
|
-
"""
|
217
|
-
Return the environment variables for this case.
|
218
|
-
"""
|
207
|
+
"""Return the environment variables for this case."""
|
219
208
|
env = os.environ.copy()
|
220
209
|
env["PWD"] = str(self.path)
|
221
210
|
return env
|
@@ -237,22 +226,16 @@ class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"]):
|
|
237
226
|
|
238
227
|
@property
|
239
228
|
def name(self) -> str:
|
240
|
-
"""
|
241
|
-
The name of the case.
|
242
|
-
"""
|
229
|
+
"""The name of the case."""
|
243
230
|
return self.path.name
|
244
231
|
|
245
232
|
def file(self, path: Union[Path, str]) -> FoamFile:
|
246
|
-
"""
|
247
|
-
Return a FoamFile object for the given path in the case.
|
248
|
-
"""
|
233
|
+
"""Return a FoamFile object for the given path in the case."""
|
249
234
|
return FoamFile(self.path / path)
|
250
235
|
|
251
236
|
@property
|
252
237
|
def _nsubdomains(self) -> Optional[int]:
|
253
|
-
"""
|
254
|
-
Return the number of subdomains as set in the decomposeParDict, or None if no decomposeParDict is found.
|
255
|
-
"""
|
238
|
+
"""Return the number of subdomains as set in the decomposeParDict, or None if no decomposeParDict is found."""
|
256
239
|
try:
|
257
240
|
nsubdomains = self.decompose_par_dict["numberOfSubdomains"]
|
258
241
|
if not isinstance(nsubdomains, int):
|
@@ -265,16 +248,12 @@ class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"]):
|
|
265
248
|
|
266
249
|
@property
|
267
250
|
def _nprocessors(self) -> int:
|
268
|
-
"""
|
269
|
-
Return the number of processor directories in the case.
|
270
|
-
"""
|
251
|
+
"""Return the number of processor directories in the case."""
|
271
252
|
return len(list(self.path.glob("processor*")))
|
272
253
|
|
273
254
|
@property
|
274
255
|
def application(self) -> str:
|
275
|
-
"""
|
276
|
-
The application name as set in the controlDict.
|
277
|
-
"""
|
256
|
+
"""The application name as set in the controlDict."""
|
278
257
|
application = self.control_dict["application"]
|
279
258
|
if not isinstance(application, str):
|
280
259
|
raise TypeError(f"application in {self.control_dict} is not a string")
|
@@ -282,51 +261,37 @@ class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"]):
|
|
282
261
|
|
283
262
|
@property
|
284
263
|
def control_dict(self) -> FoamFile:
|
285
|
-
"""
|
286
|
-
The controlDict file.
|
287
|
-
"""
|
264
|
+
"""The controlDict file."""
|
288
265
|
return self.file("system/controlDict")
|
289
266
|
|
290
267
|
@property
|
291
268
|
def fv_schemes(self) -> FoamFile:
|
292
|
-
"""
|
293
|
-
The fvSchemes file.
|
294
|
-
"""
|
269
|
+
"""The fvSchemes file."""
|
295
270
|
return self.file("system/fvSchemes")
|
296
271
|
|
297
272
|
@property
|
298
273
|
def fv_solution(self) -> FoamFile:
|
299
|
-
"""
|
300
|
-
The fvSolution file.
|
301
|
-
"""
|
274
|
+
"""The fvSolution file."""
|
302
275
|
return self.file("system/fvSolution")
|
303
276
|
|
304
277
|
@property
|
305
278
|
def decompose_par_dict(self) -> FoamFile:
|
306
|
-
"""
|
307
|
-
The decomposeParDict file.
|
308
|
-
"""
|
279
|
+
"""The decomposeParDict file."""
|
309
280
|
return self.file("system/decomposeParDict")
|
310
281
|
|
311
282
|
@property
|
312
283
|
def block_mesh_dict(self) -> FoamFile:
|
313
|
-
"""
|
314
|
-
The blockMeshDict file.
|
315
|
-
"""
|
284
|
+
"""The blockMeshDict file."""
|
316
285
|
return self.file("system/blockMeshDict")
|
317
286
|
|
318
287
|
@property
|
319
288
|
def transport_properties(self) -> FoamFile:
|
320
|
-
"""
|
321
|
-
The transportProperties file.
|
322
|
-
"""
|
289
|
+
"""The transportProperties file."""
|
323
290
|
return self.file("constant/transportProperties")
|
324
291
|
|
325
292
|
@property
|
326
293
|
def turbulence_properties(self) -> FoamFile:
|
327
|
-
"""
|
328
|
-
The turbulenceProperties file.
|
329
|
-
"""
|
294
|
+
"""The turbulenceProperties file."""
|
330
295
|
return self.file("constant/turbulenceProperties")
|
331
296
|
|
332
297
|
def __fspath__(self) -> str:
|
@@ -399,7 +364,7 @@ class FoamCase(FoamCaseBase):
|
|
399
364
|
)
|
400
365
|
except CalledProcessError as e:
|
401
366
|
raise RuntimeError(
|
402
|
-
f"{e.cmd} failed with return code {e.returncode}\n{e.stderr
|
367
|
+
f"{e.cmd} failed with return code {e.returncode}\n{e.stderr}"
|
403
368
|
) from None
|
404
369
|
|
405
370
|
else:
|
@@ -432,21 +397,15 @@ class FoamCase(FoamCaseBase):
|
|
432
397
|
)
|
433
398
|
|
434
399
|
def block_mesh(self, *, check: bool = True) -> None:
|
435
|
-
"""
|
436
|
-
Run blockMesh on this case.
|
437
|
-
"""
|
400
|
+
"""Run blockMesh on this case."""
|
438
401
|
self.run(["blockMesh"], check=check)
|
439
402
|
|
440
403
|
def decompose_par(self, *, check: bool = True) -> None:
|
441
|
-
"""
|
442
|
-
Decompose this case for parallel running.
|
443
|
-
"""
|
404
|
+
"""Decompose this case for parallel running."""
|
444
405
|
self.run(["decomposePar"], check=check)
|
445
406
|
|
446
407
|
def reconstruct_par(self, *, check: bool = True) -> None:
|
447
|
-
"""
|
448
|
-
Reconstruct this case after parallel running.
|
449
|
-
"""
|
408
|
+
"""Reconstruct this case after parallel running."""
|
450
409
|
self.run(["reconstructPar"], check=check)
|
451
410
|
|
452
411
|
def copy(self, dest: Union[Path, str]) -> "FoamCase":
|
@@ -574,7 +533,7 @@ class AsyncFoamCase(FoamCaseBase):
|
|
574
533
|
)
|
575
534
|
except CalledProcessError as e:
|
576
535
|
raise RuntimeError(
|
577
|
-
f"{e.cmd} failed with return code {e.returncode}\n{e.stderr
|
536
|
+
f"{e.cmd} failed with return code {e.returncode}\n{e.stderr}"
|
578
537
|
) from None
|
579
538
|
|
580
539
|
else:
|
@@ -624,21 +583,15 @@ class AsyncFoamCase(FoamCaseBase):
|
|
624
583
|
)
|
625
584
|
|
626
585
|
async def block_mesh(self, *, check: bool = True) -> None:
|
627
|
-
"""
|
628
|
-
Run blockMesh on this case.
|
629
|
-
"""
|
586
|
+
"""Run blockMesh on this case."""
|
630
587
|
await self.run(["blockMesh"], check=check)
|
631
588
|
|
632
589
|
async def decompose_par(self, *, check: bool = True) -> None:
|
633
|
-
"""
|
634
|
-
Decompose this case for parallel running.
|
635
|
-
"""
|
590
|
+
"""Decompose this case for parallel running."""
|
636
591
|
await self.run(["decomposePar"], check=check)
|
637
592
|
|
638
593
|
async def reconstruct_par(self, *, check: bool = True) -> None:
|
639
|
-
"""
|
640
|
-
Reconstruct this case after parallel running.
|
641
|
-
"""
|
594
|
+
"""Reconstruct this case after parallel running."""
|
642
595
|
await self.run(["reconstructPar"], check=check)
|
643
596
|
|
644
597
|
async def copy(self, dest: Union[Path, str]) -> "AsyncFoamCase":
|
foamlib/_dictionaries/_base.py
CHANGED
@@ -1,13 +1,18 @@
|
|
1
1
|
import sys
|
2
|
-
|
3
2
|
from abc import abstractmethod
|
4
3
|
from dataclasses import dataclass
|
5
4
|
from typing import Dict, NamedTuple, Optional, Union
|
6
5
|
|
7
6
|
if sys.version_info >= (3, 9):
|
8
|
-
from collections.abc import Sequence
|
7
|
+
from collections.abc import Mapping, Sequence
|
9
8
|
else:
|
10
|
-
from typing import Sequence
|
9
|
+
from typing import Mapping, Sequence
|
10
|
+
|
11
|
+
try:
|
12
|
+
import numpy as np
|
13
|
+
from numpy.typing import NDArray
|
14
|
+
except ModuleNotFoundError:
|
15
|
+
pass
|
11
16
|
|
12
17
|
|
13
18
|
class FoamDictionaryBase:
|
@@ -40,11 +45,13 @@ class FoamDictionaryBase:
|
|
40
45
|
A value that can be stored in an OpenFOAM dictionary.
|
41
46
|
"""
|
42
47
|
|
43
|
-
_Dict = Dict[str, Union["
|
48
|
+
_Dict = Dict[str, Union["Value", "_Dict"]]
|
44
49
|
|
45
50
|
@abstractmethod
|
46
51
|
def as_dict(self) -> _Dict:
|
47
|
-
"""
|
48
|
-
Return a nested dict representation of the dictionary.
|
49
|
-
"""
|
52
|
+
"""Return a nested dict representation of the dictionary."""
|
50
53
|
raise NotImplementedError
|
54
|
+
|
55
|
+
_SetValue = Union[Value, "NDArray[np.generic]"]
|
56
|
+
|
57
|
+
_SetMapping = Mapping[str, Union["_SetValue", "_SetMapping"]]
|
foamlib/_dictionaries/_files.py
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
import sys
|
2
|
-
|
3
2
|
from pathlib import Path
|
3
|
+
from types import TracebackType
|
4
4
|
from typing import (
|
5
5
|
Any,
|
6
6
|
Optional,
|
7
7
|
Tuple,
|
8
|
+
Type,
|
8
9
|
Union,
|
9
10
|
cast,
|
10
11
|
)
|
@@ -49,7 +50,12 @@ class _FoamFileBase:
|
|
49
50
|
self.__defer_io += 1
|
50
51
|
return self
|
51
52
|
|
52
|
-
def __exit__(
|
53
|
+
def __exit__(
|
54
|
+
self,
|
55
|
+
exc_type: Optional[Type[BaseException]],
|
56
|
+
exc_val: Optional[BaseException],
|
57
|
+
exc_tb: Optional[TracebackType],
|
58
|
+
) -> None:
|
53
59
|
self.__defer_io -= 1
|
54
60
|
if self.__defer_io == 0 and self.__dirty:
|
55
61
|
assert self.__contents is not None
|
@@ -99,9 +105,7 @@ class FoamFile(
|
|
99
105
|
FoamDictionaryBase,
|
100
106
|
MutableMapping[str, Union["FoamFile.Value", "FoamFile.Dictionary"]],
|
101
107
|
):
|
102
|
-
"""
|
103
|
-
An OpenFOAM dictionary within a file as a mutable mapping.
|
104
|
-
"""
|
108
|
+
"""An OpenFOAM dictionary within a file as a mutable mapping."""
|
105
109
|
|
106
110
|
def __init__(self, _file: "FoamFile", _keywords: Sequence[str]) -> None:
|
107
111
|
self._file = _file
|
@@ -127,7 +131,11 @@ class FoamFile(
|
|
127
131
|
assume_dimensions=assume_dimensions,
|
128
132
|
)
|
129
133
|
|
130
|
-
def __setitem__(
|
134
|
+
def __setitem__(
|
135
|
+
self,
|
136
|
+
keyword: str,
|
137
|
+
value: Union["FoamFile._SetValue", "FoamFile._SetMapping"],
|
138
|
+
) -> None:
|
131
139
|
self._setitem(keyword, value)
|
132
140
|
|
133
141
|
def __delitem__(self, keyword: str) -> None:
|
@@ -154,9 +162,7 @@ class FoamFile(
|
|
154
162
|
return f"{type(self).__qualname__}({self._file}, {self._keywords})"
|
155
163
|
|
156
164
|
def as_dict(self) -> FoamDictionaryBase._Dict:
|
157
|
-
"""
|
158
|
-
Return a nested dict representation of the dictionary.
|
159
|
-
"""
|
165
|
+
"""Return a nested dict representation of the dictionary."""
|
160
166
|
ret = self._file.as_dict()
|
161
167
|
|
162
168
|
for k in self._keywords:
|
@@ -185,7 +191,7 @@ class FoamFile(
|
|
185
191
|
def _setitem(
|
186
192
|
self,
|
187
193
|
keywords: Union[str, Tuple[str, ...]],
|
188
|
-
value:
|
194
|
+
value: Union["FoamFile._SetValue", "FoamFile._SetMapping"],
|
189
195
|
*,
|
190
196
|
assume_field: bool = False,
|
191
197
|
assume_dimensions: bool = False,
|
@@ -215,7 +221,11 @@ class FoamFile(
|
|
215
221
|
f"{contents[:start]}\n{serialize_entry(keywords[-1], value, assume_field=assume_field, assume_dimensions=assume_dimensions)}\n{contents[end:]}"
|
216
222
|
)
|
217
223
|
|
218
|
-
def __setitem__(
|
224
|
+
def __setitem__(
|
225
|
+
self,
|
226
|
+
keywords: Union[str, Tuple[str, ...]],
|
227
|
+
value: Union["FoamFile._SetValue", "FoamFile._SetMapping"],
|
228
|
+
) -> None:
|
219
229
|
self._setitem(keywords, value)
|
220
230
|
|
221
231
|
def __delitem__(self, keywords: Union[str, Tuple[str, ...]]) -> None:
|
@@ -264,9 +274,7 @@ class FoamFile(
|
|
264
274
|
return f"{type(self).__name__}({self.path})"
|
265
275
|
|
266
276
|
def as_dict(self) -> FoamDictionaryBase._Dict:
|
267
|
-
"""
|
268
|
-
Return a nested dict representation of the file.
|
269
|
-
"""
|
277
|
+
"""Return a nested dict representation of the file."""
|
270
278
|
_, parsed = self._read()
|
271
279
|
return as_dict(parsed)
|
272
280
|
|
@@ -281,7 +289,11 @@ class FoamFieldFile(FoamFile):
|
|
281
289
|
class BoundaryDictionary(FoamFile.Dictionary):
|
282
290
|
"""An OpenFOAM dictionary representing a boundary condition as a mutable mapping."""
|
283
291
|
|
284
|
-
def __setitem__(
|
292
|
+
def __setitem__(
|
293
|
+
self,
|
294
|
+
key: str,
|
295
|
+
value: Union[FoamFile._SetValue, FoamFile._SetMapping],
|
296
|
+
) -> None:
|
285
297
|
if key == "value":
|
286
298
|
self._setitem(key, value, assume_field=True)
|
287
299
|
else:
|
@@ -289,9 +301,7 @@ class FoamFieldFile(FoamFile):
|
|
289
301
|
|
290
302
|
@property
|
291
303
|
def type(self) -> str:
|
292
|
-
"""
|
293
|
-
Alias of `self["type"]`.
|
294
|
-
"""
|
304
|
+
"""Alias of `self["type"]`."""
|
295
305
|
ret = self["type"]
|
296
306
|
if not isinstance(ret, str):
|
297
307
|
raise TypeError("type is not a string")
|
@@ -310,9 +320,7 @@ class FoamFieldFile(FoamFile):
|
|
310
320
|
Sequence[Union[int, float, Sequence[Union[int, float]]]],
|
311
321
|
"NDArray[np.generic]",
|
312
322
|
]:
|
313
|
-
"""
|
314
|
-
Alias of `self["value"]`.
|
315
|
-
"""
|
323
|
+
"""Alias of `self["value"]`."""
|
316
324
|
ret = self["value"]
|
317
325
|
if not isinstance(ret, (int, float, Sequence)):
|
318
326
|
raise TypeError("value is not a field")
|
@@ -361,9 +369,7 @@ class FoamFieldFile(FoamFile):
|
|
361
369
|
|
362
370
|
@property
|
363
371
|
def dimensions(self) -> FoamFile.DimensionSet:
|
364
|
-
"""
|
365
|
-
Alias of `self["dimensions"]`.
|
366
|
-
"""
|
372
|
+
"""Alias of `self["dimensions"]`."""
|
367
373
|
ret = self["dimensions"]
|
368
374
|
if not isinstance(ret, FoamFile.DimensionSet):
|
369
375
|
raise TypeError("dimensions is not a DimensionSet")
|
@@ -384,9 +390,7 @@ class FoamFieldFile(FoamFile):
|
|
384
390
|
Sequence[Union[int, float, Sequence[Union[int, float]]]],
|
385
391
|
"NDArray[np.generic]",
|
386
392
|
]:
|
387
|
-
"""
|
388
|
-
Alias of `self["internalField"]`.
|
389
|
-
"""
|
393
|
+
"""Alias of `self["internalField"]`."""
|
390
394
|
ret = self["internalField"]
|
391
395
|
if not isinstance(ret, (int, float, Sequence)):
|
392
396
|
raise TypeError("internalField is not a field")
|
@@ -406,9 +410,7 @@ class FoamFieldFile(FoamFile):
|
|
406
410
|
|
407
411
|
@property
|
408
412
|
def boundary_field(self) -> "FoamFieldFile.BoundariesDictionary":
|
409
|
-
"""
|
410
|
-
Alias of `self["boundaryField"]`.
|
411
|
-
"""
|
413
|
+
"""Alias of `self["boundaryField"]`."""
|
412
414
|
ret = self["boundaryField"]
|
413
415
|
if not isinstance(ret, FoamFieldFile.BoundariesDictionary):
|
414
416
|
assert not isinstance(ret, FoamFile.Dictionary)
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import sys
|
2
|
-
|
3
2
|
from typing import Optional, Tuple
|
4
3
|
|
5
4
|
if sys.version_info >= (3, 9):
|
@@ -16,8 +15,8 @@ from pyparsing import (
|
|
16
15
|
Literal,
|
17
16
|
Located,
|
18
17
|
Opt,
|
19
|
-
ParseResults,
|
20
18
|
ParserElement,
|
19
|
+
ParseResults,
|
21
20
|
QuotedString,
|
22
21
|
Word,
|
23
22
|
c_style_comment,
|
@@ -29,8 +28,11 @@ from pyparsing import (
|
|
29
28
|
|
30
29
|
from ._base import FoamDictionaryBase
|
31
30
|
|
32
|
-
|
33
|
-
|
31
|
+
_SWITCH = (
|
32
|
+
Keyword("yes") | Keyword("true") | Keyword("on") | Keyword("y") | Keyword("t")
|
33
|
+
).set_parse_action(lambda: True) | (
|
34
|
+
Keyword("no") | Keyword("false") | Keyword("off") | Keyword("n") | Keyword("f")
|
35
|
+
).set_parse_action(lambda: False)
|
34
36
|
_DIMENSIONS = (
|
35
37
|
Literal("[").suppress() + common.number * 7 + Literal("]").suppress()
|
36
38
|
).set_parse_action(lambda tks: FoamDictionaryBase.DimensionSet(*tks))
|
@@ -65,9 +67,7 @@ _FIELD = (Keyword("uniform").suppress() + _TENSOR) | (
|
|
65
67
|
_TOKEN = QuotedString('"', unquote_results=False) | _IDENTIFIER
|
66
68
|
_ITEM = Forward()
|
67
69
|
_LIST = _list_of(_ITEM)
|
68
|
-
_ITEM <<=
|
69
|
-
_FIELD | _LIST | _DIMENSIONED | _DIMENSIONS | common.number | _YES | _NO | _TOKEN
|
70
|
-
)
|
70
|
+
_ITEM <<= _FIELD | _LIST | _DIMENSIONED | _DIMENSIONS | common.number | _SWITCH | _TOKEN
|
71
71
|
_TOKENS = (
|
72
72
|
QuotedString('"', unquote_results=False) | Word(printables.replace(";", ""))
|
73
73
|
)[2, ...].set_parse_action(lambda tks: " ".join(tks))
|
@@ -131,9 +131,7 @@ def get_value(
|
|
131
131
|
parsed: Parsed,
|
132
132
|
keywords: Tuple[str, ...],
|
133
133
|
) -> Optional[FoamDictionaryBase.Value]:
|
134
|
-
"""
|
135
|
-
Value of an entry.
|
136
|
-
"""
|
134
|
+
"""Value of an entry."""
|
137
135
|
_, value, _ = parsed[keywords]
|
138
136
|
return value
|
139
137
|
|
@@ -144,9 +142,7 @@ def get_entry_locn(
|
|
144
142
|
*,
|
145
143
|
missing_ok: bool = False,
|
146
144
|
) -> Tuple[int, int]:
|
147
|
-
"""
|
148
|
-
Location of an entry or where it should be inserted.
|
149
|
-
"""
|
145
|
+
"""Location of an entry or where it should be inserted."""
|
150
146
|
try:
|
151
147
|
start, _, end = parsed[keywords]
|
152
148
|
except KeyError:
|
@@ -165,9 +161,7 @@ def get_entry_locn(
|
|
165
161
|
|
166
162
|
|
167
163
|
def as_dict(parsed: Parsed) -> FoamDictionaryBase._Dict:
|
168
|
-
"""
|
169
|
-
Return a nested dict representation of the file.
|
170
|
-
"""
|
164
|
+
"""Return a nested dict representation of the file."""
|
171
165
|
ret: FoamDictionaryBase._Dict = {}
|
172
166
|
for keywords, (_, value, _) in parsed.items():
|
173
167
|
r = ret
|
@@ -1,18 +1,19 @@
|
|
1
1
|
import sys
|
2
|
-
|
3
2
|
from contextlib import suppress
|
4
|
-
from typing import
|
3
|
+
from typing import Union
|
5
4
|
|
6
5
|
if sys.version_info >= (3, 9):
|
7
6
|
from collections.abc import Mapping
|
8
7
|
else:
|
9
8
|
from typing import Mapping
|
10
9
|
|
11
|
-
from ._base import FoamDictionaryBase
|
12
10
|
from .._util import is_sequence
|
11
|
+
from ._base import FoamDictionaryBase
|
13
12
|
|
14
13
|
|
15
|
-
def
|
14
|
+
def _serialize_switch(
|
15
|
+
value: Union[FoamDictionaryBase._SetValue, FoamDictionaryBase._SetMapping],
|
16
|
+
) -> str:
|
16
17
|
if value is True:
|
17
18
|
return "yes"
|
18
19
|
elif value is False:
|
@@ -21,24 +22,28 @@ def _serialize_bool(value: Any) -> str:
|
|
21
22
|
raise TypeError(f"Not a bool: {type(value)}")
|
22
23
|
|
23
24
|
|
24
|
-
def _serialize_list(
|
25
|
+
def _serialize_list(
|
26
|
+
value: Union[FoamDictionaryBase._SetValue, FoamDictionaryBase._SetMapping],
|
27
|
+
) -> str:
|
25
28
|
if is_sequence(value):
|
26
29
|
return f"({' '.join(_serialize_value(v) for v in value)})"
|
27
30
|
else:
|
28
31
|
raise TypeError(f"Not a valid sequence: {type(value)}")
|
29
32
|
|
30
33
|
|
31
|
-
def _serialize_field(
|
34
|
+
def _serialize_field(
|
35
|
+
value: Union[FoamDictionaryBase._SetValue, FoamDictionaryBase._SetMapping],
|
36
|
+
) -> str:
|
32
37
|
if is_sequence(value):
|
33
38
|
try:
|
34
39
|
s = _serialize_list(value)
|
35
40
|
except TypeError:
|
36
41
|
raise TypeError(f"Not a valid field: {type(value)}") from None
|
37
42
|
else:
|
38
|
-
if len(value) < 10:
|
43
|
+
if not is_sequence(value[0]) and len(value) < 10:
|
39
44
|
return f"uniform {s}"
|
40
45
|
else:
|
41
|
-
if
|
46
|
+
if not is_sequence(value[0]):
|
42
47
|
kind = "scalar"
|
43
48
|
elif len(value[0]) == 3:
|
44
49
|
kind = "vector"
|
@@ -55,14 +60,18 @@ def _serialize_field(value: Any) -> str:
|
|
55
60
|
return f"uniform {value}"
|
56
61
|
|
57
62
|
|
58
|
-
def _serialize_dimensions(
|
63
|
+
def _serialize_dimensions(
|
64
|
+
value: Union[FoamDictionaryBase._SetValue, FoamDictionaryBase._SetMapping],
|
65
|
+
) -> str:
|
59
66
|
if is_sequence(value) and len(value) == 7:
|
60
67
|
return f"[{' '.join(str(v) for v in value)}]"
|
61
68
|
else:
|
62
69
|
raise TypeError(f"Not a valid dimension set: {type(value)}")
|
63
70
|
|
64
71
|
|
65
|
-
def _serialize_dimensioned(
|
72
|
+
def _serialize_dimensioned(
|
73
|
+
value: Union[FoamDictionaryBase._SetValue, FoamDictionaryBase._SetMapping],
|
74
|
+
) -> str:
|
66
75
|
if isinstance(value, FoamDictionaryBase.Dimensioned):
|
67
76
|
if value.name is not None:
|
68
77
|
return f"{value.name} {_serialize_dimensions(value.dimensions)} {_serialize_value(value.value)}"
|
@@ -73,7 +82,10 @@ def _serialize_dimensioned(value: Any) -> str:
|
|
73
82
|
|
74
83
|
|
75
84
|
def _serialize_value(
|
76
|
-
value:
|
85
|
+
value: Union[FoamDictionaryBase._SetValue, FoamDictionaryBase._SetMapping],
|
86
|
+
*,
|
87
|
+
assume_field: bool = False,
|
88
|
+
assume_dimensions: bool = False,
|
77
89
|
) -> str:
|
78
90
|
if isinstance(value, FoamDictionaryBase.DimensionSet) or assume_dimensions:
|
79
91
|
with suppress(TypeError):
|
@@ -90,12 +102,14 @@ def _serialize_value(
|
|
90
102
|
return _serialize_list(value)
|
91
103
|
|
92
104
|
with suppress(TypeError):
|
93
|
-
return
|
105
|
+
return _serialize_switch(value)
|
94
106
|
|
95
107
|
return str(value)
|
96
108
|
|
97
109
|
|
98
|
-
def _serialize_dictionary(
|
110
|
+
def _serialize_dictionary(
|
111
|
+
value: Union[FoamDictionaryBase._SetValue, FoamDictionaryBase._SetMapping],
|
112
|
+
) -> str:
|
99
113
|
if isinstance(value, Mapping):
|
100
114
|
return "\n".join(serialize_entry(k, v) for k, v in value.items())
|
101
115
|
else:
|
@@ -104,7 +118,7 @@ def _serialize_dictionary(value: Any) -> str:
|
|
104
118
|
|
105
119
|
def serialize_entry(
|
106
120
|
keyword: str,
|
107
|
-
value:
|
121
|
+
value: Union[FoamDictionaryBase._SetValue, FoamDictionaryBase._SetMapping],
|
108
122
|
*,
|
109
123
|
assume_field: bool = False,
|
110
124
|
assume_dimensions: bool = False,
|
foamlib/_util.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
import asyncio
|
2
|
-
import sys
|
3
2
|
import subprocess
|
4
|
-
|
3
|
+
import sys
|
5
4
|
from pathlib import Path
|
6
5
|
from typing import Any, Union
|
7
6
|
|
@@ -36,6 +35,11 @@ def is_sequence(
|
|
36
35
|
|
37
36
|
CalledProcessError = subprocess.CalledProcessError
|
38
37
|
|
38
|
+
if sys.version_info >= (3, 9):
|
39
|
+
CompletedProcess = subprocess.CompletedProcess[str]
|
40
|
+
else:
|
41
|
+
CompletedProcess = subprocess.CompletedProcess
|
42
|
+
|
39
43
|
|
40
44
|
def run_process(
|
41
45
|
cmd: Union[Sequence[Union[str, Path]], str, Path],
|
@@ -43,7 +47,7 @@ def run_process(
|
|
43
47
|
check: bool = True,
|
44
48
|
cwd: Union[None, str, Path] = None,
|
45
49
|
env: Union[None, Mapping[str, str]] = None,
|
46
|
-
) ->
|
50
|
+
) -> CompletedProcess:
|
47
51
|
shell = not is_sequence(cmd)
|
48
52
|
|
49
53
|
if sys.version_info < (3, 8):
|
@@ -56,7 +60,9 @@ def run_process(
|
|
56
60
|
cmd,
|
57
61
|
cwd=cwd,
|
58
62
|
env=env,
|
59
|
-
|
63
|
+
stdout=asyncio.subprocess.DEVNULL,
|
64
|
+
stderr=asyncio.subprocess.PIPE,
|
65
|
+
text=True,
|
60
66
|
shell=shell,
|
61
67
|
check=check,
|
62
68
|
)
|
@@ -70,13 +76,13 @@ async def run_process_async(
|
|
70
76
|
check: bool = True,
|
71
77
|
cwd: Union[None, str, Path] = None,
|
72
78
|
env: Union[None, Mapping[str, str]] = None,
|
73
|
-
) ->
|
79
|
+
) -> CompletedProcess:
|
74
80
|
if not is_sequence(cmd):
|
75
81
|
proc = await asyncio.create_subprocess_shell(
|
76
82
|
str(cmd),
|
77
83
|
cwd=cwd,
|
78
84
|
env=env,
|
79
|
-
stdout=asyncio.subprocess.
|
85
|
+
stdout=asyncio.subprocess.DEVNULL,
|
80
86
|
stderr=asyncio.subprocess.PIPE,
|
81
87
|
)
|
82
88
|
|
@@ -87,15 +93,16 @@ async def run_process_async(
|
|
87
93
|
*cmd,
|
88
94
|
cwd=cwd,
|
89
95
|
env=env,
|
90
|
-
stdout=asyncio.subprocess.
|
96
|
+
stdout=asyncio.subprocess.DEVNULL,
|
91
97
|
stderr=asyncio.subprocess.PIPE,
|
92
98
|
)
|
93
99
|
|
94
100
|
stdout, stderr = await proc.communicate()
|
95
101
|
|
102
|
+
assert stdout is None
|
96
103
|
assert proc.returncode is not None
|
97
104
|
|
98
|
-
ret =
|
105
|
+
ret = CompletedProcess(cmd, proc.returncode, None, stderr.decode())
|
99
106
|
|
100
107
|
if check:
|
101
108
|
ret.check_returncode()
|
@@ -0,0 +1,14 @@
|
|
1
|
+
foamlib/__init__.py,sha256=ZWFEP5x2m2c9zMrODOS9_vL4bf6FPnK7BY-DTLXu3JU,344
|
2
|
+
foamlib/_cases.py,sha256=SjDTVauOlcrtyvnt5uxWGSu2RYZ0lhKRmvMnuRnRuzI,20973
|
3
|
+
foamlib/_util.py,sha256=PBTpBwt_j1GXASncSDZUR8pH2u_h8UyJXm8GeFKebTY,2552
|
4
|
+
foamlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
+
foamlib/_dictionaries/__init__.py,sha256=vxGpA7uaEbJwKFGOYdLFR6R9jcUj_HW60YzZBMjNXRo,160
|
6
|
+
foamlib/_dictionaries/_base.py,sha256=i_RRwJYP11fG-e9jAqH2lN5wz4BOPNWs_frqyLInSrc,1809
|
7
|
+
foamlib/_dictionaries/_files.py,sha256=ZIIImssk9Xqgx8kYz_mr2e3IHGze1J96BvDQxQeNVaA,12912
|
8
|
+
foamlib/_dictionaries/_parsing.py,sha256=s6t9JJxAjsSp3ypeQNeskgtYWsbb52iBjrVDTUv56jc,5008
|
9
|
+
foamlib/_dictionaries/_serialization.py,sha256=kaec7AzGOERmPAeMP3Li1ZU7jyectsUS5WHgQbeT-2Y,4045
|
10
|
+
foamlib-0.2.7.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
|
11
|
+
foamlib-0.2.7.dist-info/METADATA,sha256=wwLtfgXWX2iXnqLI7jVNZHIpoVE52ZDpWvhibNc6wmA,4650
|
12
|
+
foamlib-0.2.7.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
13
|
+
foamlib-0.2.7.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
|
14
|
+
foamlib-0.2.7.dist-info/RECORD,,
|
foamlib-0.2.5.dist-info/RECORD
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
foamlib/__init__.py,sha256=ncl1G6iN85s3zP7aVBqzekY5wHCoOn8dpJxXW2e36vI,287
|
2
|
-
foamlib/_cases.py,sha256=SbMaaKdhYbgmgdxWZNB7j47P04QxZ3VVq4sP9HbTLpA,21422
|
3
|
-
foamlib/_util.py,sha256=ICs_Bc2jXpxzOUos6Cnl0blUwz1P6r1f1swP8k9Bex0,2347
|
4
|
-
foamlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
-
foamlib/_dictionaries/__init__.py,sha256=6UWBGe1t7cq-d6WWQrVm0Xpi7Whpkr-mkTWgAM4NwcE,160
|
6
|
-
foamlib/_dictionaries/_base.py,sha256=0Qic347JzJBMgBc0gHfuAGmQMWYGEn7IfJ9vKd4pm_I,1606
|
7
|
-
foamlib/_dictionaries/_files.py,sha256=Qyw04I5hqGRkHR7KWGmMdX6LyVtat1zKf50bo7CRIoU,12626
|
8
|
-
foamlib/_dictionaries/_parsing.py,sha256=w7AOyoPPghsG06WK_1fXU-udU_F8J_zuvV9eIf07P8M,4905
|
9
|
-
foamlib/_dictionaries/_serialization.py,sha256=8YInaQ0HnlDe4RnwocvTlJJkVFR7XDqGsuN4ABAyUCE,3452
|
10
|
-
foamlib-0.2.5.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
|
11
|
-
foamlib-0.2.5.dist-info/METADATA,sha256=PuzWIZKasSyaUKpO0H_g67r6wqLyswQyOzzelaiHLpQ,4650
|
12
|
-
foamlib-0.2.5.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
13
|
-
foamlib-0.2.5.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
|
14
|
-
foamlib-0.2.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|