foamlib 0.7.3__py3-none-any.whl → 0.8.1__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 +2 -2
- foamlib/_cases/__init__.py +2 -2
- foamlib/_cases/_base.py +2 -9
- foamlib/_cases/_util.py +1 -8
- foamlib/_files/__init__.py +1 -1
- foamlib/_files/_files.py +31 -45
- foamlib/_files/_io.py +1 -3
- foamlib/_files/_parsing.py +148 -103
- foamlib/_files/_serialization.py +65 -87
- foamlib/_files/_types.py +39 -10
- {foamlib-0.7.3.dist-info → foamlib-0.8.1.dist-info}/METADATA +27 -27
- foamlib-0.8.1.dist-info/RECORD +20 -0
- {foamlib-0.7.3.dist-info → foamlib-0.8.1.dist-info}/WHEEL +1 -2
- foamlib/_files/_util.py +0 -23
- foamlib-0.7.3.dist-info/RECORD +0 -22
- foamlib-0.7.3.dist-info/top_level.txt +0 -1
- {foamlib-0.7.3.dist-info → foamlib-0.8.1.dist-info/licenses}/LICENSE.txt +0 -0
foamlib/__init__.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
"""A Python interface for interacting with OpenFOAM."""
|
2
2
|
|
3
|
-
__version__ = "0.
|
3
|
+
__version__ = "0.8.1"
|
4
4
|
|
5
5
|
from ._cases import (
|
6
6
|
AsyncFoamCase,
|
@@ -16,9 +16,9 @@ __all__ = [
|
|
16
16
|
"AsyncFoamCase",
|
17
17
|
"AsyncSlurmFoamCase",
|
18
18
|
"CalledProcessError",
|
19
|
-
"FoamFile",
|
20
19
|
"FoamCase",
|
21
20
|
"FoamCaseBase",
|
22
21
|
"FoamCaseRunBase",
|
23
22
|
"FoamFieldFile",
|
23
|
+
"FoamFile",
|
24
24
|
]
|
foamlib/_cases/__init__.py
CHANGED
foamlib/_cases/_base.py
CHANGED
@@ -6,17 +6,10 @@ from pathlib import Path
|
|
6
6
|
from typing import TYPE_CHECKING, overload
|
7
7
|
|
8
8
|
if sys.version_info >= (3, 9):
|
9
|
-
from collections.abc import
|
10
|
-
Iterator,
|
11
|
-
Sequence,
|
12
|
-
)
|
9
|
+
from collections.abc import Iterator, Sequence
|
13
10
|
from collections.abc import Set as AbstractSet
|
14
11
|
else:
|
15
|
-
from typing import
|
16
|
-
AbstractSet,
|
17
|
-
Iterator,
|
18
|
-
Sequence,
|
19
|
-
)
|
12
|
+
from typing import AbstractSet, Iterator, Sequence
|
20
13
|
|
21
14
|
from .._files import FoamFieldFile, FoamFile
|
22
15
|
|
foamlib/_cases/_util.py
CHANGED
@@ -2,14 +2,7 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import functools
|
4
4
|
import sys
|
5
|
-
from typing import
|
6
|
-
TYPE_CHECKING,
|
7
|
-
Any,
|
8
|
-
AsyncContextManager,
|
9
|
-
Callable,
|
10
|
-
Generic,
|
11
|
-
TypeVar,
|
12
|
-
)
|
5
|
+
from typing import TYPE_CHECKING, Any, AsyncContextManager, Callable, Generic, TypeVar
|
13
6
|
|
14
7
|
if TYPE_CHECKING:
|
15
8
|
from types import TracebackType
|
foamlib/_files/__init__.py
CHANGED
foamlib/_files/_files.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import os
|
4
3
|
import sys
|
5
4
|
from copy import deepcopy
|
6
5
|
from typing import Any, Optional, Tuple, Union, cast
|
@@ -15,6 +14,8 @@ if sys.version_info >= (3, 9):
|
|
15
14
|
else:
|
16
15
|
from typing import Iterator, Mapping, MutableMapping, Sequence
|
17
16
|
|
17
|
+
import numpy as np
|
18
|
+
|
18
19
|
from ._io import FoamFileIO
|
19
20
|
from ._serialization import Kind, dumps, normalize
|
20
21
|
from ._types import (
|
@@ -25,15 +26,14 @@ from ._types import (
|
|
25
26
|
Entry,
|
26
27
|
Field,
|
27
28
|
File,
|
28
|
-
|
29
|
+
MutableEntry,
|
29
30
|
)
|
30
|
-
from ._util import is_sequence
|
31
31
|
|
32
32
|
|
33
33
|
class FoamFile(
|
34
34
|
MutableMapping[
|
35
35
|
Optional[Union[str, Tuple[str, ...]]],
|
36
|
-
|
36
|
+
MutableEntry,
|
37
37
|
],
|
38
38
|
FoamFileIO,
|
39
39
|
):
|
@@ -49,7 +49,7 @@ class FoamFile(
|
|
49
49
|
DimensionSet = DimensionSet
|
50
50
|
|
51
51
|
class SubDict(
|
52
|
-
MutableMapping[str,
|
52
|
+
MutableMapping[str, MutableEntry],
|
53
53
|
):
|
54
54
|
"""An OpenFOAM dictionary within a file as a mutable mapping."""
|
55
55
|
|
@@ -196,7 +196,7 @@ class FoamFile(
|
|
196
196
|
elif not isinstance(keywords, tuple):
|
197
197
|
keywords = (keywords,)
|
198
198
|
|
199
|
-
if keywords and not isinstance(normalize(keywords[-1]
|
199
|
+
if keywords and not isinstance(normalize(keywords[-1]), str):
|
200
200
|
msg = f"Invalid keyword: {keywords[-1]}"
|
201
201
|
raise ValueError(msg)
|
202
202
|
|
@@ -228,50 +228,36 @@ class FoamFile(
|
|
228
228
|
or keywords[2].endswith("Gradient")
|
229
229
|
)
|
230
230
|
):
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
if (arch is not None and "scalar=32" in arch) or (
|
235
|
-
arch is None
|
236
|
-
and os.environ.get("WM_PRECISION_OPTION", default="DP") == "SP"
|
237
|
-
):
|
238
|
-
kind = Kind.SINGLE_PRECISION_BINARY_FIELD
|
239
|
-
else:
|
240
|
-
kind = Kind.DOUBLE_PRECISION_BINARY_FIELD
|
241
|
-
else:
|
242
|
-
kind = Kind.ASCII_FIELD
|
231
|
+
kind = (
|
232
|
+
Kind.BINARY_FIELD if self.format == "binary" else Kind.ASCII_FIELD
|
233
|
+
)
|
243
234
|
elif keywords == ("dimensions",):
|
244
235
|
kind = Kind.DIMENSIONS
|
245
236
|
|
246
237
|
if (
|
247
|
-
kind
|
248
|
-
in (
|
249
|
-
Kind.ASCII_FIELD,
|
250
|
-
Kind.DOUBLE_PRECISION_BINARY_FIELD,
|
251
|
-
Kind.SINGLE_PRECISION_BINARY_FIELD,
|
252
|
-
)
|
238
|
+
kind in (Kind.ASCII_FIELD, Kind.BINARY_FIELD)
|
253
239
|
) and self.class_ == "dictionary":
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
elif (
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
):
|
270
|
-
if
|
240
|
+
try:
|
241
|
+
shape = np.shape(data) # type: ignore [arg-type]
|
242
|
+
except ValueError:
|
243
|
+
pass
|
244
|
+
else:
|
245
|
+
if not shape:
|
246
|
+
self.class_ = "volScalarField"
|
247
|
+
elif shape == (3,):
|
248
|
+
self.class_ = "volVectorField"
|
249
|
+
elif shape == (6,):
|
250
|
+
self.class_ = "volSymmTensorField"
|
251
|
+
elif shape == (9,):
|
252
|
+
self.class_ = "volTensorField"
|
253
|
+
elif len(shape) == 1:
|
254
|
+
self.class_ = "volScalarField"
|
255
|
+
elif len(shape) == 2:
|
256
|
+
if shape[1] == 3:
|
271
257
|
self.class_ = "volVectorField"
|
272
|
-
elif
|
258
|
+
elif shape[1] == 6:
|
273
259
|
self.class_ = "volSymmTensorField"
|
274
|
-
elif
|
260
|
+
elif shape[1] == 9:
|
275
261
|
self.class_ = "volTensorField"
|
276
262
|
|
277
263
|
parsed = self._get_parsed(missing_ok=True)
|
@@ -304,7 +290,7 @@ class FoamFile(
|
|
304
290
|
...,
|
305
291
|
before
|
306
292
|
+ indentation
|
307
|
-
+ dumps(keywords[-1]
|
293
|
+
+ dumps(keywords[-1])
|
308
294
|
+ b"\n"
|
309
295
|
+ indentation
|
310
296
|
+ b"{\n"
|
@@ -322,7 +308,7 @@ class FoamFile(
|
|
322
308
|
normalize(data, kind=kind),
|
323
309
|
before
|
324
310
|
+ indentation
|
325
|
-
+ dumps(keywords[-1]
|
311
|
+
+ dumps(keywords[-1])
|
326
312
|
+ b" "
|
327
313
|
+ dumps(data, kind=kind)
|
328
314
|
+ b";"
|
foamlib/_files/_io.py
CHANGED
foamlib/_files/_parsing.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import array
|
4
3
|
import re
|
5
4
|
import sys
|
5
|
+
from enum import Enum, auto
|
6
6
|
from typing import Tuple, Union, cast
|
7
7
|
|
8
8
|
if sys.version_info >= (3, 9):
|
@@ -13,8 +13,9 @@ else:
|
|
13
13
|
if sys.version_info >= (3, 10):
|
14
14
|
from types import EllipsisType
|
15
15
|
else:
|
16
|
-
|
16
|
+
EllipsisType = type(...)
|
17
17
|
|
18
|
+
import numpy as np
|
18
19
|
from pyparsing import (
|
19
20
|
Combine,
|
20
21
|
Dict,
|
@@ -39,6 +40,64 @@ from pyparsing import (
|
|
39
40
|
from ._types import Data, Dimensioned, DimensionSet, File
|
40
41
|
|
41
42
|
|
43
|
+
class _Tensor(Enum):
|
44
|
+
SCALAR = auto()
|
45
|
+
VECTOR = auto()
|
46
|
+
SYMM_TENSOR = auto()
|
47
|
+
TENSOR = auto()
|
48
|
+
|
49
|
+
@property
|
50
|
+
def shape(self) -> tuple[()] | tuple[int]:
|
51
|
+
if self == _Tensor.SCALAR:
|
52
|
+
return ()
|
53
|
+
if self == _Tensor.VECTOR:
|
54
|
+
return (3,)
|
55
|
+
if self == _Tensor.SYMM_TENSOR:
|
56
|
+
return (6,)
|
57
|
+
if self == _Tensor.TENSOR:
|
58
|
+
return (9,)
|
59
|
+
raise NotImplementedError
|
60
|
+
|
61
|
+
@property
|
62
|
+
def size(self) -> int:
|
63
|
+
return {
|
64
|
+
_Tensor.SCALAR: 1,
|
65
|
+
_Tensor.VECTOR: 3,
|
66
|
+
_Tensor.SYMM_TENSOR: 6,
|
67
|
+
_Tensor.TENSOR: 9,
|
68
|
+
}[self]
|
69
|
+
|
70
|
+
def pattern(self, *, ignore: Regex | None = None) -> str:
|
71
|
+
float_pattern = r"(?i:[+-]?(?:(?:\d+\.?\d*(?:e[+-]?\d+)?)|nan|inf(?:inity)?))"
|
72
|
+
|
73
|
+
if self == _Tensor.SCALAR:
|
74
|
+
return float_pattern
|
75
|
+
|
76
|
+
ignore_pattern = (
|
77
|
+
rf"(?:\s|{ignore.re.pattern})+" if ignore is not None else r"\s+"
|
78
|
+
)
|
79
|
+
|
80
|
+
return rf"\((?:{ignore_pattern})?(?:{float_pattern}{ignore_pattern}){{{self.size - 1}}}{float_pattern}(?:{ignore_pattern})?\)"
|
81
|
+
|
82
|
+
def parser(self) -> ParserElement:
|
83
|
+
if self == _Tensor.SCALAR:
|
84
|
+
return common.ieee_float
|
85
|
+
|
86
|
+
return (
|
87
|
+
Literal("(").suppress()
|
88
|
+
+ Group(common.ieee_float[self.size], aslist=True)
|
89
|
+
+ Literal(")").suppress()
|
90
|
+
).add_parse_action(lambda tks: np.array(tks[0], dtype=float))
|
91
|
+
|
92
|
+
def __str__(self) -> str:
|
93
|
+
return {
|
94
|
+
_Tensor.SCALAR: "scalar",
|
95
|
+
_Tensor.VECTOR: "vector",
|
96
|
+
_Tensor.SYMM_TENSOR: "symmTensor",
|
97
|
+
_Tensor.TENSOR: "tensor",
|
98
|
+
}[self]
|
99
|
+
|
100
|
+
|
42
101
|
def _list_of(entry: ParserElement) -> ParserElement:
|
43
102
|
return Opt(
|
44
103
|
Literal("List") + Literal("<") + _IDENTIFIER + Literal(">")
|
@@ -59,56 +118,47 @@ def _list_of(entry: ParserElement) -> ParserElement:
|
|
59
118
|
|
60
119
|
|
61
120
|
def _parse_ascii_field(
|
62
|
-
s: str,
|
63
|
-
) ->
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
.replace("(", " ")
|
68
|
-
.replace(")", " ")
|
69
|
-
.split()
|
70
|
-
]
|
121
|
+
s: str, tensor_kind: _Tensor, *, ignore: Regex | None
|
122
|
+
) -> np.ndarray[tuple[int] | tuple[int, int], np.dtype[np.float64]]:
|
123
|
+
if ignore is not None:
|
124
|
+
s = re.sub(ignore.re, " ", s)
|
125
|
+
s = s.replace("(", " ").replace(")", " ")
|
71
126
|
|
72
|
-
|
73
|
-
return values
|
74
|
-
|
75
|
-
return [values[i : i + elsize] for i in range(0, len(values), elsize)]
|
127
|
+
return np.fromstring(s, dtype=float, sep=" ").reshape(-1, *tensor_kind.shape)
|
76
128
|
|
77
129
|
|
78
130
|
def _unpack_binary_field(
|
79
|
-
b: bytes,
|
80
|
-
) ->
|
81
|
-
float_size = len(b) /
|
131
|
+
b: bytes, tensor_kind: _Tensor, *, length: int
|
132
|
+
) -> np.ndarray[tuple[int] | tuple[int, int], np.dtype[np.float64 | np.float32]]:
|
133
|
+
float_size = len(b) / tensor_kind.size / length
|
82
134
|
assert float_size in (4, 8)
|
83
135
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
if elsize == 1:
|
88
|
-
return values
|
136
|
+
dtype = np.float32 if float_size == 4 else float
|
137
|
+
return np.frombuffer(b, dtype=dtype).reshape(-1, *tensor_kind.shape)
|
89
138
|
|
90
|
-
return [values[i : i + elsize] for i in range(0, len(values), elsize)]
|
91
139
|
|
92
|
-
|
93
|
-
|
94
|
-
*, elsize: int = 1, ignore: Regex | None = None
|
140
|
+
def _tensor_list(
|
141
|
+
tensor_kind: _Tensor | None = None, *, ignore: Regex | None = None
|
95
142
|
) -> ParserElement:
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
else:
|
103
|
-
tensor_pattern = rf"\((?:{ignore_pattern})?(?:{float_pattern}{ignore_pattern}){{{elsize - 1}}}{float_pattern}(?:{ignore_pattern})?\)"
|
104
|
-
tensor = (
|
105
|
-
Literal("(").suppress()
|
106
|
-
+ Group(common.ieee_float[elsize], aslist=True)
|
107
|
-
+ Literal(")").suppress()
|
143
|
+
if tensor_kind is None:
|
144
|
+
return (
|
145
|
+
_tensor_list(_Tensor.SCALAR, ignore=ignore)
|
146
|
+
| _tensor_list(_Tensor.VECTOR, ignore=ignore)
|
147
|
+
| _tensor_list(_Tensor.SYMM_TENSOR, ignore=ignore)
|
148
|
+
| _tensor_list(_Tensor.TENSOR, ignore=ignore)
|
108
149
|
)
|
109
150
|
|
151
|
+
tensor_pattern = tensor_kind.pattern(ignore=ignore)
|
152
|
+
ignore_pattern = rf"(?:\s|{ignore.re.pattern})+" if ignore is not None else r"\s+"
|
153
|
+
|
110
154
|
list_ = Forward()
|
111
155
|
|
156
|
+
list_ <<= Regex(
|
157
|
+
rf"\((?:{ignore_pattern})?(?:{tensor_pattern}{ignore_pattern})*{tensor_pattern}(?:{ignore_pattern})?\)"
|
158
|
+
).add_parse_action(
|
159
|
+
lambda tks: [_parse_ascii_field(tks[0], tensor_kind, ignore=ignore)]
|
160
|
+
)
|
161
|
+
|
112
162
|
def count_parse_action(tks: ParseResults) -> None:
|
113
163
|
nonlocal list_
|
114
164
|
length = tks[0]
|
@@ -118,44 +168,66 @@ def _counted_tensor_list(
|
|
118
168
|
Regex(
|
119
169
|
rf"\((?:{ignore_pattern})?(?:{tensor_pattern}{ignore_pattern}){{{length - 1}}}{tensor_pattern}(?:{ignore_pattern})?\)"
|
120
170
|
).add_parse_action(
|
121
|
-
lambda tks: [_parse_ascii_field(tks[0],
|
171
|
+
lambda tks: [_parse_ascii_field(tks[0], tensor_kind, ignore=ignore)]
|
122
172
|
)
|
123
173
|
| Regex(
|
124
|
-
rf"\((?s:.{{{length *
|
125
|
-
).
|
174
|
+
rf"\((?s:.{{{length * tensor_kind.size * 8}}}|.{{{length * tensor_kind.size * 4}}})\)"
|
175
|
+
).add_parse_action(
|
126
176
|
lambda tks: [
|
127
177
|
_unpack_binary_field(
|
128
|
-
tks[0][1:-1].encode("latin-1"),
|
178
|
+
tks[0][1:-1].encode("latin-1"), tensor_kind, length=length
|
129
179
|
)
|
130
180
|
]
|
131
181
|
)
|
132
182
|
| (
|
133
|
-
Literal("{").suppress() +
|
134
|
-
).
|
183
|
+
Literal("{").suppress() + tensor_kind.parser() + Literal("}").suppress()
|
184
|
+
).add_parse_action(
|
185
|
+
lambda tks: [np.full((length, *tensor_kind.shape), tks[0], dtype=float)]
|
186
|
+
)
|
135
187
|
)
|
136
188
|
|
137
189
|
count = common.integer.copy().add_parse_action(count_parse_action)
|
138
190
|
|
139
|
-
return
|
191
|
+
return (
|
192
|
+
Opt(Literal("List") + Literal("<") + str(tensor_kind) + Literal(">")).suppress()
|
193
|
+
+ Opt(count).suppress()
|
194
|
+
+ list_
|
195
|
+
)
|
196
|
+
|
197
|
+
|
198
|
+
def _dict_of(
|
199
|
+
keyword: ParserElement, data: ParserElement, *, located: bool = False
|
200
|
+
) -> ParserElement:
|
201
|
+
dict_ = Forward()
|
202
|
+
|
203
|
+
keyword_entry = keyword + (dict_ | (data + Literal(";").suppress()))
|
204
|
+
|
205
|
+
if located:
|
206
|
+
keyword_entry = Located(keyword_entry)
|
207
|
+
|
208
|
+
dict_ <<= (
|
209
|
+
Literal("{").suppress()
|
210
|
+
+ Dict(Group(keyword_entry)[...], asdict=not located)
|
211
|
+
+ Literal("}").suppress()
|
212
|
+
)
|
213
|
+
|
214
|
+
return dict_
|
140
215
|
|
141
216
|
|
142
217
|
def _keyword_entry_of(
|
143
218
|
keyword: ParserElement,
|
144
|
-
|
219
|
+
data: ParserElement,
|
145
220
|
*,
|
146
221
|
located: bool = False,
|
147
222
|
) -> ParserElement:
|
148
|
-
subdict = Forward()
|
149
|
-
|
150
223
|
keyword_entry = keyword + (
|
151
|
-
(
|
152
|
-
| (data_entries + Literal(";").suppress())
|
224
|
+
_dict_of(keyword, data, located=located) | (data + Literal(";").suppress())
|
153
225
|
)
|
154
226
|
|
155
227
|
if located:
|
156
228
|
keyword_entry = Located(keyword_entry)
|
157
|
-
|
158
|
-
|
229
|
+
else:
|
230
|
+
keyword_entry = keyword_entry.copy().set_parse_action(lambda tks: tuple(tks))
|
159
231
|
|
160
232
|
return keyword_entry
|
161
233
|
|
@@ -188,12 +260,11 @@ _SWITCH = (
|
|
188
260
|
_DIMENSIONS = (
|
189
261
|
Literal("[").suppress() + common.number[0, 7] + Literal("]").suppress()
|
190
262
|
).set_parse_action(lambda tks: DimensionSet(*tks))
|
191
|
-
_TENSOR =
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
)
|
196
|
-
+ Literal(")").suppress()
|
263
|
+
_TENSOR = (
|
264
|
+
_Tensor.SCALAR.parser()
|
265
|
+
| _Tensor.VECTOR.parser()
|
266
|
+
| _Tensor.SYMM_TENSOR.parser()
|
267
|
+
| _Tensor.TENSOR.parser()
|
197
268
|
)
|
198
269
|
_IDENTIFIER = Combine(
|
199
270
|
Word(_IDENTCHARS, _IDENTBODYCHARS, exclude_chars="()")
|
@@ -203,63 +274,37 @@ _DIMENSIONED = (Opt(_IDENTIFIER) + _DIMENSIONS + _TENSOR).set_parse_action(
|
|
203
274
|
lambda tks: Dimensioned(*reversed(tks.as_list()))
|
204
275
|
)
|
205
276
|
_FIELD = (Keyword("uniform", _IDENTBODYCHARS).suppress() + _TENSOR) | (
|
206
|
-
Keyword("nonuniform", _IDENTBODYCHARS).suppress()
|
207
|
-
+ (
|
208
|
-
Literal("List").suppress()
|
209
|
-
+ Literal("<").suppress()
|
210
|
-
+ (
|
211
|
-
(
|
212
|
-
Literal("scalar").suppress()
|
213
|
-
+ Literal(">").suppress()
|
214
|
-
+ _counted_tensor_list(elsize=1, ignore=_COMMENT)
|
215
|
-
)
|
216
|
-
| (
|
217
|
-
Literal("vector").suppress()
|
218
|
-
+ Literal(">").suppress()
|
219
|
-
+ _counted_tensor_list(elsize=3, ignore=_COMMENT)
|
220
|
-
)
|
221
|
-
| (
|
222
|
-
Literal("symmTensor").suppress()
|
223
|
-
+ Literal(">").suppress()
|
224
|
-
+ _counted_tensor_list(elsize=6, ignore=_COMMENT)
|
225
|
-
)
|
226
|
-
| (
|
227
|
-
Literal("tensor").suppress()
|
228
|
-
+ Literal(">").suppress()
|
229
|
-
+ _counted_tensor_list(elsize=9, ignore=_COMMENT)
|
230
|
-
)
|
231
|
-
)
|
232
|
-
)
|
277
|
+
Keyword("nonuniform", _IDENTBODYCHARS).suppress() + _tensor_list(ignore=_COMMENT)
|
233
278
|
)
|
234
279
|
_TOKEN = dbl_quoted_string | _IDENTIFIER
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
| _list_of(_IDENTIFIER)
|
239
|
-
.set_parse_action(lambda tks: "(" + " ".join(tks[0]) + ")")
|
240
|
-
.ignore(_COMMENT)
|
241
|
-
.parse_with_tabs()
|
242
|
-
)
|
243
|
-
_KEYWORD_ENTRY = Dict(Group(_keyword_entry_of(KEYWORD, DATA)), asdict=True)
|
280
|
+
_DATA = Forward()
|
281
|
+
_KEYWORD_ENTRY = _keyword_entry_of(_TOKEN | _list_of(_IDENTIFIER), _DATA)
|
282
|
+
_DICT = _dict_of(_TOKEN, _DATA)
|
244
283
|
_DATA_ENTRY = Forward()
|
245
|
-
_LIST_ENTRY = _KEYWORD_ENTRY | _DATA_ENTRY
|
284
|
+
_LIST_ENTRY = _DICT | _KEYWORD_ENTRY | _DATA_ENTRY
|
246
285
|
_LIST = _list_of(_LIST_ENTRY)
|
247
286
|
_NUMBER = common.signed_integer ^ common.ieee_float
|
248
287
|
_DATA_ENTRY <<= _FIELD | _LIST | _DIMENSIONED | _DIMENSIONS | _NUMBER | _SWITCH | _TOKEN
|
249
288
|
|
250
|
-
|
289
|
+
_DATA <<= (
|
251
290
|
_DATA_ENTRY[1, ...]
|
252
|
-
.set_parse_action(lambda tks: tuple(tks) if len(tks) > 1 else [tks[0]])
|
291
|
+
.set_parse_action(lambda tks: [tuple(tks)] if len(tks) > 1 else [tks[0]])
|
253
292
|
.ignore(_COMMENT)
|
254
293
|
.parse_with_tabs()
|
255
294
|
)
|
256
295
|
|
296
|
+
|
297
|
+
def parse_data(s: str) -> Data:
|
298
|
+
return cast(Data, _DATA.parse_string(s, parse_all=True)[0])
|
299
|
+
|
300
|
+
|
301
|
+
_LOCATED_DICTIONARY = Group(
|
302
|
+
_keyword_entry_of(_TOKEN, Opt(_DATA, default=""), located=True)
|
303
|
+
)[...]
|
304
|
+
_LOCATED_DATA = Group(Located(_DATA.copy().add_parse_action(lambda tks: ["", tks[0]])))
|
305
|
+
|
257
306
|
_FILE = (
|
258
|
-
Dict(
|
259
|
-
Group(_keyword_entry_of(KEYWORD, Opt(DATA, default=""), located=True))[...]
|
260
|
-
+ Opt(Group(Located(DATA.copy().add_parse_action(lambda tks: ["", tks[0]]))))
|
261
|
-
+ Group(_keyword_entry_of(KEYWORD, Opt(DATA, default=""), located=True))[...]
|
262
|
-
)
|
307
|
+
Dict(_LOCATED_DICTIONARY + Opt(_LOCATED_DATA) + _LOCATED_DICTIONARY)
|
263
308
|
.ignore(_COMMENT)
|
264
309
|
.ignore(Literal("#include") + ... + LineEnd()) # type: ignore [no-untyped-call]
|
265
310
|
.parse_with_tabs()
|
foamlib/_files/_serialization.py
CHANGED
@@ -1,35 +1,25 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import array
|
4
|
-
import itertools
|
5
3
|
import sys
|
6
4
|
from enum import Enum, auto
|
7
|
-
from typing import
|
5
|
+
from typing import overload
|
8
6
|
|
9
7
|
if sys.version_info >= (3, 9):
|
10
|
-
from collections.abc import Mapping
|
8
|
+
from collections.abc import Mapping
|
11
9
|
else:
|
12
|
-
from typing import Mapping
|
10
|
+
from typing import Mapping
|
13
11
|
|
14
|
-
|
15
|
-
from ._types import Data, Dimensioned, DimensionSet, Entry
|
16
|
-
from ._util import is_sequence
|
12
|
+
import numpy as np
|
17
13
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
numpy = True
|
22
|
-
except ModuleNotFoundError:
|
23
|
-
numpy = False
|
14
|
+
from ._parsing import parse_data
|
15
|
+
from ._types import Data, Dimensioned, DimensionSet, Entry, is_sequence
|
24
16
|
|
25
17
|
|
26
18
|
class Kind(Enum):
|
27
19
|
DEFAULT = auto()
|
28
|
-
KEYWORD = auto()
|
29
20
|
SINGLE_ENTRY = auto()
|
30
21
|
ASCII_FIELD = auto()
|
31
|
-
|
32
|
-
SINGLE_PRECISION_BINARY_FIELD = auto()
|
22
|
+
BINARY_FIELD = auto()
|
33
23
|
DIMENSIONS = auto()
|
34
24
|
|
35
25
|
|
@@ -42,9 +32,29 @@ def normalize(data: Entry, *, kind: Kind = Kind.DEFAULT) -> Entry: ...
|
|
42
32
|
|
43
33
|
|
44
34
|
def normalize(data: Entry, *, kind: Kind = Kind.DEFAULT) -> Entry:
|
45
|
-
if
|
35
|
+
if kind in (Kind.ASCII_FIELD, Kind.BINARY_FIELD):
|
36
|
+
if is_sequence(data):
|
37
|
+
try:
|
38
|
+
arr = np.asarray(data)
|
39
|
+
except ValueError:
|
40
|
+
pass
|
41
|
+
else:
|
42
|
+
if not np.issubdtype(arr.dtype, np.floating):
|
43
|
+
arr = arr.astype(float)
|
44
|
+
|
45
|
+
if arr.ndim == 1 or (arr.ndim == 2 and arr.shape[1] in (3, 6, 9)):
|
46
|
+
return arr
|
47
|
+
|
48
|
+
return data
|
49
|
+
|
50
|
+
if isinstance(data, int):
|
51
|
+
return float(data)
|
52
|
+
|
53
|
+
return data
|
54
|
+
|
55
|
+
if isinstance(data, np.ndarray):
|
46
56
|
ret = data.tolist()
|
47
|
-
assert isinstance(ret, list)
|
57
|
+
assert isinstance(ret, (int, float, list))
|
48
58
|
return ret
|
49
59
|
|
50
60
|
if isinstance(data, Mapping):
|
@@ -56,31 +66,21 @@ def normalize(data: Entry, *, kind: Kind = Kind.DEFAULT) -> Entry:
|
|
56
66
|
and len(data) <= 7
|
57
67
|
and all(isinstance(d, (int, float)) for d in data)
|
58
68
|
):
|
59
|
-
data = cast(Sequence[float], data)
|
60
69
|
return DimensionSet(*data)
|
61
70
|
|
62
|
-
if
|
63
|
-
|
64
|
-
|
71
|
+
if isinstance(data, tuple) and kind == Kind.SINGLE_ENTRY and len(data) == 2:
|
72
|
+
k, v = data
|
73
|
+
return (normalize(k), normalize(v))
|
65
74
|
|
75
|
+
if is_sequence(data) and (kind == Kind.SINGLE_ENTRY or not isinstance(data, tuple)):
|
66
76
|
return [normalize(d, kind=Kind.SINGLE_ENTRY) for d in data]
|
67
77
|
|
68
|
-
if isinstance(data, Dimensioned):
|
69
|
-
value = normalize(data.value, kind=Kind.SINGLE_ENTRY)
|
70
|
-
assert isinstance(value, (int, float, list))
|
71
|
-
return Dimensioned(value, data.dimensions, data.name)
|
72
|
-
|
73
78
|
if isinstance(data, str):
|
74
|
-
|
75
|
-
data = KEYWORD.parse_string(data, parse_all=True)[0]
|
76
|
-
assert isinstance(data, str)
|
77
|
-
return data
|
78
|
-
|
79
|
-
return cast(Data, DATA.parse_string(data, parse_all=True)[0])
|
79
|
+
return parse_data(data)
|
80
80
|
|
81
81
|
if isinstance(
|
82
82
|
data,
|
83
|
-
(int, float, bool, tuple, DimensionSet),
|
83
|
+
(int, float, bool, tuple, DimensionSet, Dimensioned),
|
84
84
|
):
|
85
85
|
return data
|
86
86
|
|
@@ -96,73 +96,51 @@ def dumps(
|
|
96
96
|
data = normalize(data, kind=kind)
|
97
97
|
|
98
98
|
if isinstance(data, Mapping):
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
dumps(k, kind=Kind.KEYWORD) + b" {" + dumps(value) + b"}"
|
105
|
-
)
|
106
|
-
elif not value:
|
107
|
-
entries.append(dumps(k, kind=Kind.KEYWORD) + b";")
|
108
|
-
else:
|
109
|
-
entries.append(dumps(k, kind=Kind.KEYWORD) + b" " + dumps(value) + b";")
|
99
|
+
return (
|
100
|
+
b"{"
|
101
|
+
+ b" ".join(dumps((k, v), kind=Kind.SINGLE_ENTRY) for k, v in data.items())
|
102
|
+
+ b"}"
|
103
|
+
)
|
110
104
|
|
111
|
-
|
105
|
+
if isinstance(data, tuple) and kind == Kind.SINGLE_ENTRY and len(data) == 2:
|
106
|
+
k, v = data
|
107
|
+
ret = dumps(k) + b" " + dumps(v)
|
108
|
+
if not isinstance(v, Mapping):
|
109
|
+
ret += b";"
|
110
|
+
return ret
|
112
111
|
|
113
112
|
if isinstance(data, DimensionSet):
|
114
113
|
return b"[" + b" ".join(dumps(v) for v in data) + b"]"
|
115
114
|
|
116
|
-
if kind in (
|
117
|
-
|
118
|
-
Kind.DOUBLE_PRECISION_BINARY_FIELD,
|
119
|
-
Kind.SINGLE_PRECISION_BINARY_FIELD,
|
120
|
-
) and (
|
121
|
-
isinstance(data, (int, float))
|
122
|
-
or is_sequence(data)
|
123
|
-
and data
|
124
|
-
and isinstance(data[0], (int, float))
|
125
|
-
and len(data) in (3, 6, 9)
|
115
|
+
if kind in (Kind.ASCII_FIELD, Kind.BINARY_FIELD) and (
|
116
|
+
isinstance(data, (int, float, np.ndarray))
|
126
117
|
):
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
if data and isinstance(data[0], (int, float)):
|
118
|
+
shape = np.shape(data)
|
119
|
+
if shape in ((), (3,), (6,), (9,)):
|
120
|
+
return b"uniform " + dumps(data, kind=Kind.SINGLE_ENTRY)
|
121
|
+
|
122
|
+
assert isinstance(data, np.ndarray)
|
123
|
+
ndim = len(shape)
|
124
|
+
if ndim == 1:
|
135
125
|
tensor_kind = b"scalar"
|
136
|
-
|
137
|
-
|
126
|
+
|
127
|
+
elif ndim == 2:
|
128
|
+
if shape[1] == 3:
|
138
129
|
tensor_kind = b"vector"
|
139
|
-
elif
|
130
|
+
elif shape[1] == 6:
|
140
131
|
tensor_kind = b"symmTensor"
|
141
|
-
elif
|
132
|
+
elif shape[1] == 9:
|
142
133
|
tensor_kind = b"tensor"
|
143
134
|
else:
|
144
135
|
return dumps(data)
|
136
|
+
|
145
137
|
else:
|
146
138
|
return dumps(data)
|
147
139
|
|
148
|
-
if kind
|
149
|
-
|
150
|
-
Kind.SINGLE_PRECISION_BINARY_FIELD,
|
151
|
-
):
|
152
|
-
typecode = "f" if kind == Kind.SINGLE_PRECISION_BINARY_FIELD else "d"
|
153
|
-
if tensor_kind == b"scalar":
|
154
|
-
data = cast(Sequence[float], data)
|
155
|
-
contents = b"(" + array.array(typecode, data).tobytes() + b")"
|
156
|
-
else:
|
157
|
-
data = cast(Sequence[Sequence[float]], data)
|
158
|
-
contents = (
|
159
|
-
b"("
|
160
|
-
+ array.array(
|
161
|
-
typecode, itertools.chain.from_iterable(data)
|
162
|
-
).tobytes()
|
163
|
-
+ b")"
|
164
|
-
)
|
140
|
+
if kind == Kind.BINARY_FIELD:
|
141
|
+
contents = b"(" + data.tobytes() + b")"
|
165
142
|
else:
|
143
|
+
assert kind == Kind.ASCII_FIELD
|
166
144
|
contents = dumps(data, kind=Kind.SINGLE_ENTRY)
|
167
145
|
|
168
146
|
return b"nonuniform List<" + tensor_kind + b"> " + dumps(len(data)) + contents
|
@@ -185,7 +163,7 @@ def dumps(
|
|
185
163
|
if isinstance(data, tuple):
|
186
164
|
return b" ".join(dumps(v) for v in data)
|
187
165
|
|
188
|
-
if is_sequence(data):
|
166
|
+
if is_sequence(data) and not isinstance(data, tuple):
|
189
167
|
return b"(" + b" ".join(dumps(v, kind=Kind.SINGLE_ENTRY) for v in data) + b")"
|
190
168
|
|
191
169
|
if data is True:
|
foamlib/_files/_types.py
CHANGED
@@ -2,16 +2,20 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import sys
|
4
4
|
from dataclasses import dataclass
|
5
|
-
from typing import
|
5
|
+
from typing import Dict, NamedTuple, Optional, Tuple, Union
|
6
6
|
|
7
|
-
|
8
|
-
import numpy as np
|
7
|
+
import numpy as np
|
9
8
|
|
10
9
|
if sys.version_info >= (3, 9):
|
11
10
|
from collections.abc import Mapping, MutableMapping, Sequence
|
12
11
|
else:
|
13
12
|
from typing import Mapping, MutableMapping, Sequence
|
14
13
|
|
14
|
+
if sys.version_info >= (3, 10):
|
15
|
+
from typing import TypeGuard
|
16
|
+
else:
|
17
|
+
from typing_extensions import TypeGuard
|
18
|
+
|
15
19
|
|
16
20
|
class DimensionSet(NamedTuple):
|
17
21
|
mass: float = 0
|
@@ -29,8 +33,7 @@ class DimensionSet(NamedTuple):
|
|
29
33
|
Tensor = Union[
|
30
34
|
float,
|
31
35
|
Sequence[float],
|
32
|
-
"np.ndarray[
|
33
|
-
"np.ndarray[Tuple[int], np.dtype[np.generic]]",
|
36
|
+
"np.ndarray[tuple[()] | Tuple[int], np.dtype[np.float64]]",
|
34
37
|
]
|
35
38
|
|
36
39
|
|
@@ -41,15 +44,30 @@ class Dimensioned:
|
|
41
44
|
name: str | None = None
|
42
45
|
|
43
46
|
def __post_init__(self) -> None:
|
47
|
+
if is_sequence(self.value):
|
48
|
+
self.value = np.asarray(self.value, dtype=float)
|
49
|
+
else:
|
50
|
+
assert isinstance(self.value, (int, float, np.ndarray))
|
51
|
+
self.value = float(self.value)
|
52
|
+
|
44
53
|
if not isinstance(self.dimensions, DimensionSet):
|
45
54
|
self.dimensions = DimensionSet(*self.dimensions)
|
46
55
|
|
56
|
+
def __eq__(self, other: object) -> bool:
|
57
|
+
if not isinstance(other, Dimensioned):
|
58
|
+
return NotImplemented
|
59
|
+
|
60
|
+
return (
|
61
|
+
self.dimensions == other.dimensions
|
62
|
+
and np.array_equal(self.value, other.value)
|
63
|
+
and self.name == other.name
|
64
|
+
)
|
65
|
+
|
47
66
|
|
48
67
|
Field = Union[
|
49
68
|
Tensor,
|
50
69
|
Sequence[Tensor],
|
51
|
-
"np.ndarray[
|
52
|
-
"np.ndarray[Tuple[int, int], np.dtype[np.generic]]",
|
70
|
+
"np.ndarray[tuple[int] | tuple[int, int], np.dtype[np.float64 | np.float32]]",
|
53
71
|
]
|
54
72
|
|
55
73
|
Data = Union[
|
@@ -60,7 +78,6 @@ Data = Union[
|
|
60
78
|
Dimensioned,
|
61
79
|
DimensionSet,
|
62
80
|
Sequence["Entry"],
|
63
|
-
Tensor,
|
64
81
|
Field,
|
65
82
|
]
|
66
83
|
|
@@ -72,9 +89,21 @@ Entry = Union[
|
|
72
89
|
A value that can be stored in an OpenFOAM file.
|
73
90
|
"""
|
74
91
|
|
75
|
-
|
92
|
+
|
93
|
+
def is_sequence(
|
94
|
+
value: Entry,
|
95
|
+
) -> TypeGuard[
|
96
|
+
Sequence[Entry]
|
97
|
+
| np.ndarray[tuple[int] | tuple[int, int], np.dtype[np.float64 | np.float32]]
|
98
|
+
]:
|
99
|
+
return (isinstance(value, Sequence) and not isinstance(value, str)) or (
|
100
|
+
isinstance(value, np.ndarray) and value.ndim > 0
|
101
|
+
)
|
102
|
+
|
103
|
+
|
104
|
+
MutableEntry = Union[
|
76
105
|
Data,
|
77
|
-
MutableMapping[str, "
|
106
|
+
MutableMapping[str, "MutableEntry"],
|
78
107
|
]
|
79
108
|
|
80
109
|
Dict_ = Dict[str, Union["Entry", "Dict_"]]
|
@@ -1,15 +1,15 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: foamlib
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.8.1
|
4
4
|
Summary: A Python interface for interacting with OpenFOAM
|
5
|
-
Author-email: "Gabriel S. Gerlero" <ggerlero@cimec.unl.edu.ar>
|
6
5
|
Project-URL: Homepage, https://github.com/gerlero/foamlib
|
7
6
|
Project-URL: Repository, https://github.com/gerlero/foamlib
|
8
7
|
Project-URL: Documentation, https://foamlib.readthedocs.io
|
8
|
+
Author-email: "Gabriel S. Gerlero" <ggerlero@cimec.unl.edu.ar>
|
9
9
|
Classifier: Development Status :: 4 - Beta
|
10
10
|
Classifier: Framework :: AsyncIO
|
11
|
-
Classifier: Intended Audience :: Science/Research
|
12
11
|
Classifier: Intended Audience :: Developers
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
13
13
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
14
14
|
Classifier: Operating System :: POSIX
|
15
15
|
Classifier: Programming Language :: Python :: 3 :: Only
|
@@ -24,34 +24,34 @@ Classifier: Topic :: Scientific/Engineering
|
|
24
24
|
Classifier: Topic :: Software Development
|
25
25
|
Classifier: Typing :: Typed
|
26
26
|
Requires-Python: >=3.7
|
27
|
-
|
28
|
-
|
29
|
-
Requires-Dist:
|
30
|
-
Requires-Dist: pyparsing
|
31
|
-
Requires-Dist: typing-extensions
|
27
|
+
Requires-Dist: aioshutil<2,>=1
|
28
|
+
Requires-Dist: numpy<3,>=1
|
29
|
+
Requires-Dist: numpy<3,>=1.25.0; python_version >= '3.10'
|
30
|
+
Requires-Dist: pyparsing<4,>=3
|
31
|
+
Requires-Dist: typing-extensions<5,>=4; python_version < '3.11'
|
32
32
|
Provides-Extra: dev
|
33
|
-
Requires-Dist:
|
34
|
-
Requires-Dist:
|
35
|
-
Requires-Dist:
|
36
|
-
Requires-Dist:
|
37
|
-
Requires-Dist:
|
33
|
+
Requires-Dist: mypy<2,>=1; extra == 'dev'
|
34
|
+
Requires-Dist: pytest-asyncio<0.25,>=0.21; extra == 'dev'
|
35
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
36
|
+
Requires-Dist: pytest<9,>=7; extra == 'dev'
|
37
|
+
Requires-Dist: ruff; extra == 'dev'
|
38
|
+
Requires-Dist: sphinx-rtd-theme; extra == 'dev'
|
39
|
+
Requires-Dist: sphinx<9,>=5; extra == 'dev'
|
38
40
|
Provides-Extra: docs
|
39
|
-
Requires-Dist:
|
40
|
-
Requires-Dist: sphinx
|
41
|
-
Requires-Dist: sphinx-rtd-theme ; extra == 'docs'
|
41
|
+
Requires-Dist: sphinx-rtd-theme; extra == 'docs'
|
42
|
+
Requires-Dist: sphinx<9,>=5; extra == 'docs'
|
42
43
|
Provides-Extra: lint
|
43
|
-
Requires-Dist: ruff
|
44
|
-
Provides-Extra: numpy
|
45
|
-
Requires-Dist: numpy <3,>=1 ; extra == 'numpy'
|
46
|
-
Requires-Dist: numpy <3,>=1.25.0 ; (python_version >= "3.10") and extra == 'numpy'
|
44
|
+
Requires-Dist: ruff; extra == 'lint'
|
47
45
|
Provides-Extra: test
|
48
|
-
Requires-Dist:
|
49
|
-
Requires-Dist: pytest
|
50
|
-
Requires-Dist: pytest
|
51
|
-
Requires-Dist: pytest-cov ; extra == 'test'
|
46
|
+
Requires-Dist: pytest-asyncio<0.25,>=0.21; extra == 'test'
|
47
|
+
Requires-Dist: pytest-cov; extra == 'test'
|
48
|
+
Requires-Dist: pytest<9,>=7; extra == 'test'
|
52
49
|
Provides-Extra: typing
|
53
|
-
Requires-Dist:
|
54
|
-
Requires-Dist:
|
50
|
+
Requires-Dist: mypy<2,>=1; extra == 'typing'
|
51
|
+
Requires-Dist: pytest-asyncio<0.25,>=0.21; extra == 'typing'
|
52
|
+
Requires-Dist: pytest-cov; extra == 'typing'
|
53
|
+
Requires-Dist: pytest<9,>=7; extra == 'typing'
|
54
|
+
Description-Content-Type: text/markdown
|
55
55
|
|
56
56
|
[<img alt="foamlib" src="https://github.com/gerlero/foamlib/raw/main/logo.png" height="65">](https://github.com/gerlero/foamlib)
|
57
57
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
foamlib/__init__.py,sha256=TATCOFe7Qz20bMXgF1iX2nZmLzME7Wtg3gIocDfQTZk,452
|
2
|
+
foamlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
+
foamlib/_cases/__init__.py,sha256=_A1TTHuQfS9FH2_33lSEyLtOJZGFHZBco1tWJCVOHks,358
|
4
|
+
foamlib/_cases/_async.py,sha256=i6g4EBHqvI-1PkdrxsRto2ynW7sxsOga2bSYk1XVG1U,7795
|
5
|
+
foamlib/_cases/_base.py,sha256=37oBbM3NM-hpG7dKewZvyJNtqSAogMurcbmX-wLIgMU,6727
|
6
|
+
foamlib/_cases/_run.py,sha256=lveqKZium_qK_eTxYE8jOjwx0eiIoolCBbi56-zLw1o,14420
|
7
|
+
foamlib/_cases/_slurm.py,sha256=kj4wqgr3foMyAoUkoHOZODRBmVqH1B9KqAIEEjM8ZBg,2328
|
8
|
+
foamlib/_cases/_subprocess.py,sha256=6BlBRxknj2-BFcGkx7oVcuL63_utSaY1Axmsc1qV9j8,3887
|
9
|
+
foamlib/_cases/_sync.py,sha256=2BJXB7Nzldb4OgPukqupgYqdceUGkI2mYhhtGPWEBrc,5901
|
10
|
+
foamlib/_cases/_util.py,sha256=tK4SM5WT3eEgGsFLnidIySbom1qowBAua9z13gipKJk,1518
|
11
|
+
foamlib/_files/__init__.py,sha256=q1vkjXnjnSZvo45jPAICpWeF2LZv5V6xfzAR6S8fS5A,96
|
12
|
+
foamlib/_files/_files.py,sha256=hVzsAhUFukF7sGLUNp1wFUkzIMpRfrpKCKObLj8MKhA,15070
|
13
|
+
foamlib/_files/_io.py,sha256=BGbbm6HKxL2ka0YMCmHqZQZ1R4PPQlkvWWb4FHMAS8k,2217
|
14
|
+
foamlib/_files/_parsing.py,sha256=iKtreUueJ3NrE8a2cIpUf4zF7z3o4pJtKLufx0mnb3A,13986
|
15
|
+
foamlib/_files/_serialization.py,sha256=Vuq9Ityb55a7kheGCqeuMHyzddb4mXozglMsc90_3Cc,4746
|
16
|
+
foamlib/_files/_types.py,sha256=3l6MCwyK1wAv3B5xJsyF9Q4Ndgt-BF8zCd1N7_ZBxPM,2554
|
17
|
+
foamlib-0.8.1.dist-info/METADATA,sha256=izsNijMcEBsVrrgyWoLzx80Gi6LoJ5PAIM4zNVngxwk,7938
|
18
|
+
foamlib-0.8.1.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
19
|
+
foamlib-0.8.1.dist-info/licenses/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
|
20
|
+
foamlib-0.8.1.dist-info/RECORD,,
|
foamlib/_files/_util.py
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
import sys
|
4
|
-
from typing import TYPE_CHECKING
|
5
|
-
|
6
|
-
if sys.version_info >= (3, 9):
|
7
|
-
from collections.abc import Sequence
|
8
|
-
else:
|
9
|
-
from typing import Sequence
|
10
|
-
|
11
|
-
if sys.version_info >= (3, 10):
|
12
|
-
from typing import TypeGuard
|
13
|
-
else:
|
14
|
-
from typing_extensions import TypeGuard
|
15
|
-
|
16
|
-
if TYPE_CHECKING:
|
17
|
-
from ._types import Entry
|
18
|
-
|
19
|
-
|
20
|
-
def is_sequence(
|
21
|
-
value: Entry,
|
22
|
-
) -> TypeGuard[Sequence[Entry]]:
|
23
|
-
return isinstance(value, Sequence) and not isinstance(value, str)
|
foamlib-0.7.3.dist-info/RECORD
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
foamlib/__init__.py,sha256=GdEjgMru_5M1AG0ltkVKqNek6vw5aI4j_6QNApGRqsg,452
|
2
|
-
foamlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
-
foamlib/_cases/__init__.py,sha256=wTUHcUgU1CBgpu0cUMtksQ5VKG6B8CFu9xc3dWwsQuo,358
|
4
|
-
foamlib/_cases/_async.py,sha256=i6g4EBHqvI-1PkdrxsRto2ynW7sxsOga2bSYk1XVG1U,7795
|
5
|
-
foamlib/_cases/_base.py,sha256=FKfZxP7HspWfSswQ6yZ5bGJRdZUlupQxj2tDqngXPmc,6785
|
6
|
-
foamlib/_cases/_run.py,sha256=lveqKZium_qK_eTxYE8jOjwx0eiIoolCBbi56-zLw1o,14420
|
7
|
-
foamlib/_cases/_slurm.py,sha256=kj4wqgr3foMyAoUkoHOZODRBmVqH1B9KqAIEEjM8ZBg,2328
|
8
|
-
foamlib/_cases/_subprocess.py,sha256=6BlBRxknj2-BFcGkx7oVcuL63_utSaY1Axmsc1qV9j8,3887
|
9
|
-
foamlib/_cases/_sync.py,sha256=2BJXB7Nzldb4OgPukqupgYqdceUGkI2mYhhtGPWEBrc,5901
|
10
|
-
foamlib/_cases/_util.py,sha256=lhVca3ERY0zwYjDam6W2QMROt0yX5vAF-9_DS5RuMbM,1547
|
11
|
-
foamlib/_files/__init__.py,sha256=GDkYkF3F-ADhkCRT3j9dQQHPP5LyJJYb8TaBbZTQ6fo,96
|
12
|
-
foamlib/_files/_files.py,sha256=_qzXSsKRVXNrfySewonJJqL9I4OA8RTZuYyuWTGR4Ys,15829
|
13
|
-
foamlib/_files/_io.py,sha256=IQLqoqnA1TpHf21NbUho2wsYWevyqC6MKo-wfpaObUU,2226
|
14
|
-
foamlib/_files/_parsing.py,sha256=sY_Cyep9R7HfeTOKnKoAh9ZVXTnrJw3HGIgFFwUPGms,12541
|
15
|
-
foamlib/_files/_serialization.py,sha256=GOhWIMHNf5MaLJUjbiRffNGQn1xVGPbyh_Mm50iz5e8,5847
|
16
|
-
foamlib/_files/_types.py,sha256=mOOTXVrrD6MZGH64TmK1KX7WfUVBS8JLOuHTeeDerDQ,1729
|
17
|
-
foamlib/_files/_util.py,sha256=lkoSJHXjd6MvDxx39ZF75mhPq-_QX9AjrruVcQ7I9WI,496
|
18
|
-
foamlib-0.7.3.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
|
19
|
-
foamlib-0.7.3.dist-info/METADATA,sha256=4yvR9-0fYVRRfbROkoO3HcmmtZVYI4QAqIC_NPqKE0A,7957
|
20
|
-
foamlib-0.7.3.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
|
21
|
-
foamlib-0.7.3.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
|
22
|
-
foamlib-0.7.3.dist-info/RECORD,,
|
@@ -1 +0,0 @@
|
|
1
|
-
foamlib
|
File without changes
|