foamlib 0.3.1__py3-none-any.whl → 0.3.2__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,10 +1,10 @@
1
1
  """A Python interface for interacting with OpenFOAM."""
2
2
 
3
- __version__ = "0.3.1"
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
  ]
foamlib/_files/_files.py CHANGED
@@ -12,7 +12,7 @@ else:
12
12
 
13
13
  from ._base import FoamDict
14
14
  from ._io import FoamFileIO
15
- from ._serialization import serialize
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{serialize({keywords[-1]: {}})}\n{contents[end:]}"
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{serialize({keywords[-1]: data}, assume_field=assume_field, assume_dimensions=assume_dimensions)}\n{contents[end:]}"
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
- def serialize(
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, Mapping):
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 = serialize(
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 {serialize(data)}"
60
+ return f"uniform {dumps(data)}"
47
61
  elif isinstance(data[0], (int, float)):
48
- return f"nonuniform List<scalar> {len(data)}{serialize(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)}{serialize(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)}{serialize(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)}{serialize(data)}"
68
+ return f"nonuniform List<tensor> {len(data)}{dumps(data)}"
55
69
  else:
56
- return serialize(
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
- serialize(v, assume_field=assume_field, assume_dimensions=assume_dimensions)
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} {serialize(data.dimensions, assume_dimensions=True)} {serialize(data.value)}"
84
+ return f"{data.name} {dumps(data.dimensions, assume_dimensions=True)} {dumps(data.value)}"
71
85
  else:
72
- return f"{serialize(data.dimensions, assume_dimensions=True)} {serialize(data.value)}"
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(serialize(v) for v in data)})"
91
+ return f"({' '.join(dumps(v) for v in data)})"
76
92
 
77
93
  elif data is True:
78
94
  return "yes"
foamlib/_util.py CHANGED
@@ -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[Union["Sequence[Any]", "np.ndarray[Any, Any]"]]:
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 = subprocess.CalledProcessError
25
+ class CalledProcessError(subprocess.CalledProcessError):
26
+ """Exception raised when a process fails and `check=True`."""
37
27
 
38
- if sys.version_info >= (3, 9):
39
- CompletedProcess = subprocess.CompletedProcess[str]
40
- else:
41
- CompletedProcess = subprocess.CompletedProcess
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
- ) -> CompletedProcess:
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=asyncio.subprocess.DEVNULL,
64
- stderr=asyncio.subprocess.PIPE,
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
- return proc
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
- ) -> CompletedProcess:
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
- ret.check_returncode()
109
-
110
- return ret
112
+ _check(proc.returncode, cmd, stderr.decode())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: foamlib
3
- Version: 0.3.1
3
+ Version: 0.3.2
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=RKXFmt6ZgoSEiW8H5loLPjL4VY_2oIla-Dd0C7pEUKY,431
2
+ foamlib/_cases.py,sha256=SkUthKb98zXPMYACaGyfGC0Fo1jzD6cC4qEGesHfNfc,20554
3
+ foamlib/_util.py,sha256=0HJ9n8QG9K7jC_xUDzOJo_NA2DBCJKJRLpmd5Yu42kU,2901
4
+ foamlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ foamlib/_files/__init__.py,sha256=m4y_7wFV2Voly1aJrTYALjT3S1Aq7EbaijxdGFbJrmU,160
6
+ foamlib/_files/_base.py,sha256=YA5a-i5HZuA3JslCD6r-DwZzpSA8r42dqSXef286Ako,2050
7
+ foamlib/_files/_fields.py,sha256=jVHOHEV70i6QrWzqhF_W5CywUZyJxN5Eh5S1MrNn1G0,5632
8
+ foamlib/_files/_files.py,sha256=aS8VDGifnDSX40HdgT512fuhQ9iGlPls3p133d64Rak,5975
9
+ foamlib/_files/_io.py,sha256=alxMyxQh0zb6BZYqomZwOo9dQujMpRuS5yfpIKBEnaM,1976
10
+ foamlib/_files/_parsing.py,sha256=blyt1kpYruoW5I6DMDg8jhg6f5oz7gzedmAImuJ5b4k,5966
11
+ foamlib/_files/_serialization.py,sha256=H9STIpUxEBRwXh5WnqtjicCkGTpTYSwfWUwbVJf9x9A,2961
12
+ foamlib-0.3.2.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
13
+ foamlib-0.3.2.dist-info/METADATA,sha256=DBX2JpB09uqjPowv_ShTp7BZ9ryRI_WqVmcpp7T2-DQ,4650
14
+ foamlib-0.3.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
15
+ foamlib-0.3.2.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
16
+ foamlib-0.3.2.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- foamlib/__init__.py,sha256=tO70QZaLcvSKedqwp14wd35SdnVPg57RHiaPV_q33wI,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=YA5a-i5HZuA3JslCD6r-DwZzpSA8r42dqSXef286Ako,2050
7
- foamlib/_files/_fields.py,sha256=jVHOHEV70i6QrWzqhF_W5CywUZyJxN5Eh5S1MrNn1G0,5632
8
- foamlib/_files/_files.py,sha256=EyZnvP9okZmElzL9db4FkOD82qizeJrgb_ZGIM4xoXI,5987
9
- foamlib/_files/_io.py,sha256=alxMyxQh0zb6BZYqomZwOo9dQujMpRuS5yfpIKBEnaM,1976
10
- foamlib/_files/_parsing.py,sha256=blyt1kpYruoW5I6DMDg8jhg6f5oz7gzedmAImuJ5b4k,5966
11
- foamlib/_files/_serialization.py,sha256=Pq45Y3_DmblAk7ccUHf6RvipC_GQqU3SV89NOtV9CEg,2695
12
- foamlib-0.3.1.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
13
- foamlib-0.3.1.dist-info/METADATA,sha256=blCma_pulIQtuhsmJZ36RCRZxhdEnQxB6u2wfK-AVZY,4650
14
- foamlib-0.3.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
15
- foamlib-0.3.1.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
16
- foamlib-0.3.1.dist-info/RECORD,,