-
Notifications
You must be signed in to change notification settings - Fork 2
/
layout_json.py
140 lines (116 loc) · 4.4 KB
/
layout_json.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
"""TcEx Framework Module"""
# standard library
import json
import logging
from collections import OrderedDict
from functools import cached_property
from pathlib import Path
from ...pleb.singleton import Singleton
from .model.install_json_model import OutputVariablesModel, ParamsModel
from .model.layout_json_model import LayoutJsonModel
# get logger
_logger = logging.getLogger(__name__.split('.', maxsplit=1)[0])
class LayoutJson(metaclass=Singleton):
"""Config object for layout.json configuration file"""
def __init__(
self,
filename: str | None = None,
path: Path | str | None = None,
logger: logging.Logger | None = None,
):
"""Initialize instance properties."""
filename = filename or 'layout.json'
path = Path(path or Path.cwd())
self.log = logger or _logger
# properties
self.fqfn = path / filename
@cached_property
def contents(self) -> dict:
"""Return layout.json file contents."""
contents = {}
if self.fqfn.is_file():
try:
with self.fqfn.open() as fh:
contents = json.load(fh, object_pairs_hook=OrderedDict)
except (OSError, ValueError): # pragma: no cover
self.log.error(
f'feature=layout-json, exception=failed-reading-file, filename={self.fqfn}'
)
else: # pragma: no cover
self.log.error(f'feature=layout-json, exception=file-not-found, filename={self.fqfn}')
return contents
def create(self, inputs: list[ParamsModel], outputs: list[OutputVariablesModel]):
"""Create new layout.json file based on inputs and outputs."""
def input_data(sequence: int, title: str) -> dict:
return {
'parameters': [],
'sequence': sequence,
'title': title,
}
lj = LayoutJsonModel(
**{
'inputs': [
input_data(1, 'Action'),
input_data(2, 'Connection'),
input_data(3, 'Configure'),
input_data(4, 'Advanced'),
],
'outputs': [{'display': '', 'name': o.name} for o in outputs],
}
)
for input_ in inputs:
if input_.name == 'tc_action':
lj.inputs[0].parameters.append({'name': 'tc_action'}) # type: ignore
elif input_.hidden is True:
lj.inputs[2].parameters.append(
{
'display': "'hidden' != 'hidden'",
'hidden': 'true',
'name': input_.name,
} # type: ignore
)
else:
lj.inputs[2].parameters.append({'display': '', 'name': input_.name}) # type: ignore
# write layout file to disk
data = lj.json(
by_alias=True, exclude_defaults=True, exclude_none=True, indent=2, sort_keys=True
)
self.write(data)
@property
def has_layout(self):
"""Return True if App has layout.json file."""
return self.fqfn.is_file()
@cached_property
def model(self) -> LayoutJsonModel:
"""Return the Install JSON model."""
return LayoutJsonModel(**self.contents)
@property
def update(self):
"""Return InstallJsonUpdate instance."""
return LayoutJsonUpdate(lj=self)
def write(self, data: str):
"""Write updated file.
Args:
data: The JSON string to write data.
"""
with self.fqfn.open(mode='w') as fh:
fh.write(f'{data}\n')
class LayoutJsonUpdate:
"""Update layout.json file with current standards and schema."""
def __init__(self, lj: LayoutJson):
"""Initialize instance properties."""
self.lj = lj
def multiple(self):
"""Update the layouts.json file."""
# APP-86 - sort output data by name
self.update_sort_outputs()
data = self.lj.model.json(
by_alias=True, exclude_defaults=True, exclude_none=True, indent=2, sort_keys=True
)
self.lj.write(data)
def update_sort_outputs(self):
"""Sort output field by name."""
# APP-86 - sort output data by name
self.lj.model.outputs = sorted(
self.lj.model.dict().get('outputs', []), key=lambda i: i['name'] # type: ignore
)