foamlib 0.2.9__py3-none-any.whl → 0.3.0__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.
@@ -0,0 +1,195 @@
1
+ import sys
2
+ from typing import Tuple, Union
3
+
4
+ if sys.version_info >= (3, 9):
5
+ from collections.abc import Iterator, Mapping, MutableMapping, Sequence
6
+ else:
7
+ from typing import Iterator, Mapping, MutableMapping, Sequence
8
+
9
+ if sys.version_info >= (3, 10):
10
+ from types import EllipsisType
11
+ else:
12
+ from typing import Any as EllipsisType
13
+
14
+ from pyparsing import (
15
+ Dict,
16
+ Forward,
17
+ Group,
18
+ Keyword,
19
+ LineEnd,
20
+ Literal,
21
+ Located,
22
+ Opt,
23
+ ParserElement,
24
+ ParseResults,
25
+ QuotedString,
26
+ Word,
27
+ c_style_comment,
28
+ common,
29
+ cpp_style_comment,
30
+ identbodychars,
31
+ printables,
32
+ )
33
+
34
+ from ._base import FoamDict
35
+
36
+
37
+ def _list_of(entry: ParserElement) -> ParserElement:
38
+ return Opt(
39
+ Literal("List") + Literal("<") + common.identifier + Literal(">")
40
+ ).suppress() + (
41
+ (
42
+ Opt(common.integer).suppress()
43
+ + (
44
+ Literal("(").suppress()
45
+ + Group((entry)[...], aslist=True)
46
+ + Literal(")").suppress()
47
+ )
48
+ )
49
+ | (
50
+ common.integer + Literal("{").suppress() + entry + Literal("}").suppress()
51
+ ).set_parse_action(lambda tks: [[tks[1]] * tks[0]])
52
+ )
53
+
54
+
55
+ def _dictionary_of(
56
+ keyword: ParserElement,
57
+ data_entries: ParserElement,
58
+ *,
59
+ len: Union[int, EllipsisType] = ...,
60
+ located: bool = False,
61
+ ) -> ParserElement:
62
+ subdict = Forward()
63
+
64
+ keyword_entry = keyword + (
65
+ (Literal("{").suppress() + subdict + Literal("}").suppress())
66
+ | (data_entries + Literal(";").suppress())
67
+ )
68
+
69
+ if located:
70
+ keyword_entry = Located(keyword_entry)
71
+
72
+ subdict <<= Dict(Group(keyword_entry)[...], asdict=not located)
73
+
74
+ return Dict(Group(keyword_entry)[len], asdict=not located)
75
+
76
+
77
+ _SWITCH = (
78
+ Keyword("yes") | Keyword("true") | Keyword("on") | Keyword("y") | Keyword("t")
79
+ ).set_parse_action(lambda: True) | (
80
+ Keyword("no") | Keyword("false") | Keyword("off") | Keyword("n") | Keyword("f")
81
+ ).set_parse_action(lambda: False)
82
+ _DIMENSIONS = (
83
+ Literal("[").suppress() + common.number * 7 + Literal("]").suppress()
84
+ ).set_parse_action(lambda tks: FoamDict.DimensionSet(*tks))
85
+ _TENSOR = _list_of(common.number) | common.number
86
+ _IDENTIFIER = Word(identbodychars + "$", printables.replace(";", ""))
87
+ _DIMENSIONED = (Opt(_IDENTIFIER) + _DIMENSIONS + _TENSOR).set_parse_action(
88
+ lambda tks: FoamDict.Dimensioned(*reversed(tks.as_list()))
89
+ )
90
+ _FIELD = (Keyword("uniform").suppress() + _TENSOR) | (
91
+ Keyword("nonuniform").suppress() + _list_of(_TENSOR)
92
+ )
93
+ _TOKEN = QuotedString('"', unquote_results=False) | _IDENTIFIER
94
+ _DATA = Forward()
95
+ _KEYWORD_ENTRY = _dictionary_of(_TOKEN, _DATA, len=1)
96
+ _DATA_ENTRY = Forward()
97
+ _LIST_ENTRY = _KEYWORD_ENTRY | _DATA_ENTRY
98
+ _LIST = _list_of(_LIST_ENTRY)
99
+ _DATA_ENTRY <<= (
100
+ _FIELD | _LIST | _DIMENSIONED | _DIMENSIONS | common.number | _SWITCH | _TOKEN
101
+ )
102
+
103
+ _DATA <<= _DATA_ENTRY[1, ...].set_parse_action(
104
+ lambda tks: tuple(tks) if len(tks) > 1 else [tks[0]]
105
+ )
106
+
107
+ _FILE = (
108
+ _dictionary_of(_TOKEN, Opt(_DATA, default=""), located=True)
109
+ .ignore(c_style_comment)
110
+ .ignore(cpp_style_comment)
111
+ .ignore(Literal("#include") + ... + LineEnd()) # type: ignore [no-untyped-call]
112
+ )
113
+
114
+
115
+ class Parsed(Mapping[Tuple[str, ...], Union[FoamDict.Data, EllipsisType]]):
116
+ def __init__(self, contents: str) -> None:
117
+ self._parsed: MutableMapping[
118
+ Tuple[str, ...],
119
+ Tuple[int, Union[FoamDict.Data, EllipsisType], int],
120
+ ] = {}
121
+ for parse_result in _FILE.parse_string(contents, parse_all=True):
122
+ self._parsed.update(self._flatten_result(parse_result))
123
+
124
+ @staticmethod
125
+ def _flatten_result(
126
+ parse_result: ParseResults, *, _keywords: Tuple[str, ...] = ()
127
+ ) -> Mapping[Tuple[str, ...], Tuple[int, Union[FoamDict.Data, EllipsisType], int]]:
128
+ ret: MutableMapping[
129
+ Tuple[str, ...],
130
+ Tuple[int, Union[FoamDict.Data, EllipsisType], int],
131
+ ] = {}
132
+ start = parse_result.locn_start
133
+ assert isinstance(start, int)
134
+ item = parse_result.value
135
+ assert isinstance(item, Sequence)
136
+ end = parse_result.locn_end
137
+ assert isinstance(end, int)
138
+ keyword, *data = item
139
+ assert isinstance(keyword, str)
140
+ ret[(*_keywords, keyword)] = (start, ..., end)
141
+ for d in data:
142
+ if isinstance(d, ParseResults):
143
+ ret.update(Parsed._flatten_result(d, _keywords=(*_keywords, keyword)))
144
+ else:
145
+ ret[(*_keywords, keyword)] = (start, d, end)
146
+ return ret
147
+
148
+ def __getitem__(
149
+ self, keywords: Tuple[str, ...]
150
+ ) -> Union[FoamDict.Data, EllipsisType]:
151
+ _, data, _ = self._parsed[keywords]
152
+ return data
153
+
154
+ def __contains__(self, keywords: object) -> bool:
155
+ return keywords in self._parsed
156
+
157
+ def __iter__(self) -> Iterator[Tuple[str, ...]]:
158
+ return iter(self._parsed)
159
+
160
+ def __len__(self) -> int:
161
+ return len(self._parsed)
162
+
163
+ def entry_location(
164
+ self, keywords: Tuple[str, ...], *, missing_ok: bool = False
165
+ ) -> Tuple[int, int]:
166
+ try:
167
+ start, _, end = self._parsed[keywords]
168
+ except KeyError:
169
+ if missing_ok:
170
+ if len(keywords) > 1:
171
+ _, _, end = self._parsed[keywords[:-1]]
172
+ end -= 1
173
+ else:
174
+ end = -1
175
+
176
+ start = end
177
+ else:
178
+ raise
179
+
180
+ return start, end
181
+
182
+ def as_dict(self) -> FoamDict._Dict:
183
+ ret: FoamDict._Dict = {}
184
+ for keywords, (_, data, _) in self._parsed.items():
185
+ r = ret
186
+ for k in keywords[:-1]:
187
+ assert isinstance(r, dict)
188
+ v = r[k]
189
+ assert isinstance(v, dict)
190
+ r = v
191
+
192
+ assert isinstance(r, dict)
193
+ r[keywords[-1]] = {} if data is ... else data # type: ignore [assignment]
194
+
195
+ return ret
@@ -0,0 +1,156 @@
1
+ import sys
2
+ from contextlib import suppress
3
+
4
+ if sys.version_info >= (3, 9):
5
+ from collections.abc import Mapping
6
+ else:
7
+ from typing import Mapping
8
+
9
+ from .._util import is_sequence
10
+ from ._base import FoamDict
11
+
12
+
13
+ def _serialize_switch(data: FoamDict._SetData) -> str:
14
+ if data is True:
15
+ return "yes"
16
+ elif data is False:
17
+ return "no"
18
+ else:
19
+ raise TypeError(f"Not a bool: {type(data)}")
20
+
21
+
22
+ def _serialize_list(
23
+ data: FoamDict._SetData,
24
+ ) -> str:
25
+ if is_sequence(data):
26
+ return f"({' '.join(_serialize_data_entry(v) for v in data)})"
27
+ else:
28
+ raise TypeError(f"Not a valid sequence: {type(data)}")
29
+
30
+
31
+ def _serialize_field(
32
+ data: FoamDict._SetData,
33
+ ) -> str:
34
+ if is_sequence(data):
35
+ try:
36
+ s = _serialize_list(data)
37
+ except TypeError:
38
+ raise TypeError(f"Not a valid field: {type(data)}") from None
39
+ else:
40
+ if not is_sequence(data[0]) and len(data) < 10:
41
+ return f"uniform {s}"
42
+ else:
43
+ if not is_sequence(data[0]):
44
+ kind = "scalar"
45
+ elif len(data[0]) == 3:
46
+ kind = "vector"
47
+ elif len(data[0]) == 6:
48
+ kind = "symmTensor"
49
+ elif len(data[0]) == 9:
50
+ kind = "tensor"
51
+ else:
52
+ raise TypeError(
53
+ f"Unsupported sequence length for field: {len(data[0])}"
54
+ )
55
+ return f"nonuniform List<{kind}> {len(data)}{s}"
56
+ else:
57
+ return f"uniform {data}"
58
+
59
+
60
+ def _serialize_dimensions(
61
+ data: FoamDict._SetData,
62
+ ) -> str:
63
+ if is_sequence(data) and len(data) == 7:
64
+ return f"[{' '.join(str(v) for v in data)}]"
65
+ else:
66
+ raise TypeError(f"Not a valid dimension set: {type(data)}")
67
+
68
+
69
+ def _serialize_dimensioned(
70
+ data: FoamDict._SetData,
71
+ ) -> str:
72
+ if isinstance(data, FoamDict.Dimensioned):
73
+ if data.name is not None:
74
+ return f"{data.name} {_serialize_dimensions(data.dimensions)} {_serialize_data_entry(data.value)}"
75
+ else:
76
+ return f"{_serialize_dimensions(data.dimensions)} {_serialize_data_entry(data.value)}"
77
+ else:
78
+ raise TypeError(f"Not a valid dimensioned value: {type(data)}")
79
+
80
+
81
+ def _serialize_data_entry(
82
+ data: FoamDict._SetData,
83
+ *,
84
+ assume_field: bool = False,
85
+ assume_dimensions: bool = False,
86
+ ) -> str:
87
+ if isinstance(data, FoamDict.DimensionSet) or assume_dimensions:
88
+ with suppress(TypeError):
89
+ return _serialize_dimensions(data)
90
+
91
+ if assume_field:
92
+ with suppress(TypeError):
93
+ return _serialize_field(data)
94
+
95
+ with suppress(TypeError):
96
+ return _serialize_dimensioned(data)
97
+
98
+ with suppress(TypeError):
99
+ return _serialize_list(data)
100
+
101
+ with suppress(TypeError):
102
+ return _serialize_switch(data)
103
+
104
+ with suppress(TypeError):
105
+ return _serialize_dictionary(data)
106
+
107
+ return str(data)
108
+
109
+
110
+ def _serialize_data_entries(
111
+ data: FoamDict._SetData,
112
+ *,
113
+ assume_field: bool = False,
114
+ assume_dimensions: bool = False,
115
+ ) -> str:
116
+ if isinstance(data, FoamDict.DimensionSet) or assume_dimensions:
117
+ with suppress(TypeError):
118
+ return _serialize_dimensions(data)
119
+
120
+ if assume_field:
121
+ with suppress(TypeError):
122
+ return _serialize_field(data)
123
+
124
+ if isinstance(data, tuple):
125
+ return " ".join(_serialize_data_entry(v) for v in data)
126
+
127
+ return _serialize_data_entry(data)
128
+
129
+
130
+ def _serialize_dictionary(
131
+ data: FoamDict._SetData,
132
+ ) -> str:
133
+ if isinstance(data, Mapping):
134
+ return "\n".join(serialize_keyword_entry(k, v) for k, v in data.items())
135
+ else:
136
+ raise TypeError(f"Not a valid dictionary: {type(data)}")
137
+
138
+
139
+ def serialize_keyword_entry(
140
+ keyword: str,
141
+ data: FoamDict._SetData,
142
+ *,
143
+ assume_field: bool = False,
144
+ assume_dimensions: bool = False,
145
+ ) -> str:
146
+ with suppress(TypeError):
147
+ return f"{keyword}\n{{\n{_serialize_dictionary(data)}\n}}"
148
+
149
+ data = _serialize_data_entries(
150
+ data, assume_field=assume_field, assume_dimensions=assume_dimensions
151
+ )
152
+
153
+ if not data:
154
+ return f"{keyword};"
155
+ else:
156
+ return f"{keyword} {data};"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: foamlib
3
- Version: 0.2.9
3
+ Version: 0.3.0
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
@@ -0,0 +1,16 @@
1
+ foamlib/__init__.py,sha256=erRnbigN4XBPDC0ykv-Lw7LVsw_xtuJ7h0tgkBTNQZ8,381
2
+ foamlib/_cases.py,sha256=SkUthKb98zXPMYACaGyfGC0Fo1jzD6cC4qEGesHfNfc,20554
3
+ foamlib/_util.py,sha256=PBTpBwt_j1GXASncSDZUR8pH2u_h8UyJXm8GeFKebTY,2552
4
+ foamlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ foamlib/_files/__init__.py,sha256=m4y_7wFV2Voly1aJrTYALjT3S1Aq7EbaijxdGFbJrmU,160
6
+ foamlib/_files/_base.py,sha256=vONemjJA-NxRuIjuxwz8PynjtF1UImrfBQm1EbgZEec,1768
7
+ foamlib/_files/_fields.py,sha256=jZZiMoBn0tixGnUGpITpRxcauqhPvYk65PIktBFvEHk,5073
8
+ foamlib/_files/_files.py,sha256=1fV1TUwtNsxzt1R1YKMbB_AGpjMl-W-7YQXl7Ynoyzc,6025
9
+ foamlib/_files/_io.py,sha256=alxMyxQh0zb6BZYqomZwOo9dQujMpRuS5yfpIKBEnaM,1976
10
+ foamlib/_files/_parsing.py,sha256=blyt1kpYruoW5I6DMDg8jhg6f5oz7gzedmAImuJ5b4k,5966
11
+ foamlib/_files/_serialization.py,sha256=kbl1OTvWqHwcDwS2k5CuqjDRmiv3NpA9hIXyv4boWBA,4268
12
+ foamlib-0.3.0.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
13
+ foamlib-0.3.0.dist-info/METADATA,sha256=hl5EKAs6_mbW-1qcuIFst4I6tDQqCkG4LyZlx3DMhZY,4650
14
+ foamlib-0.3.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
15
+ foamlib-0.3.0.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
16
+ foamlib-0.3.0.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- from ._base import FoamDictionaryBase
2
- from ._files import FoamFieldFile, FoamFile
3
-
4
- __all__ = [
5
- "FoamFile",
6
- "FoamFieldFile",
7
- "FoamDictionaryBase",
8
- ]