foamlib 0.6.5__py3-none-any.whl → 0.6.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  """A Python interface for interacting with OpenFOAM."""
2
2
 
3
- __version__ = "0.6.5"
3
+ __version__ = "0.6.7"
4
4
 
5
5
  from ._cases import (
6
6
  AsyncFoamCase,
foamlib/_cases/_async.py CHANGED
@@ -101,7 +101,7 @@ class AsyncFoamCase(FoamCaseRunBase):
101
101
  async def _rmtree(
102
102
  path: Union["os.PathLike[str]", str], ignore_errors: bool = False
103
103
  ) -> None:
104
- await aioshutil.rmtree(path, ignore_errors=ignore_errors) # type: ignore [call-arg]
104
+ await aioshutil.rmtree(path, ignore_errors=ignore_errors)
105
105
 
106
106
  @staticmethod
107
107
  async def _copytree(
@@ -188,7 +188,7 @@ class AsyncFoamCase(FoamCaseRunBase):
188
188
  @asynccontextmanager
189
189
  async def copy(
190
190
  self, dst: Optional[Union["os.PathLike[str]", str]] = None
191
- ) -> "AsyncGenerator[Self]":
191
+ ) -> AsyncGenerator[Self, None]:
192
192
  """
193
193
  Make a copy of this case.
194
194
 
@@ -209,7 +209,7 @@ class AsyncFoamCase(FoamCaseRunBase):
209
209
  @asynccontextmanager
210
210
  async def clone(
211
211
  self, dst: Optional[Union["os.PathLike[str]", str]] = None
212
- ) -> "AsyncGenerator[Self]":
212
+ ) -> AsyncGenerator[Self, None]:
213
213
  """
214
214
  Clone this case (make a clean copy).
215
215
 
@@ -2,6 +2,7 @@ import asyncio
2
2
  import os
3
3
  import subprocess
4
4
  import sys
5
+ from io import BytesIO
5
6
  from typing import IO, Optional, Union
6
7
 
7
8
  if sys.version_info >= (3, 9):
@@ -48,22 +49,26 @@ def run_sync(
48
49
  shell=isinstance(cmd, str),
49
50
  )
50
51
 
51
- error = b""
52
-
53
52
  if stderr == STDOUT:
54
53
  stderr = stdout
55
54
  if stderr not in (PIPE, DEVNULL):
55
+ stderr_copy = BytesIO()
56
+
56
57
  assert not isinstance(stderr, int)
57
58
  if stderr is None:
58
59
  stderr = sys.stderr.buffer
59
60
 
60
61
  assert proc.stderr is not None
61
62
  for line in proc.stderr:
62
- error += line
63
63
  stderr.write(line)
64
+ stderr_copy.write(line)
65
+
66
+ output, _ = proc.communicate()
67
+ assert not _
68
+ error = stderr_copy.getvalue()
69
+ else:
70
+ output, error = proc.communicate()
64
71
 
65
- output, _ = proc.communicate()
66
- assert not _
67
72
  assert proc.returncode is not None
68
73
 
69
74
  if check and proc.returncode != 0:
@@ -108,22 +113,26 @@ async def run_async(
108
113
  stderr=PIPE,
109
114
  )
110
115
 
111
- error = b""
112
-
113
116
  if stderr == STDOUT:
114
117
  stderr = stdout
115
118
  if stderr not in (PIPE, DEVNULL):
119
+ stderr_copy = BytesIO()
120
+
116
121
  assert not isinstance(stderr, int)
117
122
  if stderr is None:
118
123
  stderr = sys.stderr.buffer
119
124
 
120
125
  assert proc.stderr is not None
121
126
  async for line in proc.stderr:
122
- error += line
123
127
  stderr.write(line)
128
+ stderr_copy.write(line)
129
+
130
+ output, _ = await proc.communicate()
131
+ assert not _
132
+ error = stderr_copy.getvalue()
133
+ else:
134
+ output, error = await proc.communicate()
124
135
 
125
- output, _ = await proc.communicate()
126
- assert not _
127
136
  assert proc.returncode is not None
128
137
 
129
138
  if check and proc.returncode != 0:
foamlib/_cases/_sync.py CHANGED
@@ -1,7 +1,6 @@
1
1
  import os
2
2
  import shutil
3
3
  import sys
4
- from pathlib import Path
5
4
  from types import TracebackType
6
5
  from typing import Any, Callable, Optional, Type, Union, overload
7
6
 
@@ -49,9 +48,6 @@ class FoamCase(FoamCaseRunBase):
49
48
 
50
49
  return calls.value
51
50
 
52
- def __init__(self, path: Union["os.PathLike[str]", str] = Path()):
53
- super().__init__(path)
54
-
55
51
  @staticmethod
56
52
  def _run(
57
53
  cmd: Union[Sequence[Union[str, "os.PathLike[str]"]], str],
foamlib/_files/_files.py CHANGED
@@ -86,7 +86,7 @@ class FoamFile(
86
86
 
87
87
  def as_dict(self) -> FoamFileBase._Dict:
88
88
  """Return a nested dict representation of the dictionary."""
89
- ret = self._file.as_dict()
89
+ ret = self._file.as_dict(include_header=True)
90
90
 
91
91
  for k in self._keywords:
92
92
  assert isinstance(ret, dict)
@@ -294,15 +294,10 @@ class FoamFile(
294
294
 
295
295
  def _iter(self, keywords: Tuple[str, ...] = ()) -> Iterator[Optional[str]]:
296
296
  _, parsed = self._read()
297
-
298
- yield from (
299
- k[-1] if k else None
300
- for k in parsed
301
- if k != ("FoamFile",) and k[:-1] == keywords
302
- )
297
+ yield from (k[-1] if k else None for k in parsed if k[:-1] == keywords)
303
298
 
304
299
  def __iter__(self) -> Iterator[Optional[str]]:
305
- return self._iter()
300
+ yield from (k for k in self._iter() if k != "FoamFile")
306
301
 
307
302
  def __contains__(self, keywords: object) -> bool:
308
303
  if not keywords:
@@ -328,11 +323,16 @@ class FoamFile(
328
323
  def __fspath__(self) -> str:
329
324
  return str(self.path)
330
325
 
331
- def as_dict(self) -> FoamFileBase._File:
332
- """Return a nested dict representation of the file."""
326
+ def as_dict(self, *, include_header: bool = False) -> FoamFileBase._File:
327
+ """
328
+ Return a nested dict representation of the file.
329
+
330
+ :param include_header: Whether to include the "FoamFile" header in the output.
331
+ """
333
332
  _, parsed = self._read()
334
333
  d = parsed.as_dict()
335
- del d["FoamFile"]
334
+ if not include_header:
335
+ d.pop("FoamFile", None)
336
336
  return d
337
337
 
338
338
 
@@ -95,18 +95,35 @@ def _unpack_binary_field(
95
95
  return [all]
96
96
 
97
97
 
98
+ _IDENTCHARS = identchars + "$"
99
+ _IDENTBODYCHARS = (
100
+ printables.replace(";", "")
101
+ .replace("{", "")
102
+ .replace("}", "")
103
+ .replace("[", "")
104
+ .replace("]", "")
105
+ )
106
+
98
107
  _SWITCH = (
99
- Keyword("yes") | Keyword("true") | Keyword("on") | Keyword("y") | Keyword("t")
108
+ Keyword("yes", _IDENTBODYCHARS)
109
+ | Keyword("true", _IDENTBODYCHARS)
110
+ | Keyword("on", _IDENTBODYCHARS)
111
+ | Keyword("y", _IDENTBODYCHARS)
112
+ | Keyword("t", _IDENTBODYCHARS)
100
113
  ).set_parse_action(lambda: True) | (
101
- Keyword("no") | Keyword("false") | Keyword("off") | Keyword("n") | Keyword("f")
114
+ Keyword("no", _IDENTBODYCHARS)
115
+ | Keyword("false", _IDENTBODYCHARS)
116
+ | Keyword("off", _IDENTBODYCHARS)
117
+ | Keyword("n", _IDENTBODYCHARS)
118
+ | Keyword("f", _IDENTBODYCHARS)
102
119
  ).set_parse_action(lambda: False)
103
120
  _DIMENSIONS = (
104
121
  Literal("[").suppress() + common.number[0, 7] + Literal("]").suppress()
105
122
  ).set_parse_action(lambda tks: FoamFileBase.DimensionSet(*tks))
106
123
  _TENSOR = _list_of(common.number) | common.number
107
124
  _IDENTIFIER = Combine(
108
- Word(identchars + "$", printables, exclude_chars="[{(;)}]")
109
- + Opt(Literal("(") + Word(printables, exclude_chars="[{(;)}]") + Literal(")"))
125
+ Word(_IDENTCHARS, _IDENTBODYCHARS, exclude_chars="()")
126
+ + Opt(Literal("(") + Word(_IDENTBODYCHARS, exclude_chars="()") + Literal(")"))
110
127
  )
111
128
  _DIMENSIONED = (Opt(_IDENTIFIER) + _DIMENSIONS + _TENSOR).set_parse_action(
112
129
  lambda tks: FoamFileBase.Dimensioned(*reversed(tks.as_list()))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: foamlib
3
- Version: 0.6.5
3
+ Version: 0.6.7
4
4
  Summary: A Python interface for interacting with OpenFOAM
5
5
  Author-email: "Gabriel S. Gerlero" <ggerlero@cimec.unl.edu.ar>
6
6
  Project-URL: Homepage, https://github.com/gerlero/foamlib
@@ -37,12 +37,13 @@ Requires-Dist: foamlib[typing] ; extra == 'dev'
37
37
  Requires-Dist: foamlib[docs] ; extra == 'dev'
38
38
  Provides-Extra: docs
39
39
  Requires-Dist: foamlib[numpy] ; extra == 'docs'
40
- Requires-Dist: sphinx <9,>=7 ; extra == 'docs'
40
+ Requires-Dist: sphinx <9,>=5 ; extra == 'docs'
41
41
  Requires-Dist: sphinx-rtd-theme ; extra == 'docs'
42
42
  Provides-Extra: lint
43
43
  Requires-Dist: ruff ; extra == 'lint'
44
44
  Provides-Extra: numpy
45
45
  Requires-Dist: numpy <3,>=1 ; extra == 'numpy'
46
+ Requires-Dist: numpy <3,>=1.25.0 ; (python_version >= "3.10") and extra == 'numpy'
46
47
  Provides-Extra: test
47
48
  Requires-Dist: foamlib[numpy] ; extra == 'test'
48
49
  Requires-Dist: pytest <9,>=7 ; extra == 'test'
@@ -59,7 +60,9 @@ Requires-Dist: mypy <2,>=1 ; extra == 'typing'
59
60
  [![Codecov](https://codecov.io/gh/gerlero/foamlib/branch/main/graph/badge.svg)](https://codecov.io/gh/gerlero/foamlib)
60
61
  [![Checked with mypy](http://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/)
61
62
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
63
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
62
64
  [![PyPI](https://img.shields.io/pypi/v/foamlib)](https://pypi.org/project/foamlib/)
65
+ [![Conda Version](https://img.shields.io/conda/vn/conda-forge/foamlib)](https://anaconda.org/conda-forge/foamlib)
63
66
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/foamlib)](https://pypi.org/project/foamlib/)
64
67
  ![OpenFOAM](https://img.shields.io/badge/openfoam-.com%20|%20.org-informational)
65
68
  [![Docker image](https://img.shields.io/badge/docker%20image-microfluidica%2Ffoamlib-0085a0)](https://hub.docker.com/r/microfluidica/foamlib/)
@@ -68,19 +71,26 @@ Requires-Dist: mypy <2,>=1 ; extra == 'typing'
68
71
 
69
72
  It offers the following classes:
70
73
 
71
- * [`FoamFile`](https://foamlib.readthedocs.io/en/stable/files.html#foamlib.FoamFile) (and [`FoamFieldFile`](https://foamlib.readthedocs.io/en/stable/files.html#foamlib.FoamFieldFile)): read-write access to OpenFOAM configuration and field files as if they were Python `dict`s, using `foamlib`'s own parser. Supports both ASCII and binary field formats.
74
+ * [`FoamFile`](https://foamlib.readthedocs.io/en/stable/files.html#foamlib.FoamFile) (and [`FoamFieldFile`](https://foamlib.readthedocs.io/en/stable/files.html#foamlib.FoamFieldFile)): read-write access to OpenFOAM configuration and field files as if they were Python `dict`s, using `foamlib`'s own parser. Supports ASCII and binary field formats (with or without compression).
72
75
  * [`FoamCase`](https://foamlib.readthedocs.io/en/stable/cases.html#foamlib.FoamCase): a class for configuring, running, and accessing the results of OpenFOAM cases.
73
76
  * [`AsyncFoamCase`](https://foamlib.readthedocs.io/en/stable/cases.html#foamlib.AsyncFoamCase): variant of `FoamCase` with asynchronous methods for running multiple cases at once.
77
+ * [`AsyncSlurmFoamCase`](https://foamlib.readthedocs.io/en/stable/cases.html#foamlib.AsyncSlurmFoamCase): subclass of `AsyncFoamCase` used for running cases on a Slurm cluster.
74
78
 
75
79
  ## Get started
76
80
 
77
81
  ### Install
78
82
 
79
- Install with [pip](https://pypi.org/project/pip/):
83
+ * With [pip](https://pypi.org/project/pip/):
80
84
 
81
- ```bash
82
- pip install foamlib
83
- ```
85
+ ```bash
86
+ pip install foamlib
87
+ ```
88
+
89
+ * With [conda](https://docs.conda.io/en/latest/):
90
+
91
+ ```bash
92
+ conda install -c conda-forge foamlib
93
+ ```
84
94
 
85
95
  ### Clone a case
86
96
 
@@ -164,6 +174,7 @@ from foamlib import AsyncFoamCase
164
174
  from scipy.optimize import differential_evolution
165
175
 
166
176
  base = AsyncFoamCase(Path(os.environ["FOAM_TUTORIALS"]) / "incompressible/simpleFoam/pitzDaily")
177
+ # Replace with `AsyncSlurmFoamCase` if on a cluster and you want cases to be run as Slurm jobs
167
178
 
168
179
  async def cost(x):
169
180
  async with base.clone() as clone:
@@ -1,22 +1,22 @@
1
- foamlib/__init__.py,sha256=rB9ilpTj2t4pK8NuAdlVahgfFWtBlWld8s2r_oRsW5s,486
1
+ foamlib/__init__.py,sha256=iaj4sni5OiXEQQ21hCOeo3akWqysdXWCuJSu-uQwRIY,486
2
2
  foamlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  foamlib/_cases/__init__.py,sha256=wTUHcUgU1CBgpu0cUMtksQ5VKG6B8CFu9xc3dWwsQuo,358
4
- foamlib/_cases/_async.py,sha256=PYODgIkRLHArMf3wtf34jMx7gBGi-K6hoLEhjYK9bOw,7753
4
+ foamlib/_cases/_async.py,sha256=rkJkOvOPQBcIrIyj2Q98HFh0eZ5QHzClSqEt-wcyS0M,7734
5
5
  foamlib/_cases/_base.py,sha256=4VWsu22VockyKgU_5tnSMeNrAkMgBKwZo2KGkV65rRQ,6739
6
6
  foamlib/_cases/_run.py,sha256=SjA-Qux5NhnhcLz7qiph2DcGYpElAAl_PlTGk6kGeuU,13972
7
7
  foamlib/_cases/_slurm.py,sha256=rhGSFJ-3g72TnAYlhECGfs7P7IkeaHL3ysjXfXLdCCc,2308
8
- foamlib/_cases/_subprocess.py,sha256=GTmHWy1LRD9ujpXJfSTXU2bf87GncpIA0VOR1rQW2fg,3633
9
- foamlib/_cases/_sync.py,sha256=L1Em9_32zd01RnMvksZ1GU-4okxhcwZgpLQf1c15uAs,6038
8
+ foamlib/_cases/_subprocess.py,sha256=Z6GHZ44fIQcOiDO-c7Oqp8pqE8NG7WFP9Mdbf_6WtIU,3916
9
+ foamlib/_cases/_sync.py,sha256=5lVMGuesCC--1GX8CL82bXg2o0K7OsZoff2zSOEs5d0,5910
10
10
  foamlib/_cases/_util.py,sha256=GNndpqw3Jg_S-Hxzl5vwRgD0czcTNb9NYHMhcfBoMBg,1493
11
11
  foamlib/_files/__init__.py,sha256=-UqB9YTH6mrJfXCX00kPTAAY20XG64u1MGPw_1ewLVs,148
12
12
  foamlib/_files/_base.py,sha256=zaFDjLE6jB7WtGWk8hfKusjLtlGu6CZV16AHJpRUibs,1929
13
- foamlib/_files/_files.py,sha256=1jV52dZqr-g6P0X0lA80OQcr2yMt4O-mAgERcaU4440,15583
13
+ foamlib/_files/_files.py,sha256=nQXQ-NbRDy0GETYi4e9RHsnbvLxxjSTnXVpRbTV8iXY,15748
14
14
  foamlib/_files/_io.py,sha256=T8vTEmJDidL03qeX1PUJFND-_vaF0AuC_0lE_zxLz7Q,2447
15
- foamlib/_files/_parsing.py,sha256=DzgJ53QnohRQyLXn2zOs52RIQ7bJ_fS_S2Z7rmRyVK4,9023
15
+ foamlib/_files/_parsing.py,sha256=SvPAbNb_xJwOBRGii4oLOUvhj9OdJ8auMIzdx77AYwI,9394
16
16
  foamlib/_files/_serialization.py,sha256=pb8_cIVgRhGS_ZV2p3x8p5_lK1SS6xzQHscAYYuOgFY,3407
17
17
  foamlib/_files/_util.py,sha256=UMzXmTFgvbp46w6k3oEZJoYC98pFgEK6LN5uLOwrlCg,397
18
- foamlib-0.6.5.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
19
- foamlib-0.6.5.dist-info/METADATA,sha256=xgpPiDbPfFBJjg09mDarYez95jP5RSw0uGCt9AS9kxk,6569
20
- foamlib-0.6.5.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
21
- foamlib-0.6.5.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
22
- foamlib-0.6.5.dist-info/RECORD,,
18
+ foamlib-0.6.7.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
19
+ foamlib-0.6.7.dist-info/METADATA,sha256=ZgNLLtXhkCRJtcrycPWZfCxoEd3CU_HDv1--_4C7p-o,7333
20
+ foamlib-0.6.7.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
21
+ foamlib-0.6.7.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
22
+ foamlib-0.6.7.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.1.0)
2
+ Generator: setuptools (75.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5