foamlib 0.8.2__tar.gz → 0.8.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {foamlib-0.8.2 → foamlib-0.8.4}/.github/workflows/ci.yml +5 -5
- {foamlib-0.8.2 → foamlib-0.8.4}/.github/workflows/pypi-publish.yml +1 -1
- {foamlib-0.8.2 → foamlib-0.8.4}/PKG-INFO +6 -5
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/__init__.py +1 -1
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/_files/_files.py +3 -3
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/_files/_parsing.py +26 -9
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/_files/_serialization.py +5 -2
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/_files/_types.py +1 -1
- {foamlib-0.8.2 → foamlib-0.8.4}/pyproject.toml +1 -1
- {foamlib-0.8.2 → foamlib-0.8.4}/tests/test_files/test_dumps.py +1 -1
- {foamlib-0.8.2 → foamlib-0.8.4}/tests/test_files/test_files.py +7 -7
- {foamlib-0.8.2 → foamlib-0.8.4}/tests/test_files/test_parsing.py +9 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/.devcontainer.json +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/.dockerignore +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/.git-blame-ignore-revs +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/.github/dependabot.yml +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/.github/workflows/docker.yml +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/.github/workflows/dockerhub-description.yml +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/.gitignore +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/.readthedocs.yaml +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/Dockerfile +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/LICENSE.txt +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/README.md +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/benchmark.png +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/docs/Makefile +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/docs/cases.rst +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/docs/conf.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/docs/files.rst +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/docs/index.rst +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/docs/make.bat +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/docs/ruff.toml +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/_cases/__init__.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/_cases/_async.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/_cases/_base.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/_cases/_run.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/_cases/_slurm.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/_cases/_subprocess.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/_cases/_sync.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/_cases/_util.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/_files/__init__.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/_files/_io.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/foamlib/py.typed +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/logo.png +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/tests/__init__.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/tests/ruff.toml +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/tests/test_cases/__init__.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/tests/test_cases/test_cavity.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/tests/test_cases/test_cavity_async.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/tests/test_cases/test_flange.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/tests/test_cases/test_flange_async.py +0 -0
- {foamlib-0.8.2 → foamlib-0.8.4}/tests/test_files/__init__.py +0 -0
@@ -16,9 +16,9 @@ jobs:
|
|
16
16
|
- name: Checkout
|
17
17
|
uses: actions/checkout@v4
|
18
18
|
- name: Lint with Ruff
|
19
|
-
uses: astral-sh/ruff-action@
|
19
|
+
uses: astral-sh/ruff-action@v3
|
20
20
|
- name: Format with Ruff
|
21
|
-
uses: astral-sh/ruff-action@
|
21
|
+
uses: astral-sh/ruff-action@v3
|
22
22
|
with:
|
23
23
|
args: 'format --check'
|
24
24
|
|
@@ -28,7 +28,7 @@ jobs:
|
|
28
28
|
- name: Checkout
|
29
29
|
uses: actions/checkout@v4
|
30
30
|
- name: Install uv
|
31
|
-
uses: astral-sh/setup-uv@
|
31
|
+
uses: astral-sh/setup-uv@v5
|
32
32
|
- name: Set up Python
|
33
33
|
uses: actions/setup-python@v5
|
34
34
|
with:
|
@@ -74,7 +74,7 @@ jobs:
|
|
74
74
|
with:
|
75
75
|
openfoam-version: ${{ matrix.openfoam-version }}
|
76
76
|
- name: Install uv
|
77
|
-
uses: astral-sh/setup-uv@
|
77
|
+
uses: astral-sh/setup-uv@v5
|
78
78
|
- name: Set up Python ${{ matrix.python-version }}
|
79
79
|
uses: actions/setup-python@v5
|
80
80
|
with:
|
@@ -103,7 +103,7 @@ jobs:
|
|
103
103
|
- name: Checkout
|
104
104
|
uses: actions/checkout@v4
|
105
105
|
- name: Install uv
|
106
|
-
uses: astral-sh/setup-uv@
|
106
|
+
uses: astral-sh/setup-uv@v5
|
107
107
|
- name: Check package build
|
108
108
|
run: |
|
109
109
|
uv build
|
@@ -1,11 +1,12 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: foamlib
|
3
|
-
Version: 0.8.
|
3
|
+
Version: 0.8.4
|
4
4
|
Summary: A Python interface for interacting with OpenFOAM
|
5
5
|
Project-URL: Homepage, https://github.com/gerlero/foamlib
|
6
6
|
Project-URL: Repository, https://github.com/gerlero/foamlib
|
7
7
|
Project-URL: Documentation, https://foamlib.readthedocs.io
|
8
8
|
Author-email: "Gabriel S. Gerlero" <ggerlero@cimec.unl.edu.ar>
|
9
|
+
License-File: LICENSE.txt
|
9
10
|
Classifier: Development Status :: 4 - Beta
|
10
11
|
Classifier: Framework :: AsyncIO
|
11
12
|
Classifier: Intended Audience :: Developers
|
@@ -31,7 +32,7 @@ Requires-Dist: pyparsing<4,>=3.1.2
|
|
31
32
|
Requires-Dist: typing-extensions<5,>=4; python_version < '3.11'
|
32
33
|
Provides-Extra: dev
|
33
34
|
Requires-Dist: mypy<2,>=1; extra == 'dev'
|
34
|
-
Requires-Dist: pytest-asyncio<0.
|
35
|
+
Requires-Dist: pytest-asyncio<0.26,>=0.21; extra == 'dev'
|
35
36
|
Requires-Dist: pytest-cov; extra == 'dev'
|
36
37
|
Requires-Dist: pytest<9,>=7; extra == 'dev'
|
37
38
|
Requires-Dist: ruff; extra == 'dev'
|
@@ -43,12 +44,12 @@ Requires-Dist: sphinx<9,>=5; extra == 'docs'
|
|
43
44
|
Provides-Extra: lint
|
44
45
|
Requires-Dist: ruff; extra == 'lint'
|
45
46
|
Provides-Extra: test
|
46
|
-
Requires-Dist: pytest-asyncio<0.
|
47
|
+
Requires-Dist: pytest-asyncio<0.26,>=0.21; extra == 'test'
|
47
48
|
Requires-Dist: pytest-cov; extra == 'test'
|
48
49
|
Requires-Dist: pytest<9,>=7; extra == 'test'
|
49
50
|
Provides-Extra: typing
|
50
51
|
Requires-Dist: mypy<2,>=1; extra == 'typing'
|
51
|
-
Requires-Dist: pytest-asyncio<0.
|
52
|
+
Requires-Dist: pytest-asyncio<0.26,>=0.21; extra == 'typing'
|
52
53
|
Requires-Dist: pytest-cov; extra == 'typing'
|
53
54
|
Requires-Dist: pytest<9,>=7; extra == 'typing'
|
54
55
|
Description-Content-Type: text/markdown
|
@@ -308,15 +308,15 @@ class FoamFile(
|
|
308
308
|
self[(*keywords, k)] = v
|
309
309
|
|
310
310
|
elif keywords:
|
311
|
+
val = dumps(data, kind=kind)
|
311
312
|
parsed.put(
|
312
313
|
keywords,
|
313
314
|
normalize(data, kind=kind),
|
314
315
|
before
|
315
316
|
+ indentation
|
316
317
|
+ dumps(keywords[-1])
|
317
|
-
+ b" "
|
318
|
-
+
|
319
|
-
+ b";"
|
318
|
+
+ ((b" " + val) if val else b"")
|
319
|
+
+ (b";" if not keywords[-1].startswith("#") else b"")
|
320
320
|
+ after,
|
321
321
|
)
|
322
322
|
|
@@ -89,7 +89,7 @@ def _parse_ascii_field(
|
|
89
89
|
s = re.sub(ignore.re, " ", s)
|
90
90
|
s = s.replace("(", " ").replace(")", " ")
|
91
91
|
|
92
|
-
return np.fromstring(s, sep=" ").reshape(-1, *tensor_kind.shape)
|
92
|
+
return np.fromstring(s, sep=" ").reshape(-1, *tensor_kind.shape) # type: ignore [return-value]
|
93
93
|
|
94
94
|
|
95
95
|
def _unpack_binary_field(
|
@@ -99,7 +99,7 @@ def _unpack_binary_field(
|
|
99
99
|
assert float_size in (4, 8)
|
100
100
|
|
101
101
|
dtype = np.float32 if float_size == 4 else float
|
102
|
-
return np.frombuffer(b, dtype=dtype).reshape(-1, *tensor_kind.shape)
|
102
|
+
return np.frombuffer(b, dtype=dtype).reshape(-1, *tensor_kind.shape) # type: ignore [return-value]
|
103
103
|
|
104
104
|
|
105
105
|
def _tensor_list(
|
@@ -153,12 +153,19 @@ def _tensor_list(
|
|
153
153
|
|
154
154
|
|
155
155
|
def _dict_of(
|
156
|
-
keyword: ParserElement,
|
156
|
+
keyword: ParserElement,
|
157
|
+
data: ParserElement,
|
158
|
+
*,
|
159
|
+
directive: ParserElement | None = None,
|
160
|
+
located: bool = False,
|
157
161
|
) -> ParserElement:
|
158
162
|
dict_ = Forward()
|
159
163
|
|
160
164
|
keyword_entry = keyword + (dict_ | (data + Literal(";").suppress()))
|
161
165
|
|
166
|
+
if directive is not None:
|
167
|
+
keyword_entry |= directive + data + LineEnd().suppress() # type: ignore [no-untyped-call]
|
168
|
+
|
162
169
|
if located:
|
163
170
|
keyword_entry = Located(keyword_entry)
|
164
171
|
|
@@ -175,12 +182,17 @@ def _keyword_entry_of(
|
|
175
182
|
keyword: ParserElement,
|
176
183
|
data: ParserElement,
|
177
184
|
*,
|
185
|
+
directive: ParserElement | None = None,
|
178
186
|
located: bool = False,
|
179
187
|
) -> ParserElement:
|
180
188
|
keyword_entry = keyword + (
|
181
|
-
_dict_of(keyword, data, located=located)
|
189
|
+
_dict_of(keyword, data, directive=directive, located=located)
|
190
|
+
| (data + Literal(";").suppress())
|
182
191
|
)
|
183
192
|
|
193
|
+
if directive is not None:
|
194
|
+
keyword_entry |= directive + data + LineEnd().suppress() # type: ignore [no-untyped-call]
|
195
|
+
|
184
196
|
if located:
|
185
197
|
keyword_entry = Located(keyword_entry)
|
186
198
|
else:
|
@@ -223,9 +235,10 @@ _TENSOR = (
|
|
223
235
|
| _tensor(TensorKind.SYMM_TENSOR)
|
224
236
|
| _tensor(TensorKind.TENSOR)
|
225
237
|
)
|
226
|
-
_IDENTIFIER =
|
238
|
+
_IDENTIFIER = Forward()
|
239
|
+
_IDENTIFIER <<= Combine(
|
227
240
|
Word(_IDENTCHARS, _IDENTBODYCHARS, exclude_chars="()")
|
228
|
-
+ Opt(Literal("(") +
|
241
|
+
+ Opt(Literal("(") + _IDENTIFIER + Literal(")"))
|
229
242
|
)
|
230
243
|
_DIMENSIONED = (Opt(_IDENTIFIER) + _DIMENSIONS + _TENSOR).set_parse_action(
|
231
244
|
lambda tks: Dimensioned(*reversed(tks.as_list()))
|
@@ -239,7 +252,8 @@ _FIELD = (Keyword("uniform", _IDENTBODYCHARS).suppress() + _TENSOR) | (
|
|
239
252
|
| _tensor_list(TensorKind.TENSOR, ignore=_COMMENT)
|
240
253
|
)
|
241
254
|
)
|
242
|
-
|
255
|
+
_DIRECTIVE = Word("#", _IDENTBODYCHARS)
|
256
|
+
_TOKEN = dbl_quoted_string | _IDENTIFIER | _DIRECTIVE
|
243
257
|
_DATA = Forward()
|
244
258
|
_KEYWORD_ENTRY = _keyword_entry_of(_TOKEN | _list_of(_IDENTIFIER), _DATA)
|
245
259
|
_DICT = _dict_of(_TOKEN, _DATA)
|
@@ -258,18 +272,21 @@ _DATA <<= (
|
|
258
272
|
|
259
273
|
|
260
274
|
def parse_data(s: str) -> Data:
|
275
|
+
if not s.strip():
|
276
|
+
return ""
|
261
277
|
return cast(Data, _DATA.parse_string(s, parse_all=True)[0])
|
262
278
|
|
263
279
|
|
264
280
|
_LOCATED_DICTIONARY = Group(
|
265
|
-
_keyword_entry_of(
|
281
|
+
_keyword_entry_of(
|
282
|
+
_TOKEN, Opt(_DATA, default=""), directive=_DIRECTIVE, located=True
|
283
|
+
)
|
266
284
|
)[...]
|
267
285
|
_LOCATED_DATA = Group(Located(_DATA.copy().add_parse_action(lambda tks: ["", tks[0]])))
|
268
286
|
|
269
287
|
_FILE = (
|
270
288
|
Dict(_LOCATED_DICTIONARY + Opt(_LOCATED_DATA) + _LOCATED_DICTIONARY)
|
271
289
|
.ignore(_COMMENT)
|
272
|
-
.ignore(Literal("#include") + ... + LineEnd()) # type: ignore [no-untyped-call]
|
273
290
|
.parse_with_tabs()
|
274
291
|
)
|
275
292
|
|
@@ -50,7 +50,7 @@ def normalize(data: Entry, *, kind: Kind = Kind.DEFAULT) -> Entry:
|
|
50
50
|
arr = arr.astype(float)
|
51
51
|
|
52
52
|
if arr.ndim == 1 or (arr.ndim == 2 and arr.shape[1] in (3, 6, 9)):
|
53
|
-
return arr
|
53
|
+
return arr # type: ignore [return-value]
|
54
54
|
|
55
55
|
return data
|
56
56
|
|
@@ -111,7 +111,10 @@ def dumps(
|
|
111
111
|
|
112
112
|
if isinstance(data, tuple) and kind == Kind.SINGLE_ENTRY and len(data) == 2:
|
113
113
|
k, v = data
|
114
|
-
ret = dumps(k)
|
114
|
+
ret = dumps(k)
|
115
|
+
val = dumps(v)
|
116
|
+
if val:
|
117
|
+
ret += b" " + val
|
115
118
|
if not isinstance(v, Mapping):
|
116
119
|
ret += b";"
|
117
120
|
return ret
|
@@ -79,7 +79,7 @@ class Dimensioned:
|
|
79
79
|
|
80
80
|
def __post_init__(self) -> None:
|
81
81
|
if is_sequence(self.value):
|
82
|
-
self.value = np.asarray(self.value, dtype=float)
|
82
|
+
self.value = np.asarray(self.value, dtype=float) # type: ignore [assignment]
|
83
83
|
else:
|
84
84
|
assert isinstance(self.value, (int, float, np.ndarray))
|
85
85
|
self.value = float(self.value)
|
@@ -37,7 +37,7 @@ def test_serialize_data() -> None:
|
|
37
37
|
== b"nonuniform List<vector> 2(\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x08@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@)"
|
38
38
|
)
|
39
39
|
assert (
|
40
|
-
dumps(np.array([1, 2], dtype=np.float32), kind=Kind.BINARY_FIELD)
|
40
|
+
dumps(np.array([1, 2], dtype=np.float32), kind=Kind.BINARY_FIELD) # type: ignore [arg-type]
|
41
41
|
== b"nonuniform List<scalar> 2(\x00\x00\x80?\x00\x00\x00@)"
|
42
42
|
)
|
43
43
|
assert (
|
@@ -163,19 +163,19 @@ def test_internal_field(cavity: FoamCase) -> None:
|
|
163
163
|
p_arr = np.zeros(size)
|
164
164
|
U_arr = np.zeros((size, 3))
|
165
165
|
|
166
|
-
cavity[0]["p"].internal_field = p_arr
|
167
|
-
cavity[0]["U"].internal_field = U_arr
|
166
|
+
cavity[0]["p"].internal_field = p_arr # type: ignore [assignment]
|
167
|
+
cavity[0]["U"].internal_field = U_arr # type: ignore [assignment]
|
168
168
|
|
169
169
|
assert cavity[0]["p"].internal_field == pytest.approx(p_arr)
|
170
170
|
U = cavity[0]["U"].internal_field
|
171
171
|
assert isinstance(U, np.ndarray)
|
172
172
|
assert U_arr == pytest.approx(U)
|
173
173
|
|
174
|
-
p_arr = np.arange(size) * 1e-6
|
174
|
+
p_arr = np.arange(size) * 1e-6 # type: ignore [assignment]
|
175
175
|
U_arr = np.full((size, 3), [-1e-6, 1e-6, 0]) * np.arange(size)[:, np.newaxis]
|
176
176
|
|
177
|
-
cavity[0]["p"].internal_field = p_arr
|
178
|
-
cavity[0]["U"].internal_field = U_arr
|
177
|
+
cavity[0]["p"].internal_field = p_arr # type: ignore [assignment]
|
178
|
+
cavity[0]["U"].internal_field = U_arr # type: ignore [assignment]
|
179
179
|
|
180
180
|
assert cavity[0]["p"].internal_field == pytest.approx(p_arr)
|
181
181
|
U = cavity[0]["U"].internal_field
|
@@ -210,7 +210,7 @@ def test_binary_field(cavity: FoamCase) -> None:
|
|
210
210
|
p_arr = np.arange(len(p_bin)) * 1e-6
|
211
211
|
U_arr = np.full_like(U_bin, [-1e-6, 1e-6, 0]) * np.arange(len(U_bin))[:, np.newaxis]
|
212
212
|
|
213
|
-
cavity[0]["p"].internal_field = p_arr
|
213
|
+
cavity[0]["p"].internal_field = p_arr # type: ignore [assignment]
|
214
214
|
cavity[0]["U"].internal_field = U_arr
|
215
215
|
|
216
216
|
assert cavity[0]["p"].internal_field == pytest.approx(p_arr)
|
@@ -237,7 +237,7 @@ def test_compressed_field(cavity: FoamCase) -> None:
|
|
237
237
|
p_arr = np.arange(len(p_bin)) * 1e-6
|
238
238
|
U_arr = np.full_like(U_bin, [-1e-6, 1e-6, 0]) * np.arange(len(U_bin))[:, np.newaxis]
|
239
239
|
|
240
|
-
cavity[0]["p"].internal_field = p_arr
|
240
|
+
cavity[0]["p"].internal_field = p_arr # type: ignore [assignment]
|
241
241
|
cavity[0]["U"].internal_field = U_arr
|
242
242
|
|
243
243
|
assert cavity[0]["p"].internal_field == pytest.approx(p_arr)
|
@@ -92,8 +92,17 @@ def test_parse_value() -> None:
|
|
92
92
|
assert Parsed(b"({a b; c d;} {e g;})")[()] == [{"a": "b", "c": "d"}, {"e": "g"}]
|
93
93
|
assert Parsed(b"(water oil mercury air)")[()] == ["water", "oil", "mercury", "air"]
|
94
94
|
assert Parsed(b"div(phi,U)")[()] == "div(phi,U)"
|
95
|
+
assert Parsed(b"div(nuEff*dev(T(grad(U))))")[()] == "div(nuEff*dev(T(grad(U))))"
|
95
96
|
assert Parsed(b"((air and water) { type constant; sigma 0.07; })")[()] == [
|
96
97
|
(["air", "and", "water"], {"type": "constant", "sigma": 0.07})
|
97
98
|
]
|
98
99
|
assert Parsed(b"[]")[()] == FoamFile.DimensionSet()
|
99
100
|
assert Parsed(b"object f.1;")[("object",)] == "f.1"
|
101
|
+
|
102
|
+
|
103
|
+
def test_parse_directive() -> None:
|
104
|
+
assert Parsed(b'#include "filename"')[("#include",)] == '"filename"'
|
105
|
+
assert (
|
106
|
+
Parsed(b"functions\n{\n#includeFunc funcName\n}")[("functions", "#includeFunc")]
|
107
|
+
== "funcName"
|
108
|
+
)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|