foamlib 0.2.6__tar.gz → 0.2.8__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: foamlib
3
- Version: 0.2.6
3
+ Version: 0.2.8
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
@@ -1,6 +1,6 @@
1
1
  """A Python interface for interacting with OpenFOAM."""
2
2
 
3
- __version__ = "0.2.6"
3
+ __version__ = "0.2.8"
4
4
 
5
5
  from ._cases import AsyncFoamCase, FoamCase, FoamCaseBase
6
6
  from ._dictionaries import FoamDictionaryBase, FoamFieldFile, FoamFile
@@ -4,9 +4,15 @@ from dataclasses import dataclass
4
4
  from typing import Dict, NamedTuple, Optional, Union
5
5
 
6
6
  if sys.version_info >= (3, 9):
7
- from collections.abc import Sequence
7
+ from collections.abc import Mapping, Sequence
8
8
  else:
9
- from typing import Sequence
9
+ from typing import Mapping, Sequence
10
+
11
+ try:
12
+ import numpy as np
13
+ from numpy.typing import NDArray
14
+ except ModuleNotFoundError:
15
+ pass
10
16
 
11
17
 
12
18
  class FoamDictionaryBase:
@@ -34,14 +40,25 @@ class FoamDictionaryBase:
34
40
  if not isinstance(self.dimensions, FoamDictionaryBase.DimensionSet):
35
41
  self.dimensions = FoamDictionaryBase.DimensionSet(*self.dimensions)
36
42
 
37
- Value = Union[str, int, float, bool, Dimensioned, DimensionSet, Sequence["Value"]]
43
+ Value = Union[
44
+ str,
45
+ int,
46
+ float,
47
+ bool,
48
+ Dimensioned,
49
+ DimensionSet,
50
+ Sequence["Value"],
51
+ Mapping[str, "Value"],
52
+ ]
38
53
  """
39
54
  A value that can be stored in an OpenFOAM dictionary.
40
55
  """
41
56
 
42
- _Dict = Dict[str, Union["FoamDictionaryBase.Value", "_Dict"]]
57
+ _Dict = Dict[str, Union["Value", "_Dict"]]
43
58
 
44
59
  @abstractmethod
45
60
  def as_dict(self) -> _Dict:
46
61
  """Return a nested dict representation of the dictionary."""
47
62
  raise NotImplementedError
63
+
64
+ _SetValue = Union[Value, "NDArray[np.generic]"]
@@ -1,9 +1,11 @@
1
1
  import sys
2
2
  from pathlib import Path
3
+ from types import TracebackType
3
4
  from typing import (
4
5
  Any,
5
6
  Optional,
6
7
  Tuple,
8
+ Type,
7
9
  Union,
8
10
  cast,
9
11
  )
@@ -48,7 +50,12 @@ class _FoamFileBase:
48
50
  self.__defer_io += 1
49
51
  return self
50
52
 
51
- def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
53
+ def __exit__(
54
+ self,
55
+ exc_type: Optional[Type[BaseException]],
56
+ exc_val: Optional[BaseException],
57
+ exc_tb: Optional[TracebackType],
58
+ ) -> None:
52
59
  self.__defer_io -= 1
53
60
  if self.__defer_io == 0 and self.__dirty:
54
61
  assert self.__contents is not None
@@ -124,7 +131,7 @@ class FoamFile(
124
131
  assume_dimensions=assume_dimensions,
125
132
  )
126
133
 
127
- def __setitem__(self, keyword: str, value: Any) -> None:
134
+ def __setitem__(self, keyword: str, value: "FoamFile._SetValue") -> None:
128
135
  self._setitem(keyword, value)
129
136
 
130
137
  def __delitem__(self, keyword: str) -> None:
@@ -180,7 +187,7 @@ class FoamFile(
180
187
  def _setitem(
181
188
  self,
182
189
  keywords: Union[str, Tuple[str, ...]],
183
- value: Any,
190
+ value: "FoamFile._SetValue",
184
191
  *,
185
192
  assume_field: bool = False,
186
193
  assume_dimensions: bool = False,
@@ -210,7 +217,11 @@ class FoamFile(
210
217
  f"{contents[:start]}\n{serialize_entry(keywords[-1], value, assume_field=assume_field, assume_dimensions=assume_dimensions)}\n{contents[end:]}"
211
218
  )
212
219
 
213
- def __setitem__(self, keywords: Union[str, Tuple[str, ...]], value: Any) -> None:
220
+ def __setitem__(
221
+ self,
222
+ keywords: Union[str, Tuple[str, ...]],
223
+ value: "FoamFile._SetValue",
224
+ ) -> None:
214
225
  self._setitem(keywords, value)
215
226
 
216
227
  def __delitem__(self, keywords: Union[str, Tuple[str, ...]]) -> None:
@@ -269,12 +280,20 @@ class FoamFieldFile(FoamFile):
269
280
 
270
281
  class BoundariesDictionary(FoamFile.Dictionary):
271
282
  def __getitem__(self, keyword: str) -> "FoamFieldFile.BoundaryDictionary":
272
- return cast(FoamFieldFile.BoundaryDictionary, super().__getitem__(keyword))
283
+ value = super().__getitem__(keyword)
284
+ if not isinstance(value, FoamFieldFile.BoundaryDictionary):
285
+ assert not isinstance(value, FoamFile.Dictionary)
286
+ raise TypeError(f"boundary {keyword} is not a dictionary")
287
+ return value
273
288
 
274
289
  class BoundaryDictionary(FoamFile.Dictionary):
275
290
  """An OpenFOAM dictionary representing a boundary condition as a mutable mapping."""
276
291
 
277
- def __setitem__(self, key: str, value: Any) -> None:
292
+ def __setitem__(
293
+ self,
294
+ key: str,
295
+ value: FoamFile._SetValue,
296
+ ) -> None:
278
297
  if key == "value":
279
298
  self._setitem(key, value, assume_field=True)
280
299
  else:
@@ -1,11 +1,16 @@
1
1
  import sys
2
- from typing import Optional, Tuple
2
+ from typing import Optional, Tuple, Union
3
3
 
4
4
  if sys.version_info >= (3, 9):
5
5
  from collections.abc import Mapping, MutableMapping, Sequence
6
6
  else:
7
7
  from typing import Mapping, MutableMapping, Sequence
8
8
 
9
+ if sys.version_info >= (3, 10):
10
+ from types import EllipsisType
11
+ else:
12
+ from typing import Any as EllipsisType
13
+
9
14
  from pyparsing import (
10
15
  Dict,
11
16
  Forward,
@@ -56,6 +61,28 @@ def _list_of(elem: ParserElement) -> ParserElement:
56
61
  )
57
62
 
58
63
 
64
+ def _dictionary_of(
65
+ keyword: ParserElement,
66
+ value: ParserElement,
67
+ *,
68
+ len: Union[int, EllipsisType] = ...,
69
+ located: bool = False,
70
+ ) -> ParserElement:
71
+ subdict = Forward()
72
+
73
+ entry = keyword + (
74
+ (Literal("{").suppress() + subdict + Literal("}").suppress())
75
+ | (value + Literal(";").suppress())
76
+ )
77
+
78
+ if located:
79
+ entry = Located(entry)
80
+
81
+ subdict <<= Dict(Group(entry)[...], asdict=not located)
82
+
83
+ return Dict(Group(entry)[len], asdict=not located)
84
+
85
+
59
86
  _TENSOR = _list_of(common.number) | common.number
60
87
  _IDENTIFIER = Word(identbodychars + "$", printables.replace(";", ""))
61
88
  _DIMENSIONED = (Opt(_IDENTIFIER) + _DIMENSIONS + _TENSOR).set_parse_action(
@@ -66,25 +93,19 @@ _FIELD = (Keyword("uniform").suppress() + _TENSOR) | (
66
93
  )
67
94
  _TOKEN = QuotedString('"', unquote_results=False) | _IDENTIFIER
68
95
  _ITEM = Forward()
69
- _LIST = _list_of(_ITEM)
96
+ _ENTRY = _dictionary_of(_IDENTIFIER, _ITEM, len=1)
97
+ _LIST = _list_of(_ENTRY | _ITEM)
70
98
  _ITEM <<= _FIELD | _LIST | _DIMENSIONED | _DIMENSIONS | common.number | _SWITCH | _TOKEN
99
+
71
100
  _TOKENS = (
72
101
  QuotedString('"', unquote_results=False) | Word(printables.replace(";", ""))
73
102
  )[2, ...].set_parse_action(lambda tks: " ".join(tks))
74
103
 
75
104
  _VALUE = _ITEM ^ _TOKENS
76
105
 
77
- _ENTRY = Forward()
78
- _DICTIONARY = Dict(Group(_ENTRY)[...])
79
- _ENTRY <<= Located(
80
- _TOKEN
81
- + (
82
- (Literal("{").suppress() + _DICTIONARY + Literal("}").suppress())
83
- | (Opt(_VALUE, default="") + Literal(";").suppress())
84
- )
85
- )
86
106
  _FILE = (
87
- _DICTIONARY.ignore(c_style_comment)
107
+ _dictionary_of(_TOKEN, Opt(_VALUE, default=""), located=True)
108
+ .ignore(c_style_comment)
88
109
  .ignore(cpp_style_comment)
89
110
  .ignore(Literal("#include") + ... + LineEnd()) # type: ignore [no-untyped-call]
90
111
  )
@@ -1,6 +1,5 @@
1
1
  import sys
2
2
  from contextlib import suppress
3
- from typing import Any
4
3
 
5
4
  if sys.version_info >= (3, 9):
6
5
  from collections.abc import Mapping
@@ -11,7 +10,7 @@ from .._util import is_sequence
11
10
  from ._base import FoamDictionaryBase
12
11
 
13
12
 
14
- def _serialize_switch(value: Any) -> str:
13
+ def _serialize_switch(value: FoamDictionaryBase._SetValue) -> str:
15
14
  if value is True:
16
15
  return "yes"
17
16
  elif value is False:
@@ -20,14 +19,18 @@ def _serialize_switch(value: Any) -> str:
20
19
  raise TypeError(f"Not a bool: {type(value)}")
21
20
 
22
21
 
23
- def _serialize_list(value: Any) -> str:
22
+ def _serialize_list(
23
+ value: FoamDictionaryBase._SetValue,
24
+ ) -> str:
24
25
  if is_sequence(value):
25
26
  return f"({' '.join(_serialize_value(v) for v in value)})"
26
27
  else:
27
28
  raise TypeError(f"Not a valid sequence: {type(value)}")
28
29
 
29
30
 
30
- def _serialize_field(value: Any) -> str:
31
+ def _serialize_field(
32
+ value: FoamDictionaryBase._SetValue,
33
+ ) -> str:
31
34
  if is_sequence(value):
32
35
  try:
33
36
  s = _serialize_list(value)
@@ -54,14 +57,18 @@ def _serialize_field(value: Any) -> str:
54
57
  return f"uniform {value}"
55
58
 
56
59
 
57
- def _serialize_dimensions(value: Any) -> str:
60
+ def _serialize_dimensions(
61
+ value: FoamDictionaryBase._SetValue,
62
+ ) -> str:
58
63
  if is_sequence(value) and len(value) == 7:
59
64
  return f"[{' '.join(str(v) for v in value)}]"
60
65
  else:
61
66
  raise TypeError(f"Not a valid dimension set: {type(value)}")
62
67
 
63
68
 
64
- def _serialize_dimensioned(value: Any) -> str:
69
+ def _serialize_dimensioned(
70
+ value: FoamDictionaryBase._SetValue,
71
+ ) -> str:
65
72
  if isinstance(value, FoamDictionaryBase.Dimensioned):
66
73
  if value.name is not None:
67
74
  return f"{value.name} {_serialize_dimensions(value.dimensions)} {_serialize_value(value.value)}"
@@ -72,7 +79,10 @@ def _serialize_dimensioned(value: Any) -> str:
72
79
 
73
80
 
74
81
  def _serialize_value(
75
- value: Any, *, assume_field: bool = False, assume_dimensions: bool = False
82
+ value: FoamDictionaryBase._SetValue,
83
+ *,
84
+ assume_field: bool = False,
85
+ assume_dimensions: bool = False,
76
86
  ) -> str:
77
87
  if isinstance(value, FoamDictionaryBase.DimensionSet) or assume_dimensions:
78
88
  with suppress(TypeError):
@@ -91,10 +101,15 @@ def _serialize_value(
91
101
  with suppress(TypeError):
92
102
  return _serialize_switch(value)
93
103
 
104
+ with suppress(TypeError):
105
+ return _serialize_dictionary(value)
106
+
94
107
  return str(value)
95
108
 
96
109
 
97
- def _serialize_dictionary(value: Any) -> str:
110
+ def _serialize_dictionary(
111
+ value: FoamDictionaryBase._SetValue,
112
+ ) -> str:
98
113
  if isinstance(value, Mapping):
99
114
  return "\n".join(serialize_entry(k, v) for k, v in value.items())
100
115
  else:
@@ -103,7 +118,7 @@ def _serialize_dictionary(value: Any) -> str:
103
118
 
104
119
  def serialize_entry(
105
120
  keyword: str,
106
- value: Any,
121
+ value: FoamDictionaryBase._SetValue,
107
122
  *,
108
123
  assume_field: bool = False,
109
124
  assume_dimensions: bool = False,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: foamlib
3
- Version: 0.2.6
3
+ Version: 0.2.8
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
@@ -14,5 +14,4 @@ foamlib/_dictionaries/__init__.py
14
14
  foamlib/_dictionaries/_base.py
15
15
  foamlib/_dictionaries/_files.py
16
16
  foamlib/_dictionaries/_parsing.py
17
- foamlib/_dictionaries/_serialization.py
18
- tests/test_serialization.py
17
+ foamlib/_dictionaries/_serialization.py
@@ -1,52 +0,0 @@
1
- from foamlib import FoamFile
2
- from foamlib._dictionaries._serialization import _serialize_value
3
-
4
-
5
- def test_serialize_value() -> None:
6
- assert _serialize_value(1) == "1"
7
- assert _serialize_value(1.0) == "1.0"
8
- assert _serialize_value(1.0e-3) == "0.001"
9
- assert _serialize_value(True) == "yes"
10
- assert _serialize_value(False) == "no"
11
- assert _serialize_value("word") == "word"
12
- assert _serialize_value("word word") == "word word"
13
- assert _serialize_value('"a string"') == '"a string"'
14
- assert _serialize_value(1, assume_field=True) == "uniform 1"
15
- assert _serialize_value(1.0, assume_field=True) == "uniform 1.0"
16
- assert _serialize_value(1.0e-3, assume_field=True) == "uniform 0.001"
17
- assert _serialize_value([1.0, 2.0, 3.0]) == "(1.0 2.0 3.0)"
18
- assert _serialize_value([1, 2, 3], assume_field=True) == "uniform (1 2 3)"
19
- assert (
20
- _serialize_value([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], assume_field=True)
21
- == "nonuniform List<scalar> 10(1 2 3 4 5 6 7 8 9 10)"
22
- )
23
- assert (
24
- _serialize_value([[1, 2, 3], [4, 5, 6]], assume_field=True)
25
- == "nonuniform List<vector> 2((1 2 3) (4 5 6))"
26
- )
27
- assert (
28
- _serialize_value(FoamFile.DimensionSet(mass=1, length=1, time=-2))
29
- == "[1 1 -2 0 0 0 0]"
30
- )
31
- assert (
32
- _serialize_value(
33
- FoamFile.Dimensioned(
34
- name="g",
35
- dimensions=FoamFile.DimensionSet(mass=1, length=1, time=-2),
36
- value=9.81,
37
- )
38
- )
39
- == "g [1 1 -2 0 0 0 0] 9.81"
40
- )
41
- assert (
42
- _serialize_value(
43
- FoamFile.Dimensioned(
44
- dimensions=FoamFile.DimensionSet(mass=1, length=1, time=-2), value=9.81
45
- )
46
- )
47
- == "[1 1 -2 0 0 0 0] 9.81"
48
- )
49
- assert (
50
- _serialize_value("hex (0 1 2 3 4 5 6 7) (1 1 1) simpleGrading (1 1 1)")
51
- == "hex (0 1 2 3 4 5 6 7) (1 1 1) simpleGrading (1 1 1)"
52
- )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes