foamlib 0.2.3__py3-none-any.whl → 0.2.4__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 +1 -1
- foamlib/_dictionaries/_files.py +84 -56
- foamlib/_dictionaries/_serialization.py +25 -5
- {foamlib-0.2.3.dist-info → foamlib-0.2.4.dist-info}/METADATA +2 -1
- foamlib-0.2.4.dist-info/RECORD +14 -0
- foamlib-0.2.3.dist-info/RECORD +0 -14
- {foamlib-0.2.3.dist-info → foamlib-0.2.4.dist-info}/LICENSE.txt +0 -0
- {foamlib-0.2.3.dist-info → foamlib-0.2.4.dist-info}/WHEEL +0 -0
- {foamlib-0.2.3.dist-info → foamlib-0.2.4.dist-info}/top_level.txt +0 -0
foamlib/__init__.py
CHANGED
foamlib/_dictionaries/_files.py
CHANGED
@@ -11,9 +11,11 @@ from typing import (
|
|
11
11
|
cast,
|
12
12
|
)
|
13
13
|
|
14
|
+
from typing_extensions import Self
|
15
|
+
|
14
16
|
from ._base import FoamDictionaryBase
|
15
17
|
from ._parsing import Parsed, as_dict, get_entry_locn, get_value, parse
|
16
|
-
from ._serialization import
|
18
|
+
from ._serialization import serialize_entry
|
17
19
|
|
18
20
|
try:
|
19
21
|
import numpy as np
|
@@ -22,9 +24,62 @@ except ModuleNotFoundError:
|
|
22
24
|
pass
|
23
25
|
|
24
26
|
|
27
|
+
class _FoamFileBase:
|
28
|
+
def __init__(self, path: Union[str, Path]) -> None:
|
29
|
+
self.path = Path(path).absolute()
|
30
|
+
if self.path.is_dir():
|
31
|
+
raise IsADirectoryError(self.path)
|
32
|
+
elif not self.path.is_file():
|
33
|
+
raise FileNotFoundError(self.path)
|
34
|
+
|
35
|
+
self.__contents: Optional[str] = None
|
36
|
+
self.__parsed: Optional[Parsed] = None
|
37
|
+
self.__defer_io = 0
|
38
|
+
self.__dirty = False
|
39
|
+
|
40
|
+
def __enter__(self) -> Self:
|
41
|
+
if self.__defer_io == 0:
|
42
|
+
self._read()
|
43
|
+
self.__defer_io += 1
|
44
|
+
return self
|
45
|
+
|
46
|
+
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
|
47
|
+
self.__defer_io -= 1
|
48
|
+
if self.__defer_io == 0 and self.__dirty:
|
49
|
+
assert self.__contents is not None
|
50
|
+
self._write(self.__contents)
|
51
|
+
assert not self.__dirty
|
52
|
+
|
53
|
+
def _read(self) -> Tuple[str, Parsed]:
|
54
|
+
if not self.__defer_io:
|
55
|
+
contents = self.path.read_text()
|
56
|
+
if contents != self.__contents:
|
57
|
+
self.__contents = contents
|
58
|
+
self.__parsed = None
|
59
|
+
|
60
|
+
assert self.__contents is not None
|
61
|
+
|
62
|
+
if self.__parsed is None:
|
63
|
+
self.__parsed = parse(self.__contents)
|
64
|
+
|
65
|
+
return self.__contents, self.__parsed
|
66
|
+
|
67
|
+
def _write(self, contents: str) -> None:
|
68
|
+
self.__contents = contents
|
69
|
+
self.__parsed = None
|
70
|
+
if not self.__defer_io:
|
71
|
+
self.path.write_text(contents)
|
72
|
+
self.__dirty = False
|
73
|
+
else:
|
74
|
+
self.__dirty = True
|
75
|
+
|
76
|
+
|
25
77
|
class FoamFile(
|
78
|
+
_FoamFileBase,
|
26
79
|
FoamDictionaryBase,
|
27
|
-
MutableMapping[
|
80
|
+
MutableMapping[
|
81
|
+
Union[str, Tuple[str, ...]], Union["FoamFile.Value", "FoamFile.Dictionary"]
|
82
|
+
],
|
28
83
|
):
|
29
84
|
"""
|
30
85
|
An OpenFOAM dictionary file.
|
@@ -75,9 +130,20 @@ class FoamFile(
|
|
75
130
|
def __iter__(self) -> Iterator[str]:
|
76
131
|
return self._file._iter(tuple(self._keywords))
|
77
132
|
|
133
|
+
def __contains__(self, keyword: object) -> bool:
|
134
|
+
return (*self._keywords, keyword) in self._file
|
135
|
+
|
78
136
|
def __len__(self) -> int:
|
79
137
|
return len(list(iter(self)))
|
80
138
|
|
139
|
+
def update(self, *args: Any, **kwargs: Any) -> None:
|
140
|
+
with self._file:
|
141
|
+
super().update(*args, **kwargs)
|
142
|
+
|
143
|
+
def clear(self) -> None:
|
144
|
+
with self._file:
|
145
|
+
super().clear()
|
146
|
+
|
81
147
|
def __repr__(self) -> str:
|
82
148
|
return f"{type(self).__qualname__}({self._file}, {self._keywords})"
|
83
149
|
|
@@ -95,54 +161,6 @@ class FoamFile(
|
|
95
161
|
|
96
162
|
return ret
|
97
163
|
|
98
|
-
def __init__(self, path: Union[str, Path]) -> None:
|
99
|
-
self.path = Path(path).absolute()
|
100
|
-
if self.path.is_dir():
|
101
|
-
raise IsADirectoryError(self.path)
|
102
|
-
elif not self.path.is_file():
|
103
|
-
raise FileNotFoundError(self.path)
|
104
|
-
|
105
|
-
self._contents: Optional[str] = None
|
106
|
-
self._parsed: Optional[Parsed] = None
|
107
|
-
self._defer_io = 0
|
108
|
-
self._dirty = False
|
109
|
-
|
110
|
-
def __enter__(self) -> "FoamFile":
|
111
|
-
if self._defer_io == 0:
|
112
|
-
self._read()
|
113
|
-
self._defer_io += 1
|
114
|
-
return self
|
115
|
-
|
116
|
-
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
|
117
|
-
self._defer_io -= 1
|
118
|
-
if self._defer_io == 0 and self._dirty:
|
119
|
-
assert self._contents is not None
|
120
|
-
self._write(self._contents)
|
121
|
-
assert not self._dirty
|
122
|
-
|
123
|
-
def _read(self) -> Tuple[str, Parsed]:
|
124
|
-
if not self._defer_io:
|
125
|
-
contents = self.path.read_text()
|
126
|
-
if contents != self._contents:
|
127
|
-
self._contents = contents
|
128
|
-
self._parsed = None
|
129
|
-
|
130
|
-
assert self._contents is not None
|
131
|
-
|
132
|
-
if self._parsed is None:
|
133
|
-
self._parsed = parse(self._contents)
|
134
|
-
|
135
|
-
return self._contents, self._parsed
|
136
|
-
|
137
|
-
def _write(self, contents: str) -> None:
|
138
|
-
self._contents = contents
|
139
|
-
self._parsed = None
|
140
|
-
if not self._defer_io:
|
141
|
-
self.path.write_text(contents)
|
142
|
-
self._dirty = False
|
143
|
-
else:
|
144
|
-
self._dirty = True
|
145
|
-
|
146
164
|
def __getitem__(
|
147
165
|
self, keywords: Union[str, Tuple[str, ...]]
|
148
166
|
) -> Union["FoamFile.Value", "FoamFile.Dictionary"]:
|
@@ -179,7 +197,7 @@ class FoamFile(
|
|
179
197
|
start, end = get_entry_locn(parsed, keywords, missing_ok=True)
|
180
198
|
|
181
199
|
self._write(
|
182
|
-
f"{contents[:start]}
|
200
|
+
f"{contents[:start]}\n{serialize_entry(keywords[-1], {})}\n{contents[end:]}"
|
183
201
|
)
|
184
202
|
|
185
203
|
for k, v in value.items():
|
@@ -187,12 +205,8 @@ class FoamFile(
|
|
187
205
|
else:
|
188
206
|
start, end = get_entry_locn(parsed, keywords, missing_ok=True)
|
189
207
|
|
190
|
-
value = serialize_value(
|
191
|
-
value, assume_field=assume_field, assume_dimensions=assume_dimensions
|
192
|
-
)
|
193
|
-
|
194
208
|
self._write(
|
195
|
-
f"{contents[:start]}
|
209
|
+
f"{contents[:start]}\n{serialize_entry(keywords[-1], value, assume_field=assume_field, assume_dimensions=assume_dimensions)}\n{contents[end:]}"
|
196
210
|
)
|
197
211
|
|
198
212
|
def __setitem__(self, keywords: Union[str, Tuple[str, ...]], value: Any) -> None:
|
@@ -220,9 +234,23 @@ class FoamFile(
|
|
220
234
|
def __iter__(self) -> Iterator[str]:
|
221
235
|
return self._iter()
|
222
236
|
|
237
|
+
def __contains__(self, keywords: object) -> bool:
|
238
|
+
if not isinstance(keywords, tuple):
|
239
|
+
keywords = (keywords,)
|
240
|
+
_, parsed = self._read()
|
241
|
+
return keywords in parsed
|
242
|
+
|
223
243
|
def __len__(self) -> int:
|
224
244
|
return len(list(iter(self)))
|
225
245
|
|
246
|
+
def update(self, *args: Any, **kwargs: Any) -> None:
|
247
|
+
with self:
|
248
|
+
super().update(*args, **kwargs)
|
249
|
+
|
250
|
+
def clear(self) -> None:
|
251
|
+
with self:
|
252
|
+
super().clear()
|
253
|
+
|
226
254
|
def __fspath__(self) -> str:
|
227
255
|
return str(self.path)
|
228
256
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from contextlib import suppress
|
2
|
-
from typing import Any, Sequence
|
2
|
+
from typing import Any, Mapping, Sequence
|
3
3
|
|
4
4
|
from ._base import FoamDictionaryBase
|
5
5
|
|
@@ -31,7 +31,7 @@ def _serialize_bool(value: Any) -> str:
|
|
31
31
|
|
32
32
|
def _serialize_list(value: Any) -> str:
|
33
33
|
if _is_sequence(value):
|
34
|
-
return f"({' '.join(
|
34
|
+
return f"({' '.join(_serialize_value(v) for v in value)})"
|
35
35
|
else:
|
36
36
|
raise TypeError(f"Not a valid sequence: {type(value)}")
|
37
37
|
|
@@ -73,14 +73,14 @@ def _serialize_dimensions(value: Any) -> str:
|
|
73
73
|
def _serialize_dimensioned(value: Any) -> str:
|
74
74
|
if isinstance(value, FoamDictionaryBase.Dimensioned):
|
75
75
|
if value.name is not None:
|
76
|
-
return f"{value.name} {_serialize_dimensions(value.dimensions)} {
|
76
|
+
return f"{value.name} {_serialize_dimensions(value.dimensions)} {_serialize_value(value.value)}"
|
77
77
|
else:
|
78
|
-
return f"{_serialize_dimensions(value.dimensions)} {
|
78
|
+
return f"{_serialize_dimensions(value.dimensions)} {_serialize_value(value.value)}"
|
79
79
|
else:
|
80
80
|
raise TypeError(f"Not a valid dimensioned value: {type(value)}")
|
81
81
|
|
82
82
|
|
83
|
-
def
|
83
|
+
def _serialize_value(
|
84
84
|
value: Any, *, assume_field: bool = False, assume_dimensions: bool = False
|
85
85
|
) -> str:
|
86
86
|
if isinstance(value, FoamDictionaryBase.DimensionSet) or assume_dimensions:
|
@@ -101,3 +101,23 @@ def serialize_value(
|
|
101
101
|
return _serialize_bool(value)
|
102
102
|
|
103
103
|
return str(value)
|
104
|
+
|
105
|
+
|
106
|
+
def _serialize_dictionary(value: Any) -> str:
|
107
|
+
if isinstance(value, Mapping):
|
108
|
+
return "\n".join(serialize_entry(k, v) for k, v in value.items())
|
109
|
+
else:
|
110
|
+
raise TypeError(f"Not a valid dictionary: {type(value)}")
|
111
|
+
|
112
|
+
|
113
|
+
def serialize_entry(
|
114
|
+
keyword: str,
|
115
|
+
value: Any,
|
116
|
+
*,
|
117
|
+
assume_field: bool = False,
|
118
|
+
assume_dimensions: bool = False,
|
119
|
+
) -> str:
|
120
|
+
try:
|
121
|
+
return f"{keyword}\n{{\n{_serialize_dictionary(value)}\n}}"
|
122
|
+
except TypeError:
|
123
|
+
return f"{keyword} {_serialize_value(value, assume_field=assume_field, assume_dimensions=assume_dimensions)};"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: foamlib
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.4
|
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
|
@@ -27,6 +27,7 @@ Description-Content-Type: text/markdown
|
|
27
27
|
License-File: LICENSE.txt
|
28
28
|
Requires-Dist: aioshutil <2,>=1
|
29
29
|
Requires-Dist: pyparsing <4,>=3
|
30
|
+
Requires-Dist: typing-extensions <5,>=4
|
30
31
|
Provides-Extra: docs
|
31
32
|
Requires-Dist: sphinx <8,>=7 ; extra == 'docs'
|
32
33
|
Requires-Dist: sphinx-rtd-theme ; extra == 'docs'
|
@@ -0,0 +1,14 @@
|
|
1
|
+
foamlib/__init__.py,sha256=BPC3la1UvhtGOS7utfBE5tccqz8mxqzd7Fn0zFC5yz0,287
|
2
|
+
foamlib/_cases.py,sha256=4f3c5BXnsHPhFvgXNjUcGGHyu7I0WZT6zxlvGhb9kMY,21213
|
3
|
+
foamlib/_subprocesses.py,sha256=5vqdQvpN_2v4GgDqxi-s88NGhZ6doFxkh0XY89ZWuHA,1926
|
4
|
+
foamlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
+
foamlib/_dictionaries/__init__.py,sha256=6UWBGe1t7cq-d6WWQrVm0Xpi7Whpkr-mkTWgAM4NwcE,160
|
6
|
+
foamlib/_dictionaries/_base.py,sha256=H8XfiaX1LD6OWwZ9m61SaKgI-_szF1udyEfiLurrCB8,1493
|
7
|
+
foamlib/_dictionaries/_files.py,sha256=1Ve1FG2VVKLyj6yZGe4Vy8EhEOtyORQtJMUK-cbPNt4,12424
|
8
|
+
foamlib/_dictionaries/_parsing.py,sha256=65kwMU6b4WmMngOR5ED8IBvMa59FQqTRmd9o0xPnWJM,4768
|
9
|
+
foamlib/_dictionaries/_serialization.py,sha256=viHpQKggSBfxq9V6veVcCCLNq7wdJ-2g5maecaN2beU,3612
|
10
|
+
foamlib-0.2.4.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
|
11
|
+
foamlib-0.2.4.dist-info/METADATA,sha256=Z5aFcGYwPssHy9DTrQqZ4Lsw6cJ1QjW9UFiqe0Uuf58,4640
|
12
|
+
foamlib-0.2.4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
13
|
+
foamlib-0.2.4.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
|
14
|
+
foamlib-0.2.4.dist-info/RECORD,,
|
foamlib-0.2.3.dist-info/RECORD
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
foamlib/__init__.py,sha256=VYMos2oCtIAGQx88R_0tco49MZogwcC6yvwQ2oqmSmU,287
|
2
|
-
foamlib/_cases.py,sha256=4f3c5BXnsHPhFvgXNjUcGGHyu7I0WZT6zxlvGhb9kMY,21213
|
3
|
-
foamlib/_subprocesses.py,sha256=5vqdQvpN_2v4GgDqxi-s88NGhZ6doFxkh0XY89ZWuHA,1926
|
4
|
-
foamlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
-
foamlib/_dictionaries/__init__.py,sha256=6UWBGe1t7cq-d6WWQrVm0Xpi7Whpkr-mkTWgAM4NwcE,160
|
6
|
-
foamlib/_dictionaries/_base.py,sha256=H8XfiaX1LD6OWwZ9m61SaKgI-_szF1udyEfiLurrCB8,1493
|
7
|
-
foamlib/_dictionaries/_files.py,sha256=baObt7Ewf_sM-9Y5JGMFCYK1CVdNQg3vYbOfjCgQA64,11582
|
8
|
-
foamlib/_dictionaries/_parsing.py,sha256=65kwMU6b4WmMngOR5ED8IBvMa59FQqTRmd9o0xPnWJM,4768
|
9
|
-
foamlib/_dictionaries/_serialization.py,sha256=P_eP46c-kCXx6rIGXL7hfDuEbS9h7uANZlgXsdcNwl8,3005
|
10
|
-
foamlib-0.2.3.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
|
11
|
-
foamlib-0.2.3.dist-info/METADATA,sha256=DA7Kq6YIun5m2yisx_F4DSrYP13RZKgXwq0mTTX2y9A,4600
|
12
|
-
foamlib-0.2.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
13
|
-
foamlib-0.2.3.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
|
14
|
-
foamlib-0.2.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|