foamlib 0.6.11__py3-none-any.whl → 0.6.12__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/_cases/_sync.py CHANGED
@@ -1,7 +1,8 @@
1
+ from __future__ import annotations
2
+
1
3
  import shutil
2
4
  import sys
3
- from types import TracebackType
4
- from typing import TYPE_CHECKING, Any, Callable, Optional, Type, Union, overload
5
+ from typing import TYPE_CHECKING, Any, Callable, overload
5
6
 
6
7
  if sys.version_info >= (3, 9):
7
8
  from collections.abc import Collection, Sequence
@@ -13,7 +14,6 @@ if sys.version_info >= (3, 11):
13
14
  else:
14
15
  from typing_extensions import Self
15
16
 
16
- from .._files import FoamFieldFile
17
17
  from ._base import FoamCaseBase
18
18
  from ._run import FoamCaseRunBase
19
19
  from ._subprocess import run_sync
@@ -21,6 +21,9 @@ from ._util import ValuedGenerator
21
21
 
22
22
  if TYPE_CHECKING:
23
23
  import os
24
+ from types import TracebackType
25
+
26
+ from .._files import FoamFieldFile
24
27
 
25
28
 
26
29
  class FoamCase(FoamCaseRunBase):
@@ -36,7 +39,7 @@ class FoamCase(FoamCaseRunBase):
36
39
 
37
40
  class TimeDirectory(FoamCaseRunBase.TimeDirectory):
38
41
  @property
39
- def _case(self) -> "FoamCase":
42
+ def _case(self) -> FoamCase:
40
43
  return FoamCase(self.path.parent)
41
44
 
42
45
  def cell_centers(self) -> FoamFieldFile:
@@ -50,7 +53,7 @@ class FoamCase(FoamCaseRunBase):
50
53
 
51
54
  @staticmethod
52
55
  def _run(
53
- cmd: Union[Sequence[Union[str, "os.PathLike[str]"]], str],
56
+ cmd: Sequence[str | os.PathLike[str]] | str,
54
57
  *,
55
58
  cpus: int,
56
59
  **kwargs: Any,
@@ -58,34 +61,29 @@ class FoamCase(FoamCaseRunBase):
58
61
  run_sync(cmd, **kwargs)
59
62
 
60
63
  @staticmethod
61
- def _rmtree(
62
- path: Union["os.PathLike[str]", str], *, ignore_errors: bool = False
63
- ) -> None:
64
+ def _rmtree(path: os.PathLike[str] | str, *, ignore_errors: bool = False) -> None:
64
65
  shutil.rmtree(path, ignore_errors=ignore_errors)
65
66
 
66
67
  @staticmethod
67
68
  def _copytree(
68
- src: Union["os.PathLike[str]", str],
69
- dest: Union["os.PathLike[str]", str],
69
+ src: os.PathLike[str] | str,
70
+ dest: os.PathLike[str] | str,
70
71
  *,
71
72
  symlinks: bool = False,
72
- ignore: Optional[
73
- Callable[[Union["os.PathLike[str]", str], Collection[str]], Collection[str]]
74
- ] = None,
73
+ ignore: Callable[[os.PathLike[str] | str, Collection[str]], Collection[str]]
74
+ | None = None,
75
75
  ) -> None:
76
76
  shutil.copytree(src, dest, symlinks=symlinks, ignore=ignore)
77
77
 
78
78
  @overload
79
- def __getitem__(
80
- self, index: Union[int, float, str]
81
- ) -> "FoamCase.TimeDirectory": ...
79
+ def __getitem__(self, index: int | float | str) -> FoamCase.TimeDirectory: ...
82
80
 
83
81
  @overload
84
- def __getitem__(self, index: slice) -> Sequence["FoamCase.TimeDirectory"]: ...
82
+ def __getitem__(self, index: slice) -> Sequence[FoamCase.TimeDirectory]: ...
85
83
 
86
84
  def __getitem__(
87
- self, index: Union[int, slice, float, str]
88
- ) -> Union["FoamCase.TimeDirectory", Sequence["FoamCase.TimeDirectory"]]:
85
+ self, index: int | slice | float | str
86
+ ) -> FoamCase.TimeDirectory | Sequence[FoamCase.TimeDirectory]:
89
87
  ret = super().__getitem__(index)
90
88
  if isinstance(ret, FoamCaseBase.TimeDirectory):
91
89
  return FoamCase.TimeDirectory(ret)
@@ -96,9 +94,9 @@ class FoamCase(FoamCaseRunBase):
96
94
 
97
95
  def __exit__(
98
96
  self,
99
- exc_type: Optional[Type[BaseException]],
100
- exc_val: Optional[BaseException],
101
- exc_tb: Optional[TracebackType],
97
+ exc_type: type[BaseException] | None,
98
+ exc_val: BaseException | None,
99
+ exc_tb: TracebackType | None,
102
100
  ) -> None:
103
101
  self._rmtree(self.path)
104
102
 
@@ -117,10 +115,10 @@ class FoamCase(FoamCaseRunBase):
117
115
 
118
116
  def run(
119
117
  self,
120
- cmd: Optional[Union[Sequence[Union[str, "os.PathLike[str]"]], str]] = None,
118
+ cmd: Sequence[str | os.PathLike[str]] | str | None = None,
121
119
  *,
122
- parallel: Optional[bool] = None,
123
- cpus: Optional[int] = None,
120
+ parallel: bool | None = None,
121
+ cpus: int | None = None,
124
122
  check: bool = True,
125
123
  log: bool = True,
126
124
  ) -> None:
@@ -158,7 +156,7 @@ class FoamCase(FoamCaseRunBase):
158
156
  for _ in self._restore_0_dir_calls():
159
157
  pass
160
158
 
161
- def copy(self, dst: Optional[Union["os.PathLike[str]", str]] = None) -> Self:
159
+ def copy(self, dst: os.PathLike[str] | str | None = None) -> Self:
162
160
  """
163
161
  Make a copy of this case.
164
162
 
@@ -173,7 +171,7 @@ class FoamCase(FoamCaseRunBase):
173
171
 
174
172
  return calls.value
175
173
 
176
- def clone(self, dst: Optional[Union["os.PathLike[str]", str]] = None) -> Self:
174
+ def clone(self, dst: os.PathLike[str] | str | None = None) -> Self:
177
175
  """
178
176
  Clone this case (make a clean copy).
179
177
 
foamlib/_cases/_util.py CHANGED
@@ -1,16 +1,19 @@
1
+ from __future__ import annotations
2
+
1
3
  import functools
2
4
  import sys
3
- from types import TracebackType
4
5
  from typing import (
6
+ TYPE_CHECKING,
5
7
  Any,
6
8
  AsyncContextManager,
7
9
  Callable,
8
10
  Generic,
9
- Optional,
10
- Type,
11
11
  TypeVar,
12
12
  )
13
13
 
14
+ if TYPE_CHECKING:
15
+ from types import TracebackType
16
+
14
17
  if sys.version_info >= (3, 9):
15
18
  from collections.abc import Generator
16
19
  else:
@@ -23,7 +26,7 @@ R = TypeVar("R")
23
26
 
24
27
 
25
28
  class ValuedGenerator(Generic[Y, S, R]):
26
- def __init__(self, generator: Generator[Y, S, R]):
29
+ def __init__(self, generator: Generator[Y, S, R]) -> None:
27
30
  self._generator = generator
28
31
 
29
32
  def __iter__(self) -> Generator[Y, S, R]:
@@ -32,7 +35,7 @@ class ValuedGenerator(Generic[Y, S, R]):
32
35
 
33
36
 
34
37
  class _AwaitableAsyncContextManager(Generic[R]):
35
- def __init__(self, cm: "AsyncContextManager[R]"):
38
+ def __init__(self, cm: AsyncContextManager[R]) -> None:
36
39
  self._cm = cm
37
40
 
38
41
  def __await__(self) -> Generator[Any, Any, R]:
@@ -43,15 +46,15 @@ class _AwaitableAsyncContextManager(Generic[R]):
43
46
 
44
47
  async def __aexit__(
45
48
  self,
46
- exc_type: Optional[Type[BaseException]],
47
- exc_val: Optional[BaseException],
48
- exc_tb: Optional[TracebackType],
49
- ) -> Optional[bool]:
49
+ exc_type: type[BaseException] | None,
50
+ exc_val: BaseException | None,
51
+ exc_tb: TracebackType | None,
52
+ ) -> bool | None:
50
53
  return await self._cm.__aexit__(exc_type, exc_val, exc_tb)
51
54
 
52
55
 
53
56
  def awaitableasynccontextmanager(
54
- cm: Callable[..., "AsyncContextManager[R]"],
57
+ cm: Callable[..., AsyncContextManager[R]],
55
58
  ) -> Callable[..., _AwaitableAsyncContextManager[R]]:
56
59
  @functools.wraps(cm)
57
60
  def f(*args: Any, **kwargs: Any) -> _AwaitableAsyncContextManager[R]:
foamlib/_files/_base.py CHANGED
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import sys
2
4
  from dataclasses import dataclass
3
5
  from typing import TYPE_CHECKING, Dict, NamedTuple, Optional, Tuple, Union
@@ -33,9 +35,9 @@ class FoamFileBase:
33
35
 
34
36
  @dataclass
35
37
  class Dimensioned:
36
- value: "FoamFileBase._Tensor" = 0
37
- dimensions: Union["FoamFileBase.DimensionSet", Sequence[float]] = ()
38
- name: Optional[str] = None
38
+ value: FoamFileBase._Tensor = 0
39
+ dimensions: FoamFileBase.DimensionSet | Sequence[float] = ()
40
+ name: str | None = None
39
41
 
40
42
  def __post_init__(self) -> None:
41
43
  if not isinstance(self.dimensions, FoamFileBase.DimensionSet):
foamlib/_files/_files.py CHANGED
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import sys
2
4
  from copy import deepcopy
3
5
  from typing import Any, Optional, Tuple, Union, cast
@@ -39,13 +41,13 @@ class FoamFile(
39
41
  ):
40
42
  """An OpenFOAM dictionary within a file as a mutable mapping."""
41
43
 
42
- def __init__(self, _file: "FoamFile", _keywords: Tuple[str, ...]) -> None:
44
+ def __init__(self, _file: FoamFile, _keywords: tuple[str, ...]) -> None:
43
45
  self._file = _file
44
46
  self._keywords = _keywords
45
47
 
46
48
  def __getitem__(
47
49
  self, keyword: str
48
- ) -> Union[FoamFileBase._DataEntry, "FoamFile.SubDict"]:
50
+ ) -> FoamFileBase._DataEntry | FoamFile.SubDict:
49
51
  return self._file[(*self._keywords, keyword)]
50
52
 
51
53
  def __setitem__(
@@ -97,7 +99,8 @@ class FoamFile(
97
99
  """Alias of `self["FoamFile", "version"]`."""
98
100
  ret = self["FoamFile", "version"]
99
101
  if not isinstance(ret, (int, float)):
100
- raise TypeError("version is not a number")
102
+ msg = "version is not a number"
103
+ raise TypeError(msg)
101
104
  return ret
102
105
 
103
106
  @version.setter
@@ -109,9 +112,11 @@ class FoamFile(
109
112
  """Alias of `self["FoamFile", "format"]`."""
110
113
  ret = self["FoamFile", "format"]
111
114
  if not isinstance(ret, str):
112
- raise TypeError("format is not a string")
115
+ msg = "format is not a string"
116
+ raise TypeError(msg)
113
117
  if ret not in ("ascii", "binary"):
114
- raise ValueError("format is not 'ascii' or 'binary'")
118
+ msg = "format is not 'ascii' or 'binary'"
119
+ raise ValueError(msg)
115
120
  return cast(Literal["ascii", "binary"], ret)
116
121
 
117
122
  @format.setter
@@ -123,7 +128,8 @@ class FoamFile(
123
128
  """Alias of `self["FoamFile", "class"]`."""
124
129
  ret = self["FoamFile", "class"]
125
130
  if not isinstance(ret, str):
126
- raise TypeError("class is not a string")
131
+ msg = "class is not a string"
132
+ raise TypeError(msg)
127
133
  return ret
128
134
 
129
135
  @class_.setter
@@ -135,7 +141,8 @@ class FoamFile(
135
141
  """Alias of `self["FoamFile", "location"]`."""
136
142
  ret = self["FoamFile", "location"]
137
143
  if not isinstance(ret, str):
138
- raise TypeError("location is not a string")
144
+ msg = "location is not a string"
145
+ raise TypeError(msg)
139
146
  return ret
140
147
 
141
148
  @location.setter
@@ -147,7 +154,8 @@ class FoamFile(
147
154
  """Alias of `self["FoamFile", "object"]`."""
148
155
  ret = self["FoamFile", "object"]
149
156
  if not isinstance(ret, str):
150
- raise TypeError("object is not a string")
157
+ msg = "object is not a string"
158
+ raise TypeError(msg)
151
159
  return ret
152
160
 
153
161
  @object_.setter
@@ -155,8 +163,8 @@ class FoamFile(
155
163
  self["FoamFile", "object"] = value
156
164
 
157
165
  def __getitem__(
158
- self, keywords: Optional[Union[str, Tuple[str, ...]]]
159
- ) -> Union[FoamFileBase._DataEntry, "FoamFile.SubDict"]:
166
+ self, keywords: str | tuple[str, ...] | None
167
+ ) -> FoamFileBase._DataEntry | FoamFile.SubDict:
160
168
  if not keywords:
161
169
  keywords = ()
162
170
  elif not isinstance(keywords, tuple):
@@ -173,14 +181,14 @@ class FoamFile(
173
181
  return deepcopy(value)
174
182
 
175
183
  def __setitem__(
176
- self, keywords: Optional[Union[str, Tuple[str, ...]]], data: FoamFileBase.Data
184
+ self, keywords: str | tuple[str, ...] | None, data: FoamFileBase.Data
177
185
  ) -> None:
178
- with self:
179
- if not keywords:
180
- keywords = ()
181
- elif not isinstance(keywords, tuple):
182
- keywords = (keywords,)
186
+ if not keywords:
187
+ keywords = ()
188
+ elif not isinstance(keywords, tuple):
189
+ keywords = (keywords,)
183
190
 
191
+ with self:
184
192
  try:
185
193
  write_header = (
186
194
  not self and "FoamFile" not in self and keywords != ("FoamFile",)
@@ -213,87 +221,90 @@ class FoamFile(
213
221
  kind = Kind.DIMENSIONS
214
222
 
215
223
  if (
216
- kind == Kind.FIELD or kind == Kind.BINARY_FIELD
224
+ kind in (Kind.FIELD, Kind.BINARY_FIELD)
217
225
  ) and self.class_ == "dictionary":
218
- if not is_sequence(data):
219
- class_ = "volScalarField"
220
- elif (len(data) == 3 and not is_sequence(data[0])) or len(data[0]) == 3:
221
- class_ = "volVectorField"
222
- elif (len(data) == 6 and not is_sequence(data[0])) or len(data[0]) == 6:
223
- class_ = "volSymmTensorField"
224
- elif (len(data) == 9 and not is_sequence(data[0])) or len(data[0]) == 9:
225
- class_ = "volTensorField"
226
+ if isinstance(data, (int, float)):
227
+ self.class_ = "volScalarField"
228
+
229
+ elif is_sequence(data) and data:
230
+ if isinstance(data[0], (int, float)):
231
+ if len(data) == 3:
232
+ self.class_ = "volVectorField"
233
+ elif len(data) == 6:
234
+ self.class_ = "volSymmTensorField"
235
+ elif len(data) == 9:
236
+ self.class_ = "volTensorField"
237
+ elif (
238
+ is_sequence(data[0])
239
+ and data[0]
240
+ and isinstance(data[0][0], (int, float))
241
+ ):
242
+ if len(data[0]) == 3:
243
+ self.class_ = "volVectorField"
244
+ elif len(data[0]) == 6:
245
+ self.class_ = "volSymmTensorField"
246
+ elif len(data[0]) == 9:
247
+ self.class_ = "volTensorField"
248
+
249
+ parsed = self._get_parsed(missing_ok=True)
250
+
251
+ start, end = parsed.entry_location(keywords, missing_ok=True)
252
+
253
+ if start and not parsed.contents[:start].endswith(b"\n\n"):
254
+ if parsed.contents[:start].endswith(b"\n"):
255
+ before = b"\n" if len(keywords) <= 1 else b""
226
256
  else:
227
- class_ = "volScalarField"
228
-
229
- self.class_ = class_
230
- self[keywords] = data
231
-
257
+ before = b"\n\n" if len(keywords) <= 1 else b"\n"
232
258
  else:
233
- parsed = self._get_parsed(missing_ok=True)
234
-
235
- start, end = parsed.entry_location(keywords, missing_ok=True)
236
-
237
259
  before = b""
238
- if parsed.contents[:start] and not parsed.contents[:start].endswith(
239
- b"\n"
240
- ):
241
- before = b"\n"
242
- if (
243
- parsed.contents[:start]
244
- and len(keywords) <= 1
245
- and not parsed.contents[:start].endswith(b"\n\n")
246
- ):
247
- before = b"\n\n"
248
260
 
261
+ if not parsed.contents[end:].strip() or parsed.contents[end:].startswith(
262
+ b"}"
263
+ ):
264
+ after = b"\n" + b" " * (len(keywords) - 2)
265
+ else:
249
266
  after = b""
250
- if parsed.contents[end:].startswith(b"}"):
251
- after = b" " * (len(keywords) - 2)
252
- if not parsed.contents[end:] or not parsed.contents[end:].startswith(
253
- b"\n"
254
- ):
255
- after = b"\n" + after
256
-
257
- indentation = b" " * (len(keywords) - 1)
258
-
259
- if isinstance(data, Mapping):
260
- if isinstance(data, (FoamFile, FoamFile.SubDict)):
261
- data = data.as_dict()
262
-
263
- parsed.put(
264
- keywords,
265
- ...,
266
- before
267
- + indentation
268
- + dumps(keywords[-1])
269
- + b"\n"
270
- + indentation
271
- + b"{\n"
272
- + indentation
273
- + b"}"
274
- + after,
275
- )
276
-
277
- for k, v in data.items():
278
- self[(*keywords, k)] = v
279
-
280
- elif keywords:
281
- parsed.put(
282
- keywords,
283
- data,
284
- before
285
- + indentation
286
- + dumps(keywords[-1])
287
- + b" "
288
- + dumps(data, kind=kind)
289
- + b";"
290
- + after,
291
- )
292
267
 
293
- else:
294
- parsed.put(keywords, data, before + dumps(data, kind=kind) + after)
268
+ indentation = b" " * (len(keywords) - 1)
269
+
270
+ if isinstance(data, Mapping):
271
+ if isinstance(data, (FoamFile, FoamFile.SubDict)):
272
+ data = data.as_dict()
273
+
274
+ parsed.put(
275
+ keywords,
276
+ ...,
277
+ before
278
+ + indentation
279
+ + dumps(keywords[-1])
280
+ + b"\n"
281
+ + indentation
282
+ + b"{\n"
283
+ + indentation
284
+ + b"}"
285
+ + after,
286
+ )
287
+
288
+ for k, v in data.items():
289
+ self[(*keywords, k)] = v
290
+
291
+ elif keywords:
292
+ parsed.put(
293
+ keywords,
294
+ deepcopy(data),
295
+ before
296
+ + indentation
297
+ + dumps(keywords[-1])
298
+ + b" "
299
+ + dumps(data, kind=kind)
300
+ + b";"
301
+ + after,
302
+ )
303
+
304
+ else:
305
+ parsed.put((), deepcopy(data), before + dumps(data, kind=kind) + after)
295
306
 
296
- def __delitem__(self, keywords: Optional[Union[str, Tuple[str, ...]]]) -> None:
307
+ def __delitem__(self, keywords: str | tuple[str, ...] | None) -> None:
297
308
  if not keywords:
298
309
  keywords = ()
299
310
  elif not isinstance(keywords, tuple):
@@ -302,12 +313,12 @@ class FoamFile(
302
313
  with self:
303
314
  del self._get_parsed()[keywords]
304
315
 
305
- def _iter(self, keywords: Tuple[str, ...] = ()) -> Iterator[Optional[str]]:
316
+ def _iter(self, keywords: tuple[str, ...] = ()) -> Iterator[str | None]:
306
317
  yield from (
307
318
  k[-1] if k else None for k in self._get_parsed() if k[:-1] == keywords
308
319
  )
309
320
 
310
- def __iter__(self) -> Iterator[Optional[str]]:
321
+ def __iter__(self) -> Iterator[str | None]:
311
322
  yield from (k for k in self._iter() if k != "FoamFile")
312
323
 
313
324
  def __contains__(self, keywords: object) -> bool:
@@ -348,11 +359,12 @@ class FoamFieldFile(FoamFile):
348
359
  """An OpenFOAM dictionary file representing a field as a mutable mapping."""
349
360
 
350
361
  class BoundariesSubDict(FoamFile.SubDict):
351
- def __getitem__(self, keyword: str) -> "FoamFieldFile.BoundarySubDict":
362
+ def __getitem__(self, keyword: str) -> FoamFieldFile.BoundarySubDict:
352
363
  value = super().__getitem__(keyword)
353
364
  if not isinstance(value, FoamFieldFile.BoundarySubDict):
354
365
  assert not isinstance(value, FoamFile.SubDict)
355
- raise TypeError(f"boundary {keyword} is not a dictionary")
366
+ msg = f"boundary {keyword} is not a dictionary"
367
+ raise TypeError(msg)
356
368
  return value
357
369
 
358
370
  class BoundarySubDict(FoamFile.SubDict):
@@ -363,7 +375,8 @@ class FoamFieldFile(FoamFile):
363
375
  """Alias of `self["type"]`."""
364
376
  ret = self["type"]
365
377
  if not isinstance(ret, str):
366
- raise TypeError("type is not a string")
378
+ msg = "type is not a string"
379
+ raise TypeError(msg)
367
380
  return ret
368
381
 
369
382
  @type.setter
@@ -392,8 +405,8 @@ class FoamFieldFile(FoamFile):
392
405
  del self["value"]
393
406
 
394
407
  def __getitem__(
395
- self, keywords: Optional[Union[str, Tuple[str, ...]]]
396
- ) -> Union[FoamFileBase._DataEntry, FoamFile.SubDict]:
408
+ self, keywords: str | tuple[str, ...] | None
409
+ ) -> FoamFileBase._DataEntry | FoamFile.SubDict:
397
410
  if not keywords:
398
411
  keywords = ()
399
412
  elif not isinstance(keywords, tuple):
@@ -408,15 +421,16 @@ class FoamFieldFile(FoamFile):
408
421
  return ret
409
422
 
410
423
  @property
411
- def dimensions(self) -> Union[FoamFile.DimensionSet, Sequence[float]]:
424
+ def dimensions(self) -> FoamFile.DimensionSet | Sequence[float]:
412
425
  """Alias of `self["dimensions"]`."""
413
426
  ret = self["dimensions"]
414
427
  if not isinstance(ret, FoamFile.DimensionSet):
415
- raise TypeError("dimensions is not a DimensionSet")
428
+ msg = "dimensions is not a DimensionSet"
429
+ raise TypeError(msg)
416
430
  return ret
417
431
 
418
432
  @dimensions.setter
419
- def dimensions(self, value: Union[FoamFile.DimensionSet, Sequence[float]]) -> None:
433
+ def dimensions(self, value: FoamFile.DimensionSet | Sequence[float]) -> None:
420
434
  self["dimensions"] = value
421
435
 
422
436
  @property
@@ -434,12 +448,13 @@ class FoamFieldFile(FoamFile):
434
448
  self["internalField"] = value
435
449
 
436
450
  @property
437
- def boundary_field(self) -> "FoamFieldFile.BoundariesSubDict":
451
+ def boundary_field(self) -> FoamFieldFile.BoundariesSubDict:
438
452
  """Alias of `self["boundaryField"]`."""
439
453
  ret = self["boundaryField"]
440
454
  if not isinstance(ret, FoamFieldFile.BoundariesSubDict):
441
455
  assert not isinstance(ret, FoamFile.SubDict)
442
- raise TypeError("boundaryField is not a dictionary")
456
+ msg = "boundaryField is not a dictionary"
457
+ raise TypeError(msg)
443
458
  return ret
444
459
 
445
460
  @boundary_field.setter
foamlib/_files/_io.py CHANGED
@@ -1,12 +1,10 @@
1
+ from __future__ import annotations
2
+
1
3
  import gzip
2
4
  import sys
3
5
  from pathlib import Path
4
- from types import TracebackType
5
6
  from typing import (
6
7
  TYPE_CHECKING,
7
- Optional,
8
- Type,
9
- Union,
10
8
  )
11
9
 
12
10
  if sys.version_info >= (3, 11):
@@ -18,14 +16,15 @@ from ._parsing import Parsed
18
16
 
19
17
  if TYPE_CHECKING:
20
18
  import os
19
+ from types import TracebackType
21
20
 
22
21
 
23
22
  class FoamFileIO:
24
- def __init__(self, path: Union["os.PathLike[str]", str]) -> None:
23
+ def __init__(self, path: os.PathLike[str] | str) -> None:
25
24
  self.path = Path(path).absolute()
26
25
 
27
- self.__parsed: Optional[Parsed] = None
28
- self.__missing: Optional[bool] = None
26
+ self.__parsed: Parsed | None = None
27
+ self.__missing: bool | None = None
29
28
  self.__defer_io = 0
30
29
 
31
30
  def __enter__(self) -> Self:
@@ -36,9 +35,9 @@ class FoamFileIO:
36
35
 
37
36
  def __exit__(
38
37
  self,
39
- exc_type: Optional[Type[BaseException]],
40
- exc_val: Optional[BaseException],
41
- exc_tb: Optional[TracebackType],
38
+ exc_type: type[BaseException] | None,
39
+ exc_val: BaseException | None,
40
+ exc_tb: TracebackType | None,
42
41
  ) -> None:
43
42
  self.__defer_io -= 1
44
43
  if self.__defer_io == 0: