foamlib 0.7.3__py3-none-any.whl → 0.8.0__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 +3 -3
- foamlib/_files/_io.py +1 -3
- foamlib/_files/_parsing.py +137 -84
- foamlib/_files/_serialization.py +24 -22
- foamlib/_files/_types.py +5 -7
- {foamlib-0.7.3.dist-info → foamlib-0.8.0.dist-info}/METADATA +35 -26
- foamlib-0.8.0.dist-info/RECORD +21 -0
- {foamlib-0.7.3.dist-info → foamlib-0.8.0.dist-info}/WHEEL +1 -2
- 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.0.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.0"
|
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
@@ -25,7 +25,7 @@ from ._types import (
|
|
25
25
|
Entry,
|
26
26
|
Field,
|
27
27
|
File,
|
28
|
-
|
28
|
+
MutableEntry,
|
29
29
|
)
|
30
30
|
from ._util import is_sequence
|
31
31
|
|
@@ -33,7 +33,7 @@ from ._util import is_sequence
|
|
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
|
|
foamlib/_files/_io.py
CHANGED
foamlib/_files/_parsing.py
CHANGED
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
3
3
|
import array
|
4
4
|
import re
|
5
5
|
import sys
|
6
|
+
from enum import Enum, auto
|
6
7
|
from typing import Tuple, Union, cast
|
7
8
|
|
8
9
|
if sys.version_info >= (3, 9):
|
@@ -13,7 +14,7 @@ else:
|
|
13
14
|
if sys.version_info >= (3, 10):
|
14
15
|
from types import EllipsisType
|
15
16
|
else:
|
16
|
-
|
17
|
+
EllipsisType = type(...)
|
17
18
|
|
18
19
|
from pyparsing import (
|
19
20
|
Combine,
|
@@ -39,6 +40,61 @@ 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[int, ...]:
|
51
|
+
return {
|
52
|
+
Tensor.SCALAR: (),
|
53
|
+
Tensor.VECTOR: (3,),
|
54
|
+
Tensor.SYMM_TENSOR: (6,),
|
55
|
+
Tensor.TENSOR: (9,),
|
56
|
+
}[self]
|
57
|
+
|
58
|
+
@property
|
59
|
+
def size(self) -> int:
|
60
|
+
return {
|
61
|
+
Tensor.SCALAR: 1,
|
62
|
+
Tensor.VECTOR: 3,
|
63
|
+
Tensor.SYMM_TENSOR: 6,
|
64
|
+
Tensor.TENSOR: 9,
|
65
|
+
}[self]
|
66
|
+
|
67
|
+
def pattern(self, *, ignore: Regex | None = None) -> str:
|
68
|
+
float_pattern = r"(?i:[+-]?(?:(?:\d+\.?\d*(?:e[+-]?\d+)?)|nan|inf(?:inity)?))"
|
69
|
+
|
70
|
+
if self == Tensor.SCALAR:
|
71
|
+
return float_pattern
|
72
|
+
|
73
|
+
ignore_pattern = (
|
74
|
+
rf"(?:\s|{ignore.re.pattern})+" if ignore is not None else r"\s+"
|
75
|
+
)
|
76
|
+
|
77
|
+
return rf"\((?:{ignore_pattern})?(?:{float_pattern}{ignore_pattern}){{{self.size - 1}}}{float_pattern}(?:{ignore_pattern})?\)"
|
78
|
+
|
79
|
+
def parser(self) -> ParserElement:
|
80
|
+
if self == Tensor.SCALAR:
|
81
|
+
return common.ieee_float
|
82
|
+
|
83
|
+
return (
|
84
|
+
Literal("(").suppress()
|
85
|
+
+ Group(common.ieee_float[self.size], aslist=True)
|
86
|
+
+ Literal(")").suppress()
|
87
|
+
)
|
88
|
+
|
89
|
+
def __str__(self) -> str:
|
90
|
+
return {
|
91
|
+
Tensor.SCALAR: "scalar",
|
92
|
+
Tensor.VECTOR: "vector",
|
93
|
+
Tensor.SYMM_TENSOR: "symmTensor",
|
94
|
+
Tensor.TENSOR: "tensor",
|
95
|
+
}[self]
|
96
|
+
|
97
|
+
|
42
98
|
def _list_of(entry: ParserElement) -> ParserElement:
|
43
99
|
return Opt(
|
44
100
|
Literal("List") + Literal("<") + _IDENTIFIER + Literal(">")
|
@@ -59,7 +115,7 @@ def _list_of(entry: ParserElement) -> ParserElement:
|
|
59
115
|
|
60
116
|
|
61
117
|
def _parse_ascii_field(
|
62
|
-
s: str,
|
118
|
+
s: str, tensor_kind: Tensor, *, ignore: Regex | None
|
63
119
|
) -> list[float] | list[list[float]]:
|
64
120
|
values = [
|
65
121
|
float(v)
|
@@ -69,46 +125,55 @@ def _parse_ascii_field(
|
|
69
125
|
.split()
|
70
126
|
]
|
71
127
|
|
72
|
-
if
|
128
|
+
if tensor_kind == Tensor.SCALAR:
|
73
129
|
return values
|
74
130
|
|
75
|
-
return [
|
131
|
+
return [
|
132
|
+
values[i : i + tensor_kind.size]
|
133
|
+
for i in range(0, len(values), tensor_kind.size)
|
134
|
+
]
|
76
135
|
|
77
136
|
|
78
137
|
def _unpack_binary_field(
|
79
|
-
b: bytes,
|
138
|
+
b: bytes, tensor_kind: Tensor, *, length: int
|
80
139
|
) -> list[float] | list[list[float]]:
|
81
|
-
float_size = len(b) /
|
140
|
+
float_size = len(b) / tensor_kind.size / length
|
82
141
|
assert float_size in (4, 8)
|
83
142
|
|
84
143
|
arr = array.array("f" if float_size == 4 else "d", b)
|
85
144
|
values = arr.tolist()
|
86
145
|
|
87
|
-
if
|
146
|
+
if tensor_kind == Tensor.SCALAR:
|
88
147
|
return values
|
89
148
|
|
90
|
-
return [
|
149
|
+
return [
|
150
|
+
values[i : i + tensor_kind.size]
|
151
|
+
for i in range(0, len(values), tensor_kind.size)
|
152
|
+
]
|
91
153
|
|
92
154
|
|
93
|
-
def
|
94
|
-
|
155
|
+
def _tensor_list(
|
156
|
+
tensor_kind: Tensor | None = None, *, ignore: Regex | None = None
|
95
157
|
) -> 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()
|
158
|
+
if tensor_kind is None:
|
159
|
+
return (
|
160
|
+
_tensor_list(Tensor.SCALAR, ignore=ignore)
|
161
|
+
| _tensor_list(Tensor.VECTOR, ignore=ignore)
|
162
|
+
| _tensor_list(Tensor.SYMM_TENSOR, ignore=ignore)
|
163
|
+
| _tensor_list(Tensor.TENSOR, ignore=ignore)
|
108
164
|
)
|
109
165
|
|
166
|
+
tensor_pattern = tensor_kind.pattern(ignore=ignore)
|
167
|
+
ignore_pattern = rf"(?:\s|{ignore.re.pattern})+" if ignore is not None else r"\s+"
|
168
|
+
|
110
169
|
list_ = Forward()
|
111
170
|
|
171
|
+
list_ <<= Regex(
|
172
|
+
rf"\((?:{ignore_pattern})?(?:{tensor_pattern}{ignore_pattern})*{tensor_pattern}(?:{ignore_pattern})?\)"
|
173
|
+
).add_parse_action(
|
174
|
+
lambda tks: [_parse_ascii_field(tks[0], tensor_kind, ignore=ignore)]
|
175
|
+
)
|
176
|
+
|
112
177
|
def count_parse_action(tks: ParseResults) -> None:
|
113
178
|
nonlocal list_
|
114
179
|
length = tks[0]
|
@@ -118,44 +183,64 @@ def _counted_tensor_list(
|
|
118
183
|
Regex(
|
119
184
|
rf"\((?:{ignore_pattern})?(?:{tensor_pattern}{ignore_pattern}){{{length - 1}}}{tensor_pattern}(?:{ignore_pattern})?\)"
|
120
185
|
).add_parse_action(
|
121
|
-
lambda tks: [_parse_ascii_field(tks[0],
|
186
|
+
lambda tks: [_parse_ascii_field(tks[0], tensor_kind, ignore=ignore)]
|
122
187
|
)
|
123
188
|
| Regex(
|
124
|
-
rf"\((?s:.{{{length *
|
189
|
+
rf"\((?s:.{{{length * tensor_kind.size * 8}}}|.{{{length * tensor_kind.size * 4}}})\)"
|
125
190
|
).set_parse_action(
|
126
191
|
lambda tks: [
|
127
192
|
_unpack_binary_field(
|
128
|
-
tks[0][1:-1].encode("latin-1"),
|
193
|
+
tks[0][1:-1].encode("latin-1"), tensor_kind, length=length
|
129
194
|
)
|
130
195
|
]
|
131
196
|
)
|
132
197
|
| (
|
133
|
-
Literal("{").suppress() +
|
198
|
+
Literal("{").suppress() + tensor_kind.parser() + Literal("}").suppress()
|
134
199
|
).set_parse_action(lambda tks: [[tks[0]] * length])
|
135
200
|
)
|
136
201
|
|
137
202
|
count = common.integer.copy().add_parse_action(count_parse_action)
|
138
203
|
|
139
|
-
return
|
204
|
+
return (
|
205
|
+
Opt(Literal("List") + Literal("<") + str(tensor_kind) + Literal(">")).suppress()
|
206
|
+
+ Opt(count).suppress()
|
207
|
+
+ list_
|
208
|
+
)
|
209
|
+
|
210
|
+
|
211
|
+
def _dict_of(
|
212
|
+
keyword: ParserElement, data: ParserElement, *, located: bool = False
|
213
|
+
) -> ParserElement:
|
214
|
+
dict_ = Forward()
|
215
|
+
|
216
|
+
keyword_entry = keyword + (dict_ | (data + Literal(";").suppress()))
|
217
|
+
|
218
|
+
if located:
|
219
|
+
keyword_entry = Located(keyword_entry)
|
220
|
+
|
221
|
+
dict_ <<= (
|
222
|
+
Literal("{").suppress()
|
223
|
+
+ Dict(Group(keyword_entry)[...], asdict=not located)
|
224
|
+
+ Literal("}").suppress()
|
225
|
+
)
|
226
|
+
|
227
|
+
return dict_
|
140
228
|
|
141
229
|
|
142
230
|
def _keyword_entry_of(
|
143
231
|
keyword: ParserElement,
|
144
|
-
|
232
|
+
data: ParserElement,
|
145
233
|
*,
|
146
234
|
located: bool = False,
|
147
235
|
) -> ParserElement:
|
148
|
-
subdict = Forward()
|
149
|
-
|
150
236
|
keyword_entry = keyword + (
|
151
|
-
(
|
152
|
-
| (data_entries + Literal(";").suppress())
|
237
|
+
_dict_of(keyword, data, located=located) | (data + Literal(";").suppress())
|
153
238
|
)
|
154
239
|
|
155
240
|
if located:
|
156
241
|
keyword_entry = Located(keyword_entry)
|
157
|
-
|
158
|
-
|
242
|
+
else:
|
243
|
+
keyword_entry = keyword_entry.copy().set_parse_action(lambda tks: tuple(tks))
|
159
244
|
|
160
245
|
return keyword_entry
|
161
246
|
|
@@ -188,12 +273,11 @@ _SWITCH = (
|
|
188
273
|
_DIMENSIONS = (
|
189
274
|
Literal("[").suppress() + common.number[0, 7] + Literal("]").suppress()
|
190
275
|
).set_parse_action(lambda tks: DimensionSet(*tks))
|
191
|
-
_TENSOR =
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
)
|
196
|
-
+ Literal(")").suppress()
|
276
|
+
_TENSOR = (
|
277
|
+
Tensor.SCALAR.parser()
|
278
|
+
| Tensor.VECTOR.parser()
|
279
|
+
| Tensor.SYMM_TENSOR.parser()
|
280
|
+
| Tensor.TENSOR.parser()
|
197
281
|
)
|
198
282
|
_IDENTIFIER = Combine(
|
199
283
|
Word(_IDENTCHARS, _IDENTBODYCHARS, exclude_chars="()")
|
@@ -203,63 +287,32 @@ _DIMENSIONED = (Opt(_IDENTIFIER) + _DIMENSIONS + _TENSOR).set_parse_action(
|
|
203
287
|
lambda tks: Dimensioned(*reversed(tks.as_list()))
|
204
288
|
)
|
205
289
|
_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
|
-
)
|
290
|
+
Keyword("nonuniform", _IDENTBODYCHARS).suppress() + _tensor_list(ignore=_COMMENT)
|
233
291
|
)
|
234
|
-
|
292
|
+
TOKEN = dbl_quoted_string | _IDENTIFIER
|
235
293
|
DATA = Forward()
|
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)
|
294
|
+
_KEYWORD_ENTRY = _keyword_entry_of(TOKEN | _list_of(_IDENTIFIER), DATA)
|
295
|
+
_DICT = _dict_of(TOKEN, DATA)
|
244
296
|
_DATA_ENTRY = Forward()
|
245
|
-
_LIST_ENTRY = _KEYWORD_ENTRY | _DATA_ENTRY
|
297
|
+
_LIST_ENTRY = _DICT | _KEYWORD_ENTRY | _DATA_ENTRY
|
246
298
|
_LIST = _list_of(_LIST_ENTRY)
|
247
299
|
_NUMBER = common.signed_integer ^ common.ieee_float
|
248
|
-
_DATA_ENTRY <<= _FIELD | _LIST | _DIMENSIONED | _DIMENSIONS | _NUMBER | _SWITCH |
|
300
|
+
_DATA_ENTRY <<= _FIELD | _LIST | _DIMENSIONED | _DIMENSIONS | _NUMBER | _SWITCH | TOKEN
|
249
301
|
|
250
302
|
DATA <<= (
|
251
303
|
_DATA_ENTRY[1, ...]
|
252
|
-
.set_parse_action(lambda tks: tuple(tks) if len(tks) > 1 else [tks[0]])
|
304
|
+
.set_parse_action(lambda tks: [tuple(tks)] if len(tks) > 1 else [tks[0]])
|
253
305
|
.ignore(_COMMENT)
|
254
306
|
.parse_with_tabs()
|
255
307
|
)
|
256
308
|
|
309
|
+
_LOCATED_DICTIONARY = Group(
|
310
|
+
_keyword_entry_of(TOKEN, Opt(DATA, default=""), located=True)
|
311
|
+
)[...]
|
312
|
+
_LOCATED_DATA = Group(Located(DATA.copy().add_parse_action(lambda tks: ["", tks[0]])))
|
313
|
+
|
257
314
|
_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
|
-
)
|
315
|
+
Dict(_LOCATED_DICTIONARY + Opt(_LOCATED_DATA) + _LOCATED_DICTIONARY)
|
263
316
|
.ignore(_COMMENT)
|
264
317
|
.ignore(Literal("#include") + ... + LineEnd()) # type: ignore [no-untyped-call]
|
265
318
|
.parse_with_tabs()
|
foamlib/_files/_serialization.py
CHANGED
@@ -11,7 +11,7 @@ if sys.version_info >= (3, 9):
|
|
11
11
|
else:
|
12
12
|
from typing import Mapping, Sequence
|
13
13
|
|
14
|
-
from ._parsing import DATA,
|
14
|
+
from ._parsing import DATA, TOKEN
|
15
15
|
from ._types import Data, Dimensioned, DimensionSet, Entry
|
16
16
|
from ._util import is_sequence
|
17
17
|
|
@@ -59,10 +59,11 @@ def normalize(data: Entry, *, kind: Kind = Kind.DEFAULT) -> Entry:
|
|
59
59
|
data = cast(Sequence[float], data)
|
60
60
|
return DimensionSet(*data)
|
61
61
|
|
62
|
-
if
|
63
|
-
|
64
|
-
|
62
|
+
if isinstance(data, tuple) and kind == Kind.SINGLE_ENTRY and len(data) == 2:
|
63
|
+
k, v = data
|
64
|
+
return (normalize(k, kind=Kind.KEYWORD), normalize(v))
|
65
65
|
|
66
|
+
if is_sequence(data) and (kind == Kind.SINGLE_ENTRY or not isinstance(data, tuple)):
|
66
67
|
return [normalize(d, kind=Kind.SINGLE_ENTRY) for d in data]
|
67
68
|
|
68
69
|
if isinstance(data, Dimensioned):
|
@@ -72,7 +73,7 @@ def normalize(data: Entry, *, kind: Kind = Kind.DEFAULT) -> Entry:
|
|
72
73
|
|
73
74
|
if isinstance(data, str):
|
74
75
|
if kind == Kind.KEYWORD:
|
75
|
-
data =
|
76
|
+
data = TOKEN.parse_string(data, parse_all=True)[0]
|
76
77
|
assert isinstance(data, str)
|
77
78
|
return data
|
78
79
|
|
@@ -96,19 +97,18 @@ def dumps(
|
|
96
97
|
data = normalize(data, kind=kind)
|
97
98
|
|
98
99
|
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";")
|
100
|
+
return (
|
101
|
+
b"{"
|
102
|
+
+ b" ".join(dumps((k, v), kind=Kind.SINGLE_ENTRY) for k, v in data.items())
|
103
|
+
+ b"}"
|
104
|
+
)
|
110
105
|
|
111
|
-
|
106
|
+
if isinstance(data, tuple) and kind == Kind.SINGLE_ENTRY and len(data) == 2:
|
107
|
+
k, v = data
|
108
|
+
ret = dumps(k, kind=Kind.KEYWORD) + b" " + dumps(v)
|
109
|
+
if not isinstance(v, Mapping):
|
110
|
+
ret += b";"
|
111
|
+
return ret
|
112
112
|
|
113
113
|
if isinstance(data, DimensionSet):
|
114
114
|
return b"[" + b" ".join(dumps(v) for v in data) + b"]"
|
@@ -119,10 +119,12 @@ def dumps(
|
|
119
119
|
Kind.SINGLE_PRECISION_BINARY_FIELD,
|
120
120
|
) and (
|
121
121
|
isinstance(data, (int, float))
|
122
|
-
or
|
123
|
-
|
124
|
-
|
125
|
-
|
122
|
+
or (
|
123
|
+
is_sequence(data)
|
124
|
+
and data
|
125
|
+
and isinstance(data[0], (int, float))
|
126
|
+
and len(data) in (3, 6, 9)
|
127
|
+
)
|
126
128
|
):
|
127
129
|
return b"uniform " + dumps(data, kind=Kind.SINGLE_ENTRY)
|
128
130
|
|
@@ -185,7 +187,7 @@ def dumps(
|
|
185
187
|
if isinstance(data, tuple):
|
186
188
|
return b" ".join(dumps(v) for v in data)
|
187
189
|
|
188
|
-
if is_sequence(data):
|
190
|
+
if is_sequence(data) and not isinstance(data, tuple):
|
189
191
|
return b"(" + b" ".join(dumps(v, kind=Kind.SINGLE_ENTRY) for v in data) + b")"
|
190
192
|
|
191
193
|
if data is True:
|
foamlib/_files/_types.py
CHANGED
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import sys
|
4
4
|
from dataclasses import dataclass
|
5
|
-
from typing import TYPE_CHECKING, Dict, NamedTuple, Optional,
|
5
|
+
from typing import TYPE_CHECKING, Dict, NamedTuple, Optional, Union
|
6
6
|
|
7
7
|
if TYPE_CHECKING:
|
8
8
|
import numpy as np
|
@@ -29,8 +29,7 @@ class DimensionSet(NamedTuple):
|
|
29
29
|
Tensor = Union[
|
30
30
|
float,
|
31
31
|
Sequence[float],
|
32
|
-
"np.ndarray[
|
33
|
-
"np.ndarray[Tuple[int], np.dtype[np.generic]]",
|
32
|
+
"np.ndarray[tuple[()] | tuple[int], np.dtype[np.float64 | np.int_]]",
|
34
33
|
]
|
35
34
|
|
36
35
|
|
@@ -48,8 +47,7 @@ class Dimensioned:
|
|
48
47
|
Field = Union[
|
49
48
|
Tensor,
|
50
49
|
Sequence[Tensor],
|
51
|
-
"np.ndarray[
|
52
|
-
"np.ndarray[Tuple[int, int], np.dtype[np.generic]]",
|
50
|
+
"np.ndarray[tuple[int] | tuple[int, int], np.dtype[np.float64 | np.int_]]",
|
53
51
|
]
|
54
52
|
|
55
53
|
Data = Union[
|
@@ -72,9 +70,9 @@ Entry = Union[
|
|
72
70
|
A value that can be stored in an OpenFOAM file.
|
73
71
|
"""
|
74
72
|
|
75
|
-
|
73
|
+
MutableEntry = Union[
|
76
74
|
Data,
|
77
|
-
MutableMapping[str, "
|
75
|
+
MutableMapping[str, "MutableEntry"],
|
78
76
|
]
|
79
77
|
|
80
78
|
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.0
|
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,43 @@ 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 <4,>=3
|
31
|
-
Requires-Dist: typing-extensions <5,>=4 ; python_version < "3.11"
|
27
|
+
Requires-Dist: aioshutil<2,>=1
|
28
|
+
Requires-Dist: pyparsing<4,>=3
|
29
|
+
Requires-Dist: typing-extensions<5,>=4; python_version < '3.11'
|
32
30
|
Provides-Extra: dev
|
33
|
-
Requires-Dist:
|
34
|
-
Requires-Dist:
|
35
|
-
Requires-Dist:
|
36
|
-
Requires-Dist:
|
37
|
-
Requires-Dist:
|
31
|
+
Requires-Dist: mypy<2,>=1; extra == 'dev'
|
32
|
+
Requires-Dist: numpy<3,>=1; extra == 'dev'
|
33
|
+
Requires-Dist: numpy<3,>=1.25.0; (python_version >= '3.10') and 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:
|
41
|
-
Requires-Dist: sphinx-rtd-theme
|
41
|
+
Requires-Dist: numpy<3,>=1; extra == 'docs'
|
42
|
+
Requires-Dist: numpy<3,>=1.25.0; (python_version >= '3.10') and extra == 'docs'
|
43
|
+
Requires-Dist: sphinx-rtd-theme; extra == 'docs'
|
44
|
+
Requires-Dist: sphinx<9,>=5; extra == 'docs'
|
42
45
|
Provides-Extra: lint
|
43
|
-
Requires-Dist: ruff
|
46
|
+
Requires-Dist: ruff; extra == 'lint'
|
44
47
|
Provides-Extra: numpy
|
45
|
-
Requires-Dist: numpy
|
46
|
-
Requires-Dist: numpy
|
48
|
+
Requires-Dist: numpy<3,>=1; extra == 'numpy'
|
49
|
+
Requires-Dist: numpy<3,>=1.25.0; (python_version >= '3.10') and extra == 'numpy'
|
47
50
|
Provides-Extra: test
|
48
|
-
Requires-Dist:
|
49
|
-
Requires-Dist:
|
50
|
-
Requires-Dist: pytest-asyncio
|
51
|
-
Requires-Dist: pytest-cov
|
51
|
+
Requires-Dist: numpy<3,>=1; extra == 'test'
|
52
|
+
Requires-Dist: numpy<3,>=1.25.0; (python_version >= '3.10') and extra == 'test'
|
53
|
+
Requires-Dist: pytest-asyncio<0.25,>=0.21; extra == 'test'
|
54
|
+
Requires-Dist: pytest-cov; extra == 'test'
|
55
|
+
Requires-Dist: pytest<9,>=7; extra == 'test'
|
52
56
|
Provides-Extra: typing
|
53
|
-
Requires-Dist:
|
54
|
-
Requires-Dist:
|
57
|
+
Requires-Dist: mypy<2,>=1; extra == 'typing'
|
58
|
+
Requires-Dist: numpy<3,>=1; extra == 'typing'
|
59
|
+
Requires-Dist: numpy<3,>=1.25.0; (python_version >= '3.10') and extra == 'typing'
|
60
|
+
Requires-Dist: pytest-asyncio<0.25,>=0.21; extra == 'typing'
|
61
|
+
Requires-Dist: pytest-cov; extra == 'typing'
|
62
|
+
Requires-Dist: pytest<9,>=7; extra == 'typing'
|
63
|
+
Description-Content-Type: text/markdown
|
55
64
|
|
56
65
|
[<img alt="foamlib" src="https://github.com/gerlero/foamlib/raw/main/logo.png" height="65">](https://github.com/gerlero/foamlib)
|
57
66
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
foamlib/__init__.py,sha256=iN_p0PYnIJNOiwBl-JcsqwLyxvZMD2qW6X7alo-YOO4,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=Afkv9X8Om-AxIe9Ojqbz203_69okdlMNIlSeEAMnkzY,15832
|
13
|
+
foamlib/_files/_io.py,sha256=BGbbm6HKxL2ka0YMCmHqZQZ1R4PPQlkvWWb4FHMAS8k,2217
|
14
|
+
foamlib/_files/_parsing.py,sha256=Go-gwu5HAZF__iF29l_EiPWouBIhjeQG8e6P9vM2cXY,13833
|
15
|
+
foamlib/_files/_serialization.py,sha256=gc0ybQFKU68Ytdv1Uwa1kA8GgunI69XnIch259K4ing,5826
|
16
|
+
foamlib/_files/_types.py,sha256=jvXegp5vKLMJpN8I3jTpAhnT2WQ5FJ5WVBcqw5pRjdQ,1666
|
17
|
+
foamlib/_files/_util.py,sha256=lkoSJHXjd6MvDxx39ZF75mhPq-_QX9AjrruVcQ7I9WI,496
|
18
|
+
foamlib-0.8.0.dist-info/METADATA,sha256=RZN9GJjprIVwmk39qVXBNJq3yr9Sy9LhuVjHAIPcHfc,8499
|
19
|
+
foamlib-0.8.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
20
|
+
foamlib-0.8.0.dist-info/licenses/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
|
21
|
+
foamlib-0.8.0.dist-info/RECORD,,
|
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
|