foamlib 0.6.12__py3-none-any.whl → 0.6.14__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.12"
3
+ __version__ = "0.6.14"
4
4
 
5
5
  from ._cases import (
6
6
  AsyncFoamCase,
foamlib/_files/_files.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import os
3
4
  import sys
4
5
  from copy import deepcopy
5
6
  from typing import Any, Optional, Tuple, Union, cast
@@ -16,7 +17,7 @@ else:
16
17
 
17
18
  from ._base import FoamFileBase
18
19
  from ._io import FoamFileIO
19
- from ._serialization import Kind, dumps
20
+ from ._serialization import Kind, dumps, normalize
20
21
  from ._util import is_sequence
21
22
 
22
23
 
@@ -216,12 +217,28 @@ class FoamFile(
216
217
  or keywords[2].endswith("Gradient")
217
218
  )
218
219
  ):
219
- kind = Kind.BINARY_FIELD if self.format == "binary" else Kind.FIELD
220
+ if self.format == "binary":
221
+ arch = self.get(("FoamFile", "arch"), default=None)
222
+ assert arch is None or isinstance(arch, str)
223
+ if (arch is not None and "scalar=32" in arch) or (
224
+ arch is None
225
+ and os.environ.get("WM_PRECISION_OPTION", default="DP") == "SP"
226
+ ):
227
+ kind = Kind.SINGLE_PRECISION_BINARY_FIELD
228
+ else:
229
+ kind = Kind.DOUBLE_PRECISION_BINARY_FIELD
230
+ else:
231
+ kind = Kind.ASCII_FIELD
220
232
  elif keywords == ("dimensions",):
221
233
  kind = Kind.DIMENSIONS
222
234
 
223
235
  if (
224
- kind in (Kind.FIELD, Kind.BINARY_FIELD)
236
+ kind
237
+ in (
238
+ Kind.ASCII_FIELD,
239
+ Kind.DOUBLE_PRECISION_BINARY_FIELD,
240
+ Kind.SINGLE_PRECISION_BINARY_FIELD,
241
+ )
225
242
  ) and self.class_ == "dictionary":
226
243
  if isinstance(data, (int, float)):
227
244
  self.class_ = "volScalarField"
@@ -291,7 +308,7 @@ class FoamFile(
291
308
  elif keywords:
292
309
  parsed.put(
293
310
  keywords,
294
- deepcopy(data),
311
+ normalize(data, kind=kind),
295
312
  before
296
313
  + indentation
297
314
  + dumps(keywords[-1])
@@ -302,7 +319,11 @@ class FoamFile(
302
319
  )
303
320
 
304
321
  else:
305
- parsed.put((), deepcopy(data), before + dumps(data, kind=kind) + after)
322
+ parsed.put(
323
+ (),
324
+ normalize(data, kind=kind),
325
+ before + dumps(data, kind=kind) + after,
326
+ )
306
327
 
307
328
  def __delitem__(self, keywords: str | tuple[str, ...] | None) -> None:
308
329
  if not keywords:
@@ -29,7 +29,6 @@ from pyparsing import (
29
29
  ParseResults,
30
30
  QuotedString,
31
31
  Word,
32
- c_style_comment,
33
32
  common,
34
33
  counted_array,
35
34
  cpp_style_comment,
@@ -41,9 +40,7 @@ from ._base import FoamFileBase
41
40
 
42
41
 
43
42
  def _list_of(entry: ParserElement) -> ParserElement:
44
- return Opt(
45
- Literal("List") + Literal("<") + common.identifier + Literal(">")
46
- ).suppress() + (
43
+ return (
47
44
  (
48
45
  counted_array(entry, common.integer + Literal("(").suppress())
49
46
  + Literal(")").suppress()
@@ -82,10 +79,12 @@ def _keyword_entry_of(
82
79
 
83
80
  def _unpack_binary_field(
84
81
  tks: ParseResults,
82
+ *,
83
+ elsize: int = 1,
85
84
  ) -> Sequence[Sequence[float] | Sequence[Sequence[float]]]:
86
- elsize = len(tks[0]) // 8
85
+ float_size = len(tks[0]) // elsize
87
86
 
88
- arr = array.array("d", "".join(tks).encode("latin-1"))
87
+ arr = array.array("f" if float_size == 4 else "d", "".join(tks).encode("latin-1"))
89
88
 
90
89
  values: Sequence[float] | Sequence[Sequence[float]]
91
90
 
@@ -122,7 +121,13 @@ _SWITCH = (
122
121
  _DIMENSIONS = (
123
122
  Literal("[").suppress() + common.number[0, 7] + Literal("]").suppress()
124
123
  ).set_parse_action(lambda tks: FoamFileBase.DimensionSet(*tks))
125
- _TENSOR = _list_of(common.number) | common.number
124
+ _TENSOR = common.ieee_float | (
125
+ Literal("(").suppress()
126
+ + Group(
127
+ common.ieee_float[9] | common.ieee_float[6] | common.ieee_float[3], aslist=True
128
+ )
129
+ + Literal(")").suppress()
130
+ )
126
131
  _IDENTIFIER = Combine(
127
132
  Word(_IDENTCHARS, _IDENTBODYCHARS, exclude_chars="()")
128
133
  + Opt(Literal("(") + Word(_IDENTBODYCHARS, exclude_chars="()") + Literal(")"))
@@ -130,45 +135,121 @@ _IDENTIFIER = Combine(
130
135
  _DIMENSIONED = (Opt(_IDENTIFIER) + _DIMENSIONS + _TENSOR).set_parse_action(
131
136
  lambda tks: FoamFileBase.Dimensioned(*reversed(tks.as_list()))
132
137
  )
133
- _FIELD = (Keyword("uniform").suppress() + _TENSOR) | (
134
- Keyword("nonuniform").suppress()
138
+ _FIELD = (Keyword("uniform", _IDENTBODYCHARS).suppress() + _TENSOR) | (
139
+ Keyword("nonuniform", _IDENTBODYCHARS).suppress()
135
140
  + (
136
- _list_of(_TENSOR)
137
- | (
138
- Literal("List").suppress()
139
- + Literal("<").suppress()
140
- + (
141
- counted_array(
142
- CharsNotIn(exact=8),
143
- Literal("scalar").suppress()
144
- + Literal(">").suppress()
145
- + common.integer
146
- + Literal("(").suppress(),
141
+ Literal("List").suppress()
142
+ + Literal("<").suppress()
143
+ + (
144
+ (
145
+ Literal("scalar").suppress()
146
+ + Literal(">").suppress()
147
+ + (
148
+ _list_of(common.ieee_float)
149
+ | (
150
+ (
151
+ (
152
+ counted_array(
153
+ CharsNotIn(exact=8),
154
+ common.integer + Literal("(").suppress(),
155
+ )
156
+ )
157
+ | (
158
+ counted_array(
159
+ CharsNotIn(exact=4),
160
+ common.integer + Literal("(").suppress(),
161
+ )
162
+ )
163
+ )
164
+ + Literal(")").suppress()
165
+ ).set_parse_action(_unpack_binary_field)
147
166
  )
148
- | counted_array(
149
- CharsNotIn(exact=8 * 3),
150
- Literal("vector").suppress()
151
- + Literal(">").suppress()
152
- + common.integer
153
- + Literal("(").suppress(),
167
+ )
168
+ | (
169
+ Literal("vector").suppress()
170
+ + Literal(">").suppress()
171
+ + (
172
+ _list_of(
173
+ Literal("(").suppress()
174
+ + Group(common.ieee_float[3], aslist=True)
175
+ + Literal(")").suppress()
176
+ )
177
+ | (
178
+ (
179
+ (
180
+ counted_array(
181
+ CharsNotIn(exact=8 * 3),
182
+ common.integer + Literal("(").suppress(),
183
+ )
184
+ )
185
+ | (
186
+ counted_array(
187
+ CharsNotIn(exact=4 * 3),
188
+ common.integer + Literal("(").suppress(),
189
+ )
190
+ )
191
+ )
192
+ + Literal(")").suppress()
193
+ ).set_parse_action(lambda tks: _unpack_binary_field(tks, elsize=3))
154
194
  )
155
- | counted_array(
156
- CharsNotIn(exact=8 * 6),
157
- Literal("symmTensor").suppress()
158
- + Literal(">").suppress()
159
- + common.integer
160
- + Literal("(").suppress(),
195
+ )
196
+ | (
197
+ Literal("vector").suppress()
198
+ + Literal(">").suppress()
199
+ + (
200
+ _list_of(
201
+ Literal("(").suppress()
202
+ + Group(common.ieee_float[6], aslist=True)
203
+ + Literal(")").suppress()
204
+ )
205
+ | (
206
+ (
207
+ (
208
+ counted_array(
209
+ CharsNotIn(exact=8 * 6),
210
+ common.integer + Literal("(").suppress(),
211
+ )
212
+ )
213
+ | (
214
+ counted_array(
215
+ CharsNotIn(exact=4 * 6),
216
+ common.integer + Literal("(").suppress(),
217
+ )
218
+ )
219
+ )
220
+ + Literal(")").suppress()
221
+ ).set_parse_action(lambda tks: _unpack_binary_field(tks, elsize=6))
161
222
  )
162
- | counted_array(
163
- CharsNotIn(exact=8 * 9),
164
- Literal("tensor").suppress()
165
- + Literal(">").suppress()
166
- + common.integer
167
- + Literal("(").suppress(),
223
+ )
224
+ | (
225
+ Literal("tensor").suppress()
226
+ + Literal(">").suppress()
227
+ + (
228
+ _list_of(
229
+ Literal("(").suppress()
230
+ + Group(common.ieee_float[9], aslist=True)
231
+ + Literal(")").suppress()
232
+ )
233
+ | (
234
+ (
235
+ (
236
+ counted_array(
237
+ CharsNotIn(exact=8 * 9),
238
+ common.integer + Literal("(").suppress(),
239
+ )
240
+ )
241
+ | (
242
+ counted_array(
243
+ CharsNotIn(exact=4 * 9),
244
+ common.integer + Literal("(").suppress(),
245
+ )
246
+ )
247
+ )
248
+ + Literal(")").suppress()
249
+ ).set_parse_action(lambda tks: _unpack_binary_field(tks, elsize=9))
168
250
  )
169
251
  )
170
- + Literal(")").suppress()
171
- ).set_parse_action(_unpack_binary_field)
252
+ )
172
253
  )
173
254
  )
174
255
  _TOKEN = QuotedString('"', unquote_results=False) | _IDENTIFIER
@@ -180,9 +261,8 @@ _KEYWORD_ENTRY = Dict(Group(_keyword_entry_of(_KEYWORD, _DATA)), asdict=True)
180
261
  _DATA_ENTRY = Forward()
181
262
  _LIST_ENTRY = _KEYWORD_ENTRY | _DATA_ENTRY
182
263
  _LIST = _list_of(_LIST_ENTRY)
183
- _DATA_ENTRY <<= (
184
- _FIELD | _LIST | _DIMENSIONED | _DIMENSIONS | common.number | _SWITCH | _TOKEN
185
- )
264
+ _NUMBER = common.signed_integer ^ common.ieee_float
265
+ _DATA_ENTRY <<= _FIELD | _LIST | _DIMENSIONED | _DIMENSIONS | _NUMBER | _SWITCH | _TOKEN
186
266
 
187
267
  _DATA <<= _DATA_ENTRY[1, ...].set_parse_action(
188
268
  lambda tks: tuple(tks) if len(tks) > 1 else [tks[0]]
@@ -202,7 +282,6 @@ _FILE = (
202
282
  )
203
283
  + Group(_keyword_entry_of(_KEYWORD, Opt(_DATA, default=""), located=True))[...]
204
284
  )
205
- .ignore(c_style_comment)
206
285
  .ignore(cpp_style_comment)
207
286
  .ignore(Literal("#include") + ... + LineEnd()) # type: ignore [no-untyped-call]
208
287
  .parse_with_tabs()
@@ -1,10 +1,12 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import array
4
+ import contextlib
4
5
  import itertools
6
+ import re
5
7
  import sys
6
8
  from enum import Enum, auto
7
- from typing import cast
9
+ from typing import cast, overload
8
10
 
9
11
  if sys.version_info >= (3, 9):
10
12
  from collections.abc import Mapping, Sequence
@@ -25,38 +27,111 @@ except ModuleNotFoundError:
25
27
  class Kind(Enum):
26
28
  DEFAULT = auto()
27
29
  SINGLE_ENTRY = auto()
28
- FIELD = auto()
29
- BINARY_FIELD = auto()
30
+ ASCII_FIELD = auto()
31
+ DOUBLE_PRECISION_BINARY_FIELD = auto()
32
+ SINGLE_PRECISION_BINARY_FIELD = auto()
30
33
  DIMENSIONS = auto()
31
34
 
32
35
 
36
+ _TOKENS = re.compile(r'(?:[^\s"]|"(?:[^"])*")+')
37
+
38
+
39
+ @overload
40
+ def normalize(
41
+ data: FoamFileBase._DataEntry, *, kind: Kind = Kind.DEFAULT
42
+ ) -> FoamFileBase._DataEntry: ...
43
+
44
+
45
+ @overload
46
+ def normalize(
47
+ data: FoamFileBase.Data, *, kind: Kind = Kind.DEFAULT
48
+ ) -> FoamFileBase.Data: ...
49
+
50
+
51
+ def normalize(
52
+ data: FoamFileBase.Data, *, kind: Kind = Kind.DEFAULT
53
+ ) -> FoamFileBase.Data:
54
+ if numpy and isinstance(data, np.ndarray):
55
+ ret = data.tolist()
56
+ assert isinstance(ret, list)
57
+ return ret
58
+
59
+ if kind == Kind.SINGLE_ENTRY and isinstance(data, tuple):
60
+ ret = normalize(list(data))
61
+ assert isinstance(ret, list)
62
+ return ret
63
+
64
+ if isinstance(data, Mapping):
65
+ return {k: normalize(v, kind=kind) for k, v in data.items()}
66
+
67
+ if (
68
+ kind == Kind.DIMENSIONS
69
+ and is_sequence(data)
70
+ and len(data) <= 7
71
+ and all(isinstance(d, (int, float)) for d in data)
72
+ ):
73
+ data = cast(Sequence[float], data)
74
+ return FoamFileBase.DimensionSet(*data)
75
+
76
+ if is_sequence(data) and not isinstance(data, tuple):
77
+ return [normalize(d, kind=Kind.SINGLE_ENTRY) for d in data]
78
+
79
+ if isinstance(data, str):
80
+ with contextlib.suppress(ValueError):
81
+ return int(data)
82
+
83
+ with contextlib.suppress(ValueError):
84
+ return float(data)
85
+
86
+ tokens: list[str] = re.findall(_TOKENS, data)
87
+
88
+ if len(tokens) == 1:
89
+ return tokens[0]
90
+
91
+ return tuple(tokens) if kind != Kind.SINGLE_ENTRY else " ".join(tokens)
92
+
93
+ if isinstance(data, FoamFileBase.Dimensioned):
94
+ value = normalize(data.value, kind=Kind.SINGLE_ENTRY)
95
+ assert isinstance(value, (int, float, list))
96
+ return FoamFileBase.Dimensioned(value, data.dimensions, data.name)
97
+
98
+ if isinstance(
99
+ data,
100
+ (int, float, bool, tuple, FoamFileBase.DimensionSet),
101
+ ):
102
+ return data
103
+
104
+ msg = f"Unsupported data type: {type(data)}"
105
+ raise TypeError(msg)
106
+
107
+
33
108
  def dumps(
34
109
  data: FoamFileBase.Data,
35
110
  *,
36
111
  kind: Kind = Kind.DEFAULT,
37
112
  ) -> bytes:
38
- if numpy and isinstance(data, np.ndarray):
39
- return dumps(data.tolist(), kind=kind)
113
+ data = normalize(data, kind=kind)
40
114
 
41
115
  if isinstance(data, Mapping):
42
116
  entries = []
43
117
  for k, v in data.items():
44
- b = dumps(v, kind=kind)
45
118
  if isinstance(v, Mapping):
46
- entries.append(dumps(k) + b" {" + b + b"}")
47
- elif not b:
119
+ entries.append(dumps(k) + b" {" + dumps(v) + b"}")
120
+ elif not v:
48
121
  entries.append(dumps(k) + b";")
49
122
  else:
50
- entries.append(dumps(k) + b" " + b + b";")
123
+ entries.append(dumps(k) + b" " + dumps(v) + b";")
51
124
 
52
125
  return b" ".join(entries)
53
126
 
54
- if isinstance(data, FoamFileBase.DimensionSet) or (
55
- kind == Kind.DIMENSIONS and is_sequence(data) and len(data) == 7
56
- ):
127
+ if isinstance(data, FoamFileBase.DimensionSet):
57
128
  return b"[" + b" ".join(dumps(v) for v in data) + b"]"
58
129
 
59
- if kind in (Kind.FIELD, Kind.BINARY_FIELD) and (
130
+ if kind in (
131
+ Kind.ASCII_FIELD,
132
+ Kind.DOUBLE_PRECISION_BINARY_FIELD,
133
+ Kind.SINGLE_PRECISION_BINARY_FIELD,
134
+ ) and (
60
135
  isinstance(data, (int, float))
61
136
  or is_sequence(data)
62
137
  and data
@@ -65,7 +140,11 @@ def dumps(
65
140
  ):
66
141
  return b"uniform " + dumps(data, kind=Kind.SINGLE_ENTRY)
67
142
 
68
- if kind in (Kind.FIELD, Kind.BINARY_FIELD) and is_sequence(data):
143
+ if kind in (
144
+ Kind.ASCII_FIELD,
145
+ Kind.DOUBLE_PRECISION_BINARY_FIELD,
146
+ Kind.SINGLE_PRECISION_BINARY_FIELD,
147
+ ) and is_sequence(data):
69
148
  if data and isinstance(data[0], (int, float)):
70
149
  tensor_kind = b"scalar"
71
150
  elif is_sequence(data[0]) and data[0] and isinstance(data[0][0], (int, float)):
@@ -80,15 +159,21 @@ def dumps(
80
159
  else:
81
160
  return dumps(data)
82
161
 
83
- if kind == Kind.BINARY_FIELD:
162
+ if kind in (
163
+ Kind.DOUBLE_PRECISION_BINARY_FIELD,
164
+ Kind.SINGLE_PRECISION_BINARY_FIELD,
165
+ ):
166
+ typecode = "f" if kind == Kind.SINGLE_PRECISION_BINARY_FIELD else "d"
84
167
  if tensor_kind == b"scalar":
85
168
  data = cast(Sequence[float], data)
86
- contents = b"(" + array.array("d", data).tobytes() + b")"
169
+ contents = b"(" + array.array(typecode, data).tobytes() + b")"
87
170
  else:
88
171
  data = cast(Sequence[Sequence[float]], data)
89
172
  contents = (
90
173
  b"("
91
- + array.array("d", itertools.chain.from_iterable(data)).tobytes()
174
+ + array.array(
175
+ typecode, itertools.chain.from_iterable(data)
176
+ ).tobytes()
92
177
  + b")"
93
178
  )
94
179
  else:
@@ -96,9 +181,6 @@ def dumps(
96
181
 
97
182
  return b"nonuniform List<" + tensor_kind + b"> " + dumps(len(data)) + contents
98
183
 
99
- if kind != Kind.SINGLE_ENTRY and isinstance(data, tuple):
100
- return b" ".join(dumps(v) for v in data)
101
-
102
184
  if isinstance(data, FoamFileBase.Dimensioned):
103
185
  if data.name is not None:
104
186
  return (
@@ -114,6 +196,9 @@ def dumps(
114
196
  + dumps(data.value, kind=Kind.SINGLE_ENTRY)
115
197
  )
116
198
 
199
+ if isinstance(data, tuple):
200
+ return b" ".join(dumps(v) for v in data)
201
+
117
202
  if is_sequence(data):
118
203
  return b"(" + b" ".join(dumps(v, kind=Kind.SINGLE_ENTRY) for v in data) + b")"
119
204
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: foamlib
3
- Version: 0.6.12
3
+ Version: 0.6.14
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,4 +1,4 @@
1
- foamlib/__init__.py,sha256=fzKDNF8_CX5rU1KVBoVQZHdjJ_nEiRbLv_sfj6-CHAY,487
1
+ foamlib/__init__.py,sha256=2TB7NPVimWOf7GSEz5g_Gbguf3RJvD-eOWA0ykCCwLM,487
2
2
  foamlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  foamlib/_cases/__init__.py,sha256=wTUHcUgU1CBgpu0cUMtksQ5VKG6B8CFu9xc3dWwsQuo,358
4
4
  foamlib/_cases/_async.py,sha256=i6g4EBHqvI-1PkdrxsRto2ynW7sxsOga2bSYk1XVG1U,7795
@@ -10,13 +10,13 @@ foamlib/_cases/_sync.py,sha256=2BJXB7Nzldb4OgPukqupgYqdceUGkI2mYhhtGPWEBrc,5901
10
10
  foamlib/_cases/_util.py,sha256=lhVca3ERY0zwYjDam6W2QMROt0yX5vAF-9_DS5RuMbM,1547
11
11
  foamlib/_files/__init__.py,sha256=-UqB9YTH6mrJfXCX00kPTAAY20XG64u1MGPw_1ewLVs,148
12
12
  foamlib/_files/_base.py,sha256=ZY_6Zxr3LZHVzJEex6SUTi9Pgo7Oi7i3Jo-wre9G3yE,1968
13
- foamlib/_files/_files.py,sha256=WF_FWiDhnkA4dtZ6zR1A0iGrv76eI3SetlQu6Zl6HY8,14949
13
+ foamlib/_files/_files.py,sha256=oYRlMfCUH9oNeu-yf2HAPmLxLHteIe7gHhsWXdn7wU0,15767
14
14
  foamlib/_files/_io.py,sha256=IQLqoqnA1TpHf21NbUho2wsYWevyqC6MKo-wfpaObUU,2226
15
- foamlib/_files/_parsing.py,sha256=qLZx_VZMNEoyfmrkC_r85QBuABa26-6Y0fHnxCq74Q8,10880
16
- foamlib/_files/_serialization.py,sha256=HN9XCDbZ0I-b_UdpEYgDVNX6U4tPd6u-uYBKOoX3uqg,3681
15
+ foamlib/_files/_parsing.py,sha256=sJ7XadWFqmJTaL9TEYyaYEu3r-CQweruwPUNWIZt4i0,14165
16
+ foamlib/_files/_serialization.py,sha256=p2yRpyyOAOKP7P6T7BLEgRVvORuzQEcv_P6dEsOZ9_8,5981
17
17
  foamlib/_files/_util.py,sha256=VXUTD0B3NbnlaE_KCqWzrFcWvBz_2JfnIWpNp3snX3Y,526
18
- foamlib-0.6.12.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
19
- foamlib-0.6.12.dist-info/METADATA,sha256=fN1pEtQzMHd-yuzMkugYgTtpVwZwV-U0CPxU6rRTnzA,7742
20
- foamlib-0.6.12.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
21
- foamlib-0.6.12.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
22
- foamlib-0.6.12.dist-info/RECORD,,
18
+ foamlib-0.6.14.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
19
+ foamlib-0.6.14.dist-info/METADATA,sha256=Um-3D8v1EnQPeX-pAySWkM-SWVBgTPIiLgKd4Ewq3RY,7742
20
+ foamlib-0.6.14.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
21
+ foamlib-0.6.14.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
22
+ foamlib-0.6.14.dist-info/RECORD,,