-
Notifications
You must be signed in to change notification settings - Fork 1
/
static.py
122 lines (97 loc) · 3.76 KB
/
static.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
__all__ = ['Static']
import io
import json
import pathlib as p
import shutil
import sys
import typing as t
from ..base.lib import lib
from ..base.type import Dict, Keys
from ..util.decorator import Match
from ..util.object import Data
if t.TYPE_CHECKING:
from typing_extensions import Self
from ..base.core import Foam
class Static:
'''OpenFOAM static parser
Example:
>>> foam = Foam.from_demo('cavity')
Foam.from_file('.../of.yaml/foam/static/demo/7/cavity.yaml', warn=False)
>>> foam.save('case')
>>> data = {
... 'name': 'Allrun',
... 'type': ['embed', 'text'],
... 'permission': 777,
... 'data': 'echo hello world!\n',
... }
>>> static = Static.from_foam(foam)
>>> static[tuple(data['type'])](data)
'''
match = Match.default()
def __init__(self, foam: 'Foam') -> None:
self._foam = foam
def __getitem__(self, keys: Keys[str]) -> t.Callable:
try:
return lambda *args, **kwargs: self.match[keys](self, *args, **kwargs)
except KeyError:
raise Exception(f'Unknown types "{keys}"')
@classmethod
def from_foam(cls, foam: 'Foam') -> 'Self':
return cls(foam)
@match.register()
def _(self, static: Dict) -> None:
# do nothing
pass
@match.register('embed', 'text')
def _(self, static: Dict) -> None:
out = self._out(static['name'])
self._foam._write(out, static['data'], static.get('permission', None))
@match.register('embed', 'binary')
def _(self, static: Dict) -> None:
out = self._out(static['name'])
out.write_bytes(static['data'])
@match.register('embed', '7z')
def _(self, static: Dict) -> None:
self._assert()
out = self._out(static['name'])
with lib['py7zr'].SevenZipFile(io.BytesIO(static['data']), mode='r') as z:
z.extractall(path=out.parent)
@match.register('path', 'raw')
def _(self, static: Dict) -> None:
out, in_ = self._out(static['name']), self._in(static['data'])
if in_.is_dir():
kwargs = {'dirs_exist_ok': True} if sys.version_info >= (3, 8) else {}
shutil.copytree(in_, out, **kwargs)
elif in_.is_file():
shutil.copyfile(in_, out)
else:
raise Exception('Target is neither a file nor a directory')
@match.register('path', '7z')
def _(self, static: Dict) -> None:
self._assert()
out, in_ = self._out(static['name']), self._in(static['data'])
with lib['py7zr'].SevenZipFile(in_, mode='r') as z:
z.extractall(path=out.parent)
@match.register('path', 'foam', 'json')
def _(self, static: Dict) -> None:
self._path_foam(static)
@match.register('path', 'foam', 'yaml')
def _(self, static: Dict) -> None:
self._path_foam(static)
def _out(self, name: str) -> p.Path:
out = self._foam._path(name)
out.parent.mkdir(parents=True, exist_ok=True)
return out
def _in(self, data: str) -> p.Path:
return self._foam._root / data
def _assert(self) -> None:
assert lib['py7zr'] is not None, 'pip install ifoam[7z]' # TODO: improve error message
def _path_foam(self, static: Dict) -> None:
data = Data.from_dict({})
out, in_ = self._foam._path(), self._in(static['data'])
data[static['name'].split('/')] = { # p.Path(static['name']).parts
'json': lambda path: json.loads(path.read_text()),
'yaml': lambda path: lib['yaml'].load(path.read_text(), Loader=lib['SafeLoader']),
}[static['type'][2]](in_)
self._foam.__class__([{'order': ['meta', 'foam']}, data._data], in_.parent, warn=False) \
.save(out, paraview=False)