foamlib 0.3.1__tar.gz → 0.3.2__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.3.1 → foamlib-0.3.2}/PKG-INFO +1 -1
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib/__init__.py +3 -2
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib/_files/_files.py +3 -3
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib/_files/_serialization.py +29 -13
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib/_util.py +35 -33
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib.egg-info/PKG-INFO +1 -1
- {foamlib-0.3.1 → foamlib-0.3.2}/LICENSE.txt +0 -0
- {foamlib-0.3.1 → foamlib-0.3.2}/README.md +0 -0
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib/_cases.py +0 -0
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib/_files/__init__.py +0 -0
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib/_files/_base.py +0 -0
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib/_files/_fields.py +0 -0
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib/_files/_io.py +0 -0
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib/_files/_parsing.py +0 -0
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib/py.typed +0 -0
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib.egg-info/SOURCES.txt +0 -0
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib.egg-info/dependency_links.txt +0 -0
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib.egg-info/requires.txt +0 -0
- {foamlib-0.3.1 → foamlib-0.3.2}/foamlib.egg-info/top_level.txt +0 -0
- {foamlib-0.3.1 → foamlib-0.3.2}/pyproject.toml +0 -0
- {foamlib-0.3.1 → foamlib-0.3.2}/setup.cfg +0 -0
@@ -1,10 +1,10 @@
|
|
1
1
|
"""A Python interface for interacting with OpenFOAM."""
|
2
2
|
|
3
|
-
__version__ = "0.3.
|
3
|
+
__version__ = "0.3.2"
|
4
4
|
|
5
5
|
from ._cases import AsyncFoamCase, FoamCase, FoamCaseBase
|
6
6
|
from ._files import FoamDict, FoamFieldFile, FoamFile
|
7
|
-
from ._util import CalledProcessError
|
7
|
+
from ._util import CalledProcessError, CalledProcessWarning
|
8
8
|
|
9
9
|
__all__ = [
|
10
10
|
"FoamCase",
|
@@ -14,4 +14,5 @@ __all__ = [
|
|
14
14
|
"FoamFieldFile",
|
15
15
|
"FoamDict",
|
16
16
|
"CalledProcessError",
|
17
|
+
"CalledProcessWarning",
|
17
18
|
]
|
@@ -12,7 +12,7 @@ else:
|
|
12
12
|
|
13
13
|
from ._base import FoamDict
|
14
14
|
from ._io import FoamFileIO
|
15
|
-
from ._serialization import
|
15
|
+
from ._serialization import dumps
|
16
16
|
|
17
17
|
|
18
18
|
class FoamFile(
|
@@ -134,7 +134,7 @@ class FoamFile(
|
|
134
134
|
start, end = parsed.entry_location(keywords, missing_ok=True)
|
135
135
|
|
136
136
|
self._write(
|
137
|
-
f"{contents[:start]}\n{
|
137
|
+
f"{contents[:start]}\n{dumps({keywords[-1]: {}})}\n{contents[end:]}"
|
138
138
|
)
|
139
139
|
|
140
140
|
for k, v in data.items():
|
@@ -143,7 +143,7 @@ class FoamFile(
|
|
143
143
|
start, end = parsed.entry_location(keywords, missing_ok=True)
|
144
144
|
|
145
145
|
self._write(
|
146
|
-
f"{contents[:start]}\n{
|
146
|
+
f"{contents[:start]}\n{dumps({keywords[-1]: data}, assume_field=assume_field, assume_dimensions=assume_dimensions)}\n{contents[end:]}"
|
147
147
|
)
|
148
148
|
|
149
149
|
def __setitem__(
|
@@ -8,18 +8,32 @@ else:
|
|
8
8
|
from .._util import is_sequence
|
9
9
|
from ._base import FoamDict
|
10
10
|
|
11
|
+
try:
|
12
|
+
import numpy as np
|
11
13
|
|
12
|
-
|
14
|
+
numpy = True
|
15
|
+
except ModuleNotFoundError:
|
16
|
+
numpy = False
|
17
|
+
|
18
|
+
|
19
|
+
def dumps(
|
13
20
|
data: FoamDict._SetData,
|
14
21
|
*,
|
15
22
|
assume_field: bool = False,
|
16
23
|
assume_dimensions: bool = False,
|
17
24
|
assume_data_entries: bool = False,
|
18
25
|
) -> str:
|
19
|
-
if isinstance(data,
|
26
|
+
if numpy and isinstance(data, np.ndarray):
|
27
|
+
return dumps(
|
28
|
+
data.tolist(),
|
29
|
+
assume_field=assume_field,
|
30
|
+
assume_dimensions=assume_dimensions,
|
31
|
+
)
|
32
|
+
|
33
|
+
elif isinstance(data, Mapping):
|
20
34
|
entries = []
|
21
35
|
for k, v in data.items():
|
22
|
-
s =
|
36
|
+
s = dumps(
|
23
37
|
v,
|
24
38
|
assume_field=assume_field,
|
25
39
|
assume_dimensions=assume_dimensions,
|
@@ -43,17 +57,17 @@ def serialize(
|
|
43
57
|
|
44
58
|
elif assume_field and is_sequence(data):
|
45
59
|
if isinstance(data[0], (int, float)) and len(data) in (3, 6, 9):
|
46
|
-
return f"uniform {
|
60
|
+
return f"uniform {dumps(data)}"
|
47
61
|
elif isinstance(data[0], (int, float)):
|
48
|
-
return f"nonuniform List<scalar> {len(data)}{
|
62
|
+
return f"nonuniform List<scalar> {len(data)}{dumps(data)}"
|
49
63
|
elif len(data[0]) == 3:
|
50
|
-
return f"nonuniform List<vector> {len(data)}{
|
64
|
+
return f"nonuniform List<vector> {len(data)}{dumps(data)}"
|
51
65
|
elif len(data[0]) == 6:
|
52
|
-
return f"nonuniform List<symmTensor> {len(data)}{
|
66
|
+
return f"nonuniform List<symmTensor> {len(data)}{dumps(data)}"
|
53
67
|
elif len(data[0]) == 9:
|
54
|
-
return f"nonuniform List<tensor> {len(data)}{
|
68
|
+
return f"nonuniform List<tensor> {len(data)}{dumps(data)}"
|
55
69
|
else:
|
56
|
-
return
|
70
|
+
return dumps(
|
57
71
|
data,
|
58
72
|
assume_dimensions=assume_dimensions,
|
59
73
|
assume_data_entries=assume_data_entries,
|
@@ -61,18 +75,20 @@ def serialize(
|
|
61
75
|
|
62
76
|
elif assume_data_entries and isinstance(data, tuple):
|
63
77
|
return " ".join(
|
64
|
-
|
78
|
+
dumps(v, assume_field=assume_field, assume_dimensions=assume_dimensions)
|
65
79
|
for v in data
|
66
80
|
)
|
67
81
|
|
68
82
|
elif isinstance(data, FoamDict.Dimensioned):
|
69
83
|
if data.name is not None:
|
70
|
-
return f"{data.name} {
|
84
|
+
return f"{data.name} {dumps(data.dimensions, assume_dimensions=True)} {dumps(data.value)}"
|
71
85
|
else:
|
72
|
-
return
|
86
|
+
return (
|
87
|
+
f"{dumps(data.dimensions, assume_dimensions=True)} {dumps(data.value)}"
|
88
|
+
)
|
73
89
|
|
74
90
|
elif is_sequence(data):
|
75
|
-
return f"({' '.join(
|
91
|
+
return f"({' '.join(dumps(v) for v in data)})"
|
76
92
|
|
77
93
|
elif data is True:
|
78
94
|
return "yes"
|
@@ -2,7 +2,8 @@ import asyncio
|
|
2
2
|
import subprocess
|
3
3
|
import sys
|
4
4
|
from pathlib import Path
|
5
|
-
from typing import Any, Union
|
5
|
+
from typing import Any, Optional, Union
|
6
|
+
from warnings import warn
|
6
7
|
|
7
8
|
if sys.version_info >= (3, 9):
|
8
9
|
from collections.abc import Mapping, Sequence
|
@@ -14,31 +15,36 @@ if sys.version_info >= (3, 10):
|
|
14
15
|
else:
|
15
16
|
from typing_extensions import TypeGuard
|
16
17
|
|
17
|
-
try:
|
18
|
-
import numpy as np
|
19
|
-
except ModuleNotFoundError:
|
20
|
-
numpy = False
|
21
|
-
else:
|
22
|
-
numpy = True
|
23
|
-
|
24
18
|
|
25
19
|
def is_sequence(
|
26
20
|
value: Any,
|
27
|
-
) -> TypeGuard[
|
28
|
-
return (
|
29
|
-
isinstance(value, Sequence)
|
30
|
-
and not isinstance(value, str)
|
31
|
-
or numpy
|
32
|
-
and isinstance(value, np.ndarray)
|
33
|
-
)
|
21
|
+
) -> TypeGuard[Sequence[Any]]:
|
22
|
+
return isinstance(value, Sequence) and not isinstance(value, str)
|
34
23
|
|
35
24
|
|
36
|
-
CalledProcessError
|
25
|
+
class CalledProcessError(subprocess.CalledProcessError):
|
26
|
+
"""Exception raised when a process fails and `check=True`."""
|
37
27
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
28
|
+
def __str__(self) -> str:
|
29
|
+
msg = super().__str__()
|
30
|
+
if self.stderr:
|
31
|
+
msg += f"\n{self.stderr}"
|
32
|
+
return msg
|
33
|
+
|
34
|
+
|
35
|
+
class CalledProcessWarning(Warning):
|
36
|
+
"""Warning raised when a process prints to stderr and `check=True`."""
|
37
|
+
|
38
|
+
|
39
|
+
def _check(
|
40
|
+
retcode: int,
|
41
|
+
cmd: Union[Sequence[Union[str, Path]], str, Path],
|
42
|
+
stderr: Optional[str],
|
43
|
+
) -> None:
|
44
|
+
if retcode != 0:
|
45
|
+
raise CalledProcessError(retcode, cmd, None, stderr)
|
46
|
+
elif stderr:
|
47
|
+
warn(f"Command {cmd} printed to stderr.\n{stderr}", CalledProcessWarning)
|
42
48
|
|
43
49
|
|
44
50
|
def run_process(
|
@@ -47,7 +53,7 @@ def run_process(
|
|
47
53
|
check: bool = True,
|
48
54
|
cwd: Union[None, str, Path] = None,
|
49
55
|
env: Union[None, Mapping[str, str]] = None,
|
50
|
-
) ->
|
56
|
+
) -> None:
|
51
57
|
shell = not is_sequence(cmd)
|
52
58
|
|
53
59
|
if sys.version_info < (3, 8):
|
@@ -60,14 +66,14 @@ def run_process(
|
|
60
66
|
cmd,
|
61
67
|
cwd=cwd,
|
62
68
|
env=env,
|
63
|
-
stdout=
|
64
|
-
stderr=
|
69
|
+
stdout=subprocess.DEVNULL,
|
70
|
+
stderr=subprocess.PIPE if check else subprocess.DEVNULL,
|
65
71
|
text=True,
|
66
72
|
shell=shell,
|
67
|
-
check=check,
|
68
73
|
)
|
69
74
|
|
70
|
-
|
75
|
+
if check:
|
76
|
+
_check(proc.returncode, cmd, proc.stderr)
|
71
77
|
|
72
78
|
|
73
79
|
async def run_process_async(
|
@@ -76,14 +82,14 @@ async def run_process_async(
|
|
76
82
|
check: bool = True,
|
77
83
|
cwd: Union[None, str, Path] = None,
|
78
84
|
env: Union[None, Mapping[str, str]] = None,
|
79
|
-
) ->
|
85
|
+
) -> None:
|
80
86
|
if not is_sequence(cmd):
|
81
87
|
proc = await asyncio.create_subprocess_shell(
|
82
88
|
str(cmd),
|
83
89
|
cwd=cwd,
|
84
90
|
env=env,
|
85
91
|
stdout=asyncio.subprocess.DEVNULL,
|
86
|
-
stderr=asyncio.subprocess.PIPE,
|
92
|
+
stderr=asyncio.subprocess.PIPE if check else asyncio.subprocess.DEVNULL,
|
87
93
|
)
|
88
94
|
|
89
95
|
else:
|
@@ -94,7 +100,7 @@ async def run_process_async(
|
|
94
100
|
cwd=cwd,
|
95
101
|
env=env,
|
96
102
|
stdout=asyncio.subprocess.DEVNULL,
|
97
|
-
stderr=asyncio.subprocess.PIPE,
|
103
|
+
stderr=asyncio.subprocess.PIPE if check else asyncio.subprocess.DEVNULL,
|
98
104
|
)
|
99
105
|
|
100
106
|
stdout, stderr = await proc.communicate()
|
@@ -102,9 +108,5 @@ async def run_process_async(
|
|
102
108
|
assert stdout is None
|
103
109
|
assert proc.returncode is not None
|
104
110
|
|
105
|
-
ret = CompletedProcess(cmd, proc.returncode, None, stderr.decode())
|
106
|
-
|
107
111
|
if check:
|
108
|
-
|
109
|
-
|
110
|
-
return ret
|
112
|
+
_check(proc.returncode, cmd, stderr.decode())
|
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
|