1
|
|
|
# Copyright 2014 Diamond Light Source Ltd. |
2
|
|
|
# |
3
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
4
|
|
|
# you may not use this file except in compliance with the License. |
5
|
|
|
# You may obtain a copy of the License at |
6
|
|
|
# |
7
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0 |
8
|
|
|
# |
9
|
|
|
# Unless required by applicable law or agreed to in writing, software |
10
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS, |
11
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12
|
|
|
# See the License for the specific language governing permissions and |
13
|
|
|
# limitations under the License. |
14
|
|
|
|
15
|
|
|
""" |
16
|
|
|
.. module:: content |
17
|
|
|
:platform: Unix |
18
|
|
|
:synopsis: Content class for the configurator |
19
|
|
|
|
20
|
|
|
.. moduleauthor:: Nicola Wadeson <[email protected]> |
21
|
|
|
|
22
|
|
|
""" |
23
|
|
|
import re |
24
|
|
|
import os |
25
|
|
|
import inspect |
26
|
|
|
|
27
|
|
|
from savu.plugins import utils as pu |
28
|
|
|
from savu.data.plugin_list import PluginList |
29
|
|
|
import scripts.config_generator.parameter_utils as param_u |
30
|
|
|
|
31
|
|
|
from . import mutations |
32
|
|
|
|
33
|
|
|
|
34
|
|
|
class Content(object): |
35
|
|
|
def __init__(self, filename=None, level="basic"): |
36
|
|
|
self.disp_level = level |
37
|
|
|
self.plugin_list = PluginList() |
38
|
|
|
self.plugin_mutations = mutations.plugin_mutations |
39
|
|
|
self.param_mutations = mutations.param_mutations |
40
|
|
|
self.filename = filename |
41
|
|
|
self._finished = False |
42
|
|
|
self.failed = {} |
43
|
|
|
self.expand_dim = None |
44
|
|
|
|
45
|
|
|
def set_finished(self, check="y"): |
46
|
|
|
self._finished = True if check.lower() == "y" else False |
47
|
|
|
|
48
|
|
|
def is_finished(self): |
49
|
|
|
return self._finished |
50
|
|
|
|
51
|
|
|
def fopen(self, infile, update=False, skip=False): |
52
|
|
|
if os.path.exists(infile): |
53
|
|
|
self.plugin_list._populate_plugin_list(infile, active_pass=True) |
54
|
|
|
else: |
55
|
|
|
raise Exception("INPUT ERROR: The file does not exist.") |
56
|
|
|
self.filename = infile |
57
|
|
|
if update: |
58
|
|
|
self.plugin_mutations = self.check_mutations( |
59
|
|
|
self.plugin_mutations |
60
|
|
|
) |
61
|
|
|
self.param_mutations = self.check_mutations(self.param_mutations) |
62
|
|
|
self._apply_plugin_updates(skip) |
63
|
|
|
|
64
|
|
|
def check_mutations(self, mut_dict: dict): |
65
|
|
|
plist_version = self._version_to_float(self.plugin_list.version) |
66
|
|
|
# deleting elements while iterating invalidates the iterator |
67
|
|
|
# which raises a RuntimeError in Python 3. |
68
|
|
|
# Instead a copy of the dict is mutated and returned |
69
|
|
|
mut_dict_copy = mut_dict.copy() |
70
|
|
|
for key, subdict in mut_dict.items(): |
71
|
|
|
if "up_to_version" in subdict.keys(): |
72
|
|
|
up_to_version = self._version_to_float( |
73
|
|
|
subdict["up_to_version"] |
74
|
|
|
) |
75
|
|
|
if plist_version >= up_to_version: |
76
|
|
|
del mut_dict_copy[key] |
77
|
|
|
return mut_dict_copy |
78
|
|
|
|
79
|
|
|
def _version_to_float(self, version): |
80
|
|
|
if version is None: |
81
|
|
|
return 0 |
82
|
|
|
if isinstance(version, bytes): |
83
|
|
|
version = version.decode("ascii") |
84
|
|
|
split_vals = version.split(".") |
85
|
|
|
return float(".".join([split_vals[0], "".join(split_vals[1:])])) |
86
|
|
|
|
87
|
|
|
def display(self, formatter, **kwargs): |
88
|
|
|
# Set current level |
89
|
|
|
if "current_level" not in list(kwargs.keys()): |
90
|
|
|
kwargs["current_level"] = self.disp_level |
91
|
|
|
if ( |
92
|
|
|
"disp_level" in list(kwargs.keys()) |
93
|
|
|
and kwargs["disp_level"] is True |
94
|
|
|
): |
95
|
|
|
# Display level |
96
|
|
|
print(f"Level is set at '{kwargs['current_level']}'") |
97
|
|
|
else: |
98
|
|
|
# Display parameter |
99
|
|
|
kwargs["expand_dim"] = self.expand_dim |
100
|
|
|
print("\n" + formatter._get_string(**kwargs) + "\n") |
101
|
|
|
|
102
|
|
|
def check_file(self, filename): |
103
|
|
|
if not filename: |
104
|
|
|
raise Exception( |
105
|
|
|
"INPUT ERROR: Please specify the output filepath." |
106
|
|
|
) |
107
|
|
|
path = os.path.dirname(filename) |
108
|
|
|
path = path if path else "." |
109
|
|
|
if not os.path.exists(path): |
110
|
|
|
file_error = "INPUT_ERROR: Incorrect filepath." |
111
|
|
|
raise Exception(file_error) |
112
|
|
|
|
113
|
|
|
def save(self, filename, check="y", template=False): |
114
|
|
|
self.check_plugin_list_exists() |
115
|
|
|
# Check if a loader and saver are present. |
116
|
|
|
self.plugin_list._check_loaders() |
117
|
|
|
if check.lower() == "y": |
118
|
|
|
print(f"Saving file {filename}") |
119
|
|
|
if template: |
120
|
|
|
self.plugin_list.add_template(create=True) |
121
|
|
|
self.plugin_list._save_plugin_list(filename) |
122
|
|
|
else: |
123
|
|
|
print("The process list has NOT been saved.") |
124
|
|
|
|
125
|
|
|
def clear(self, check="y"): |
126
|
|
|
if check.lower() == "y": |
127
|
|
|
self.expand_dim = None |
128
|
|
|
self.plugin_list.plugin_list = [] |
129
|
|
|
|
130
|
|
|
def check_plugin_list_exists(self): |
131
|
|
|
""" Check if plugin list is populated. """ |
132
|
|
|
pos_list = self.get_positions() |
133
|
|
|
if not pos_list: |
134
|
|
|
print("There are no items to access in your list.") |
135
|
|
|
raise Exception("Please add an item to the process list.") |
136
|
|
|
|
137
|
|
|
def add(self, name, str_pos): |
138
|
|
|
self.check_for_plugin_failure(name) |
139
|
|
|
plugin = pu.plugins[name]() |
140
|
|
|
plugin.get_plugin_tools()._populate_default_parameters() |
141
|
|
|
pos, str_pos = self.convert_pos(str_pos) |
142
|
|
|
self.insert(plugin, pos, str_pos) |
143
|
|
|
|
144
|
|
|
def refresh(self, str_pos, defaults=False, change=False): |
145
|
|
|
pos = self.find_position(str_pos) |
146
|
|
|
plugin_entry = self.plugin_list.plugin_list[pos] |
147
|
|
|
name = change if change else plugin_entry["name"] |
148
|
|
|
active = plugin_entry["active"] |
149
|
|
|
plugin = pu.plugins[name]() |
150
|
|
|
plugin.get_plugin_tools()._populate_default_parameters() |
151
|
|
|
keep = self.get(pos)["data"] if not defaults else None |
152
|
|
|
self.insert(plugin, pos, str_pos, replace=True) |
153
|
|
|
self.plugin_list.plugin_list[pos]["active"] = active |
154
|
|
|
if keep: |
155
|
|
|
self._update_parameters(plugin, name, keep, str_pos) |
156
|
|
|
|
157
|
|
|
|
158
|
|
|
def check_for_plugin_failure(self, name): |
159
|
|
|
"""Check if the plugin failed to load |
160
|
|
|
|
161
|
|
|
:param name: plugin name |
162
|
|
|
""" |
163
|
|
|
if (name not in list(pu.plugins.keys()) |
164
|
|
|
or self.plugin_in_failed_dict(name)): |
165
|
|
|
if self.plugin_in_failed_dict(name): |
166
|
|
|
msg = f"IMPORT ERROR: {name} is unavailable due to" \ |
167
|
|
|
f" the following error:\n\t{self.failed[name]}" |
168
|
|
|
raise Exception(msg) |
169
|
|
|
raise Exception("INPUT ERROR: Unknown plugin %s" % name) |
170
|
|
|
|
171
|
|
|
|
172
|
|
|
def plugin_in_failed_dict(self, name): |
173
|
|
|
"""Check if plugin in failed dictionary |
174
|
|
|
|
175
|
|
|
:param name: plugin name |
176
|
|
|
:return: True if plugin name in the list of failed plugins |
177
|
|
|
""" |
178
|
|
|
failed_plugin_list = list(self.failed.keys()) if self.failed else [] |
179
|
|
|
return True if name in failed_plugin_list else False |
180
|
|
|
|
181
|
|
|
|
182
|
|
|
def check_preview_param(self, plugin_pos): |
183
|
|
|
""" Check that the plugin position number is valid and it contains |
184
|
|
|
a preview parameter |
185
|
|
|
|
186
|
|
|
:param plugin_pos: |
187
|
|
|
:return: |
188
|
|
|
""" |
189
|
|
|
pos = self.find_position(plugin_pos) |
190
|
|
|
plugin_entry = self.plugin_list.plugin_list[pos] |
191
|
|
|
parameters = plugin_entry["data"] |
192
|
|
|
if "preview" not in parameters: |
193
|
|
|
raise Exception("You can only use this command with " |
194
|
|
|
"plugins containing the preview parameter") |
195
|
|
|
|
196
|
|
|
def set_preview_display(self, expand_off, expand_dim, dim_view, |
197
|
|
|
plugin_pos): |
198
|
|
|
"""Set the dimensions_to_display value to "off" to prevent the |
199
|
|
|
preview parameter being shown in it's expanded form. |
200
|
|
|
|
201
|
|
|
If dimensions_to_display = "all", then all dimension slices are shown. |
202
|
|
|
If a number is provided to dim_view, that dimension is shown. |
203
|
|
|
|
204
|
|
|
:param expand_off: True if expand display should be turned off |
205
|
|
|
:param expand_dim: The dimension number to display, or "all" |
206
|
|
|
:param dim_view: True if only a certain dimension should be shown |
207
|
|
|
:param plugin_pos: Plugin position |
208
|
|
|
""" |
209
|
|
|
if expand_off is True: |
210
|
|
|
self.expand_dim = None |
211
|
|
|
print(f"Expand diplay has been turned off") |
212
|
|
|
else: |
213
|
|
|
self.check_preview_param(plugin_pos) |
214
|
|
|
dims_to_display = expand_dim if dim_view else "all" |
215
|
|
|
self.expand_dim = dims_to_display |
216
|
|
|
|
217
|
|
|
def _update_parameters(self, plugin, name, keep, str_pos): |
218
|
|
|
union_params = set(keep).intersection(set(plugin.parameters)) |
219
|
|
|
# Names of the parameter names present in both lists |
220
|
|
|
for param in union_params: |
221
|
|
|
self.modify(str_pos, param, keep[param], ref=True) |
222
|
|
|
# add any parameter mutations here |
223
|
|
|
classes = [c.__name__ for c in inspect.getmro(plugin.__class__)] |
224
|
|
|
m_dict = self.param_mutations |
225
|
|
|
keys = [k for k in list(m_dict.keys()) if k in classes] |
226
|
|
|
|
227
|
|
|
changes = False |
228
|
|
|
for k in keys: |
229
|
|
|
for entry in m_dict[k]["params"]: |
230
|
|
|
if entry["old"] in list(keep.keys()): |
231
|
|
|
changes = True |
232
|
|
|
val = keep[entry["old"]] |
233
|
|
|
if "eval" in list(entry.keys()): |
234
|
|
|
val = eval(entry["eval"]) |
235
|
|
|
self.modify(str_pos, entry["new"], val, ref=True) |
236
|
|
|
if changes: |
237
|
|
|
mutations.param_change_str(keep, plugin.parameters, name, keys) |
238
|
|
|
|
239
|
|
|
def _apply_plugin_updates(self, skip=False): |
240
|
|
|
# Update old process lists that start from 0 |
241
|
|
|
the_list = self.plugin_list.plugin_list |
242
|
|
|
if "pos" in list(the_list[0].keys()) and the_list[0]["pos"] == "0": |
243
|
|
|
self.increment_positions() |
244
|
|
|
|
245
|
|
|
missing = [] |
246
|
|
|
pos = len(the_list) - 1 |
247
|
|
|
notices = mutations.plugin_notices |
248
|
|
|
|
249
|
|
|
for plugin in the_list[::-1]: |
250
|
|
|
# update old process lists to include 'active' flag |
251
|
|
|
if "active" not in list(plugin.keys()): |
252
|
|
|
plugin["active"] = True |
253
|
|
|
|
254
|
|
|
while True: |
255
|
|
|
name = the_list[pos]["name"] |
256
|
|
|
if name in notices.keys(): |
257
|
|
|
print(notices[name]["desc"]) |
258
|
|
|
|
259
|
|
|
# if a plugin is missing from all available plugins |
260
|
|
|
# then look for mutations in the plugin name |
261
|
|
|
search = True if name not in pu.plugins.keys() else False |
262
|
|
|
found = self._mutate_plugins(name, pos, search=search) |
263
|
|
|
if search and not found: |
264
|
|
|
str_pos = self.plugin_list.plugin_list[pos]["pos"] |
265
|
|
|
missing.append([name, str_pos]) |
266
|
|
|
self.remove(pos) |
267
|
|
|
pos -= 1 |
268
|
|
|
if name == the_list[pos]["name"]: |
269
|
|
|
break |
270
|
|
|
pos -= 1 |
271
|
|
|
|
272
|
|
|
for name, pos in missing[::-1]: |
273
|
|
|
if skip: |
274
|
|
|
print(f"Skipping plugin {pos}: {name}") |
275
|
|
|
else: |
276
|
|
|
message = ( |
277
|
|
|
f"\nPLUGIN ERROR: The plugin {name} is " |
278
|
|
|
f"unavailable in this version of Savu. \n Type open" |
279
|
|
|
f" -s <process_list> to skip the broken plugin." |
280
|
|
|
) |
281
|
|
|
raise Exception(f"Incompatible process list. {message}") |
282
|
|
|
|
283
|
|
|
def _mutate_plugins(self, name, pos, search=False): |
284
|
|
|
""" Perform plugin mutations. """ |
285
|
|
|
# check for case changes in plugin name |
286
|
|
|
if search: |
287
|
|
|
for key in pu.plugins.keys(): |
288
|
|
|
if name.lower() == key.lower(): |
289
|
|
|
str_pos = self.plugin_list.plugin_list[pos]["pos"] |
290
|
|
|
self.refresh(str_pos, change=key) |
291
|
|
|
return True |
292
|
|
|
|
293
|
|
|
# check mutations dict |
294
|
|
|
m_dict = self.plugin_mutations |
295
|
|
|
if name in m_dict.keys(): |
296
|
|
|
mutate = m_dict[name] |
297
|
|
|
if "replace" in mutate.keys(): |
298
|
|
|
if mutate["replace"] in list(pu.plugins.keys()): |
299
|
|
|
str_pos = self.plugin_list.plugin_list[pos]["pos"] |
300
|
|
|
self.refresh(str_pos, change=mutate["replace"]) |
301
|
|
|
print(mutate["desc"]) |
302
|
|
|
return True |
303
|
|
|
raise Exception( |
304
|
|
|
f"Replacement plugin {mutate['replace']} " |
305
|
|
|
f"unavailable for {name}" |
306
|
|
|
) |
307
|
|
|
elif "remove" in mutate.keys(): |
308
|
|
|
self.remove(pos) |
309
|
|
|
print(mutate["desc"]) |
310
|
|
|
else: |
311
|
|
|
raise Exception("Unknown mutation type.") |
312
|
|
|
return False |
313
|
|
|
|
314
|
|
|
def move(self, old, new): |
315
|
|
|
old_pos = self.find_position(old) |
316
|
|
|
entry = self.plugin_list.plugin_list[old_pos] |
317
|
|
|
self.remove(old_pos) |
318
|
|
|
new_pos, new = self.convert_pos(new) |
319
|
|
|
name = entry["name"] |
320
|
|
|
self.insert(pu.plugins[name](), new_pos, new) |
321
|
|
|
self.plugin_list.plugin_list[new_pos] = entry |
322
|
|
|
self.plugin_list.plugin_list[new_pos]["pos"] = new |
323
|
|
|
|
324
|
|
|
def modify(self, pos_str, param_name, value, default=False, ref=False, |
325
|
|
|
dim=False): |
326
|
|
|
"""Modify the plugin at pos_str and the parameter at param_name |
327
|
|
|
The new value will be set if it is valid. |
328
|
|
|
|
329
|
|
|
:param pos_str: The plugin position |
330
|
|
|
:param param_name: The parameter position/name |
331
|
|
|
:param value: The new parameter value |
332
|
|
|
:param default: True if value should be reverted to the default |
333
|
|
|
:param ref: boolean Refresh the plugin |
334
|
|
|
:param dim: The dimension to be modified |
335
|
|
|
|
336
|
|
|
returns: A boolean True if the value is a valid input for the |
337
|
|
|
selected parameter |
338
|
|
|
""" |
339
|
|
|
pos = self.find_position(pos_str) |
340
|
|
|
plugin_entry = self.plugin_list.plugin_list[pos] |
341
|
|
|
tools = plugin_entry["tools"] |
342
|
|
|
parameters = plugin_entry["data"] |
343
|
|
|
params = plugin_entry["param"] |
344
|
|
|
param_name, value = self.setup_modify(params, param_name, value, ref) |
345
|
|
|
default_str = ["-d", "--default"] |
346
|
|
|
if default or value in default_str: |
347
|
|
|
value = tools.get_default_value(param_name) |
348
|
|
|
self._change_value(param_name, value, tools, parameters) |
349
|
|
|
valid_modification = True |
350
|
|
|
else: |
351
|
|
|
value = self._catch_parameter_tuning_syntax(value, param_name) |
352
|
|
|
valid_modification = self.modify_main( |
353
|
|
|
param_name, value, tools, parameters, dim |
354
|
|
|
) |
355
|
|
|
return valid_modification |
356
|
|
|
|
357
|
|
|
def _catch_parameter_tuning_syntax(self, value, param_name): |
358
|
|
|
"""Check if the new parameter value seems like it is written |
359
|
|
|
in parameter tuning syntax with colons. If it is, then append |
360
|
|
|
a semi colon onto the end. |
361
|
|
|
|
362
|
|
|
:param value: new parameter value |
363
|
|
|
:param param_name: |
364
|
|
|
:return: modified value with semi colon appended |
365
|
|
|
""" |
366
|
|
|
if self._is_multi_parameter_syntax(value) \ |
367
|
|
|
and param_name != "preview": |
368
|
|
|
# Assume parameter tuning syntax is being used |
369
|
|
|
value = f"{value};" |
370
|
|
|
print("Parameter tuning syntax applied") |
371
|
|
|
return value |
372
|
|
|
|
373
|
|
|
def _is_multi_parameter_syntax(self, value): |
374
|
|
|
"""If the value contains two colons, is not a dictionary, |
375
|
|
|
and doesnt already contain a semi colon, then assume that |
376
|
|
|
it is using parameter tuning syntax |
377
|
|
|
|
378
|
|
|
:param value: new parameter value |
379
|
|
|
:return boolean True if parameter tuning syntax is being used |
380
|
|
|
""" |
381
|
|
|
isdict = re.findall(r"[\{\}]+", value) |
382
|
|
|
return (isinstance(value, str) |
383
|
|
|
and value.count(":") >= 2 |
384
|
|
|
and not isdict |
385
|
|
|
and ";" not in value) |
386
|
|
|
|
387
|
|
|
def setup_modify(self, params, param_name, value, ref): |
388
|
|
|
"""Get the parameter keys in the correct order and find |
389
|
|
|
the parameter name string |
390
|
|
|
|
391
|
|
|
:param params: The plugin parameters |
392
|
|
|
:param param_name: The parameter position/name |
393
|
|
|
:param value: The new parameter value |
394
|
|
|
:param ref: boolean Refresh the plugin |
395
|
|
|
|
396
|
|
|
return: param_name str to avoid discrepancy, value |
397
|
|
|
""" |
398
|
|
|
if ref: |
399
|
|
|
# For a refresh, refresh all keys, including those with |
400
|
|
|
# dependencies (which have the display off) |
401
|
|
|
keys = params.keys() |
402
|
|
|
else: |
403
|
|
|
# Select the correct group and order of parameters according to that |
404
|
|
|
# on display to the user. This ensures correct parameter is modified. |
405
|
|
|
keys = pu.set_order_by_visibility(params) |
406
|
|
|
value = self.value(value) |
407
|
|
|
param_name = pu.param_to_str(param_name, keys) |
408
|
|
|
return param_name, value |
409
|
|
|
|
410
|
|
|
def modify_main(self, param_name, value, tools, parameters, dim): |
411
|
|
|
"""Check the parameter is within the current parameter list. |
412
|
|
|
Check the new parameter value is valid, modify the parameter |
413
|
|
|
value, update defaults, check if dependent parameters should |
414
|
|
|
be made visible or hidden. |
415
|
|
|
|
416
|
|
|
:param param_name: The parameter position/name |
417
|
|
|
:param value: The new parameter value |
418
|
|
|
:param tools: The plugin tools |
419
|
|
|
:param parameters: The plugin parameters |
420
|
|
|
:param dim: The dimensions |
421
|
|
|
|
422
|
|
|
returns: A boolean True if the value is a valid input for the |
423
|
|
|
selected parameter |
424
|
|
|
""" |
425
|
|
|
parameter_valid = False |
426
|
|
|
current_parameter_details = tools.param.get(param_name) |
427
|
|
|
|
428
|
|
|
# If dimensions are provided then alter preview param |
429
|
|
|
if self.preview_dimension_to_modify(dim, param_name): |
430
|
|
|
# Filter the dimension, dim1 or dim1.start |
431
|
|
|
dim, _slice = self._separate_dimension_and_slice(dim) |
432
|
|
|
value = self.modify_preview( |
433
|
|
|
parameters, param_name, value, dim, _slice |
434
|
|
|
) |
435
|
|
|
|
436
|
|
|
# If found, then the parameter is within the current parameter list |
437
|
|
|
# displayed to the user |
438
|
|
|
if current_parameter_details: |
439
|
|
|
value_check = pu._dumps(value) |
440
|
|
|
parameter_valid, error_str = param_u.is_valid( |
441
|
|
|
param_name, value_check, current_parameter_details |
442
|
|
|
) |
443
|
|
|
if parameter_valid: |
444
|
|
|
self._change_value(param_name, value, tools, parameters) |
445
|
|
|
else: |
446
|
|
|
value = str(value) |
447
|
|
|
display_value = f"{value[0:12]}.." if len(value) > 12 \ |
448
|
|
|
else value |
449
|
|
|
print(f"ERROR: The input value {display_value} " |
450
|
|
|
f"for {param_name} is not correct.") |
451
|
|
|
print(error_str) |
452
|
|
|
else: |
453
|
|
|
print("Not in parameter keys.") |
454
|
|
|
return parameter_valid |
455
|
|
|
|
456
|
|
|
def _change_value(self, param_name, value, tools, parameters): |
457
|
|
|
""" Change the parameter "param_name" value inside the parameters list |
458
|
|
|
Update feedback messages for various dependant parameters |
459
|
|
|
|
460
|
|
|
:param param_name: The parameter position/name |
461
|
|
|
:param value: The new parameter value |
462
|
|
|
:param tools: The plugin tools |
463
|
|
|
:param parameters: The plugin parameters |
464
|
|
|
""" |
465
|
|
|
# Save the value |
466
|
|
|
parameters[param_name] = value |
467
|
|
|
tools.warn_dependents(param_name, value) |
468
|
|
|
# Update the list of parameters to hide those dependent on others |
469
|
|
|
tools.check_dependencies(parameters) |
470
|
|
|
|
471
|
|
|
def check_required_args(self, value, required): |
472
|
|
|
"""Check required argument 'value' is present |
473
|
|
|
|
474
|
|
|
:param value: Argument value |
475
|
|
|
:param required: bool, True if the argument is required |
476
|
|
|
""" |
477
|
|
|
if required and (not value): |
478
|
|
|
raise Exception("Please enter a value") |
479
|
|
|
|
480
|
|
|
if (not required) and value: |
481
|
|
|
raise Exception(f"Unrecognised argument: {value}") |
482
|
|
|
|
483
|
|
|
def preview_dimension_to_modify(self, dim, param_name): |
484
|
|
|
"""Check that the dimension string is only present when the parameter |
485
|
|
|
to modify is the preview parameter |
486
|
|
|
|
487
|
|
|
:param dim: Dimension string |
488
|
|
|
:param param_name: The parameter name (of the parameter to be modified) |
489
|
|
|
:return: True if dimension string is provided and the parameter to modify |
490
|
|
|
the preview parameter |
491
|
|
|
""" |
492
|
|
|
if dim: |
493
|
|
|
if param_name == "preview": |
494
|
|
|
return True |
495
|
|
|
else: |
496
|
|
|
raise Exception( |
497
|
|
|
"Please only use the dimension syntax when " |
498
|
|
|
"modifying the preview parameter." |
499
|
|
|
) |
500
|
|
|
return False |
501
|
|
|
|
502
|
|
|
def modify_dimensions(self, pos_str, dim, check="y"): |
503
|
|
|
"""Modify the plugin preview value. Remove or add dimensions |
504
|
|
|
to the preview parameter until the provided dimension number |
505
|
|
|
is reached. |
506
|
|
|
|
507
|
|
|
:param pos_str: The plugin position |
508
|
|
|
:param dim: The new number of dimensions |
509
|
|
|
:return True if preview is modified |
510
|
|
|
""" |
511
|
|
|
pos = self.find_position(pos_str) |
512
|
|
|
plugin_entry = self.plugin_list.plugin_list[pos] |
513
|
|
|
parameters = plugin_entry["data"] |
514
|
|
|
self.check_param_exists(parameters, "preview") |
515
|
|
|
current_prev_list = pu._dumps(parameters["preview"]) |
516
|
|
|
if not isinstance(current_prev_list, list): |
517
|
|
|
# Temporarily cover dict instance for preview |
518
|
|
|
print("This command is only possible for preview " |
519
|
|
|
"values of the type list") |
520
|
|
|
return False |
521
|
|
|
pu.check_valid_dimension(dim, []) |
522
|
|
|
if check.lower() == "y": |
523
|
|
|
while len(current_prev_list) > dim: |
524
|
|
|
current_prev_list.pop() |
525
|
|
|
while len(current_prev_list) < dim: |
526
|
|
|
current_prev_list.append(":") |
527
|
|
|
parameters["preview"] = current_prev_list |
528
|
|
|
return True |
529
|
|
|
return False |
530
|
|
|
|
531
|
|
|
def check_param_exists(self, parameters, pname): |
532
|
|
|
"""Check the parameter is present in the current parameter list |
533
|
|
|
|
534
|
|
|
:param parameters: Dictionary of parameters |
535
|
|
|
:param pname: Parameter name |
536
|
|
|
:return: |
537
|
|
|
""" |
538
|
|
|
if not parameters.get(pname): |
539
|
|
|
raise Exception( |
540
|
|
|
f"The {pname} parameter is not available" f" for this plugin." |
541
|
|
|
) |
542
|
|
|
|
543
|
|
|
def value(self, value): |
544
|
|
|
if not value.count(";"): |
545
|
|
|
try: |
546
|
|
|
value = eval(value) |
547
|
|
|
except (NameError, SyntaxError): |
548
|
|
|
try: |
549
|
|
|
value = eval(f"'{value}'") |
550
|
|
|
# if there is one quotation mark there will be an error |
551
|
|
|
except EOFError: |
552
|
|
|
raise EOFError( |
553
|
|
|
"There is an end of line error. Please check your" |
554
|
|
|
' input for the character "\'".' |
555
|
|
|
) |
556
|
|
|
except SyntaxError: |
557
|
|
|
raise SyntaxError( |
558
|
|
|
"There is a syntax error. Please check your input." |
559
|
|
|
) |
560
|
|
|
except: |
561
|
|
|
raise Exception("Please check your input.") |
562
|
|
|
return value |
563
|
|
|
|
564
|
|
|
def convert_to_ascii(self, value): |
565
|
|
|
ascii_list = [] |
566
|
|
|
for v in value: |
567
|
|
|
ascii_list.append(v.encode("ascii", "ignore")) |
568
|
|
|
return ascii_list |
569
|
|
|
|
570
|
|
|
def on_and_off(self, str_pos, index): |
571
|
|
|
print(("switching plugin %s %s" % (str_pos, index))) |
572
|
|
|
status = True if index == "ON" else False |
573
|
|
|
pos = self.find_position(str_pos) |
574
|
|
|
self.plugin_list.plugin_list[pos]["active"] = status |
575
|
|
|
|
576
|
|
|
def convert_pos(self, str_pos): |
577
|
|
|
""" Converts the display position (input) to the equivalent numerical |
578
|
|
|
position and updates the display position if required. |
579
|
|
|
|
580
|
|
|
:param str_pos: the plugin display position (input) string. |
581
|
|
|
:returns: the equivalent numerical position of str_pos and and updated\ |
582
|
|
|
str_pos. |
583
|
|
|
:rtype: (pos, str_pos) |
584
|
|
|
""" |
585
|
|
|
pos_list = self.get_split_positions() |
586
|
|
|
num = re.findall(r"\d+", str_pos)[0] |
587
|
|
|
letter = re.findall("[a-z]", str_pos) |
588
|
|
|
entry = [num, letter[0]] if letter else [num] |
589
|
|
|
|
590
|
|
|
# full value already exists in the list |
591
|
|
|
if entry in pos_list: |
592
|
|
|
index = pos_list.index(entry) |
593
|
|
|
return self.inc_positions(index, pos_list, entry, 1) |
594
|
|
|
|
595
|
|
|
# only the number exists in the list |
596
|
|
|
num_list = [pos_list[i][0] for i in range(len(pos_list))] |
597
|
|
|
if entry[0] in num_list: |
598
|
|
|
start = num_list.index(entry[0]) |
599
|
|
|
if len(entry) == 2: |
600
|
|
|
if len(pos_list[start]) == 2: |
601
|
|
|
idx = int([i for i in range(len(num_list)) if |
602
|
|
|
(num_list[i] == entry[0])][-1]) + 1 |
603
|
|
|
entry = [entry[0], str(chr(ord(pos_list[idx - 1][1]) + 1))] |
604
|
|
|
return idx, ''.join(entry) |
605
|
|
|
if entry[1] == 'a': |
606
|
|
|
self.plugin_list.plugin_list[start]['pos'] = entry[0] + 'b' |
607
|
|
|
return start, ''.join(entry) |
608
|
|
|
else: |
609
|
|
|
self.plugin_list.plugin_list[start]['pos'] = entry[0] + 'a' |
610
|
|
|
return start + 1, entry[0] + 'b' |
611
|
|
|
return self.inc_positions(start, pos_list, entry, 1) |
612
|
|
|
|
613
|
|
|
# number not in list |
614
|
|
|
entry[0] = str(int(num_list[-1]) + 1 if num_list else 1) |
615
|
|
|
if len(entry) == 2: |
616
|
|
|
entry[1] = "a" |
617
|
|
|
return len(self.plugin_list.plugin_list), "".join(entry) |
618
|
|
|
|
619
|
|
|
def increment_positions(self): |
620
|
|
|
"""Update old process lists that start plugin numbering from 0 to |
621
|
|
|
start from 1.""" |
622
|
|
|
for plugin in self.plugin_list.plugin_list: |
623
|
|
|
str_pos = plugin["pos"] |
624
|
|
|
num = str(int(re.findall(r"\d+", str_pos)[0]) + 1) |
625
|
|
|
letter = re.findall("[a-z]", str_pos) |
626
|
|
|
plugin["pos"] = "".join([num, letter[0]] if letter else [num]) |
627
|
|
|
|
628
|
|
|
def get_positions(self): |
629
|
|
|
""" Get a list of all current plugin entry positions. """ |
630
|
|
|
elems = self.plugin_list.plugin_list |
631
|
|
|
pos_list = [] |
632
|
|
|
for e in elems: |
633
|
|
|
pos_list.append(e["pos"]) |
634
|
|
|
return pos_list |
635
|
|
|
|
636
|
|
|
def get_param_arg_str(self, pos_str, subelem): |
637
|
|
|
"""Get the name of the parameter so that the display lists the |
638
|
|
|
correct item when the parameter order has been updated |
639
|
|
|
|
640
|
|
|
:param pos_str: The plugin position |
641
|
|
|
:param subelem: The parameter |
642
|
|
|
:return: The plugin.parameter_name argument |
643
|
|
|
""" |
644
|
|
|
pos = self.find_position(pos_str) |
645
|
|
|
current_parameter_list = self.plugin_list.plugin_list[pos]["param"] |
646
|
|
|
current_parameter_list_ordered = pu.set_order_by_visibility( |
647
|
|
|
current_parameter_list |
648
|
|
|
) |
649
|
|
|
param_name = pu.param_to_str(subelem, current_parameter_list_ordered) |
650
|
|
|
param_argument = pos_str + "." + param_name |
651
|
|
|
return param_argument |
652
|
|
|
|
653
|
|
|
def get_split_positions(self): |
654
|
|
|
""" Separate numbers and letters in positions. """ |
655
|
|
|
positions = self.get_positions() |
656
|
|
|
split_pos = [] |
657
|
|
|
for i in range(len(positions)): |
658
|
|
|
num = re.findall(r"\d+", positions[i])[0] |
659
|
|
|
letter = re.findall("[a-z]", positions[i]) |
660
|
|
|
split_pos.append([num, letter[0]] if letter else [num]) |
661
|
|
|
return split_pos |
662
|
|
|
|
663
|
|
|
def find_position(self, pos): |
664
|
|
|
""" Find the numerical index of a position (a string). """ |
665
|
|
|
pos_list = self.get_positions() |
666
|
|
|
if not pos_list: |
667
|
|
|
print("There are no items to access in your list.") |
668
|
|
|
raise Exception("Please add an item to the process list.") |
669
|
|
|
else: |
670
|
|
|
if pos not in pos_list: |
671
|
|
|
raise ValueError("Incorrect plugin position.") |
672
|
|
|
return pos_list.index(pos) |
673
|
|
|
|
674
|
|
|
def inc_positions(self, start, pos_list, entry, inc): |
675
|
|
|
if len(entry) == 1: |
676
|
|
|
self.inc_numbers(start, pos_list, inc) |
677
|
|
|
else: |
678
|
|
|
idx = [ |
679
|
|
|
i |
680
|
|
|
for i in range(start, len(pos_list)) |
681
|
|
|
if pos_list[i][0] == entry[0] |
682
|
|
|
] |
683
|
|
|
self.inc_letters(idx, pos_list, inc) |
684
|
|
|
return start, "".join(entry) |
685
|
|
|
|
686
|
|
|
def inc_numbers(self, start, pos_list, inc): |
687
|
|
|
for i in range(start, len(pos_list)): |
688
|
|
|
pos_list[i][0] = str(int(pos_list[i][0]) + inc) |
689
|
|
|
self.plugin_list.plugin_list[i]["pos"] = "".join(pos_list[i]) |
690
|
|
|
|
691
|
|
|
def inc_letters(self, idx, pos_list, inc): |
692
|
|
|
for i in idx: |
693
|
|
|
pos_list[i][1] = str(chr(ord(pos_list[i][1]) + inc)) |
694
|
|
|
self.plugin_list.plugin_list[i]["pos"] = "".join(pos_list[i]) |
695
|
|
|
|
696
|
|
|
def split_plugin_string(self, start, stop, subelem_view=False): |
697
|
|
|
"""Find the start and stop number for the plugin range selected. |
698
|
|
|
|
699
|
|
|
:param start: Plugin starting index (including a subelem value |
700
|
|
|
if permitted) |
701
|
|
|
:param stop: Plugin stopping index |
702
|
|
|
:param subelem_view: False if subelem value not permitted |
703
|
|
|
:return: range_dict containing start stop (and possible subelem) |
704
|
|
|
""" |
705
|
|
|
range_dict = {} |
706
|
|
|
if start: |
707
|
|
|
if subelem_view and "." in start: |
708
|
|
|
start, stop, subelem = self._split_subelem(start) |
709
|
|
|
range_dict["subelem"] = subelem |
710
|
|
|
else: |
711
|
|
|
start, stop = self._get_start_stop(start, stop) |
712
|
|
|
range_dict["start"] = start |
713
|
|
|
range_dict["stop"] = stop |
714
|
|
|
return range_dict |
715
|
|
|
|
716
|
|
|
def _get_start_stop(self, start, stop): |
717
|
|
|
"""Find the start and stop number for the plugin range selected """ |
718
|
|
|
start = self.find_position(start) |
719
|
|
|
stop = self.find_position(stop) + 1 if stop else start + 1 |
720
|
|
|
return start, stop |
721
|
|
|
|
722
|
|
|
def _split_subelem(self, start, config_disp=True): |
723
|
|
|
"""Separate the start string containing the plugin number, |
724
|
|
|
parameter(subelement), dimension and command |
725
|
|
|
|
726
|
|
|
:param start: The plugin to start at |
727
|
|
|
:param config_disp: True if command and dimension arguments |
728
|
|
|
are not permitted |
729
|
|
|
:return: start plugin, range_dict containing a subelem |
730
|
|
|
if a parameter is specified |
731
|
|
|
""" |
732
|
|
|
start, subelem, dim, command = self.separate_plugin_subelem( |
733
|
|
|
start, config_disp |
734
|
|
|
) |
735
|
|
|
start, stop = self._get_start_stop(start, "") |
736
|
|
|
return start, stop, subelem |
737
|
|
|
|
738
|
|
|
def _check_command_valid(self, plugin_param, config_disp): |
739
|
|
|
"""Check the plugin_param string length |
740
|
|
|
|
741
|
|
|
:param plugin_param: The string containing plugin number, parameter, |
742
|
|
|
and command |
743
|
|
|
:param config_disp: bool, True if command and dimension arguments are |
744
|
|
|
not permitted |
745
|
|
|
""" |
746
|
|
|
if config_disp: |
747
|
|
|
if not 1 < len(plugin_param) < 3: |
748
|
|
|
raise ValueError( |
749
|
|
|
"Use either 'plugin_pos.param_name' or" |
750
|
|
|
" 'plugin_pos.param_no'" |
751
|
|
|
) |
752
|
|
|
else: |
753
|
|
|
# The modify command is being used |
754
|
|
|
if len(plugin_param) <= 1: |
755
|
|
|
raise ValueError( |
756
|
|
|
"Please enter the plugin parameter to modify" |
757
|
|
|
". Either 'plugin_pos.param_name' or" |
758
|
|
|
" 'plugin_pos.param_no'" |
759
|
|
|
) |
760
|
|
|
if not 1 < len(plugin_param) < 5: |
761
|
|
|
raise ValueError( |
762
|
|
|
"Enter 'plugin_pos.param_no.dimension'. " |
763
|
|
|
"Following the dimension, use start/stop/step" |
764
|
|
|
" eg. '1.1.dim1.start' " |
765
|
|
|
) |
766
|
|
|
|
767
|
|
|
def separate_plugin_subelem(self, plugin_param, config_disp): |
768
|
|
|
"""Separate the plugin number,parameter (subelement) number |
769
|
|
|
and additional command if present. |
770
|
|
|
|
771
|
|
|
:param plugin_param: A string supplied by the user input which |
772
|
|
|
contains the plugin element to edit/display. eg "1.1.dim.command" |
773
|
|
|
:param config_disp: bool, True if command and dimension arguments are |
774
|
|
|
not permitted |
775
|
|
|
|
776
|
|
|
:returns plugin: The number of the plugin element |
777
|
|
|
subelem: The number of the parameter |
778
|
|
|
dim: The dimension |
779
|
|
|
command: The supplied command, eg expand or a dimension |
780
|
|
|
string |
781
|
|
|
""" |
782
|
|
|
plugin_param = plugin_param.split(".") |
783
|
|
|
plugin = plugin_param[0] |
784
|
|
|
start = self.find_position(plugin) |
785
|
|
|
self._check_command_valid(plugin_param, config_disp) |
786
|
|
|
subelem = plugin_param[1] |
787
|
|
|
if len(plugin_param) > 2: |
788
|
|
|
dim = self.dim_str_to_int(plugin_param[2]) |
789
|
|
|
command = str(dim) |
790
|
|
|
if len(plugin_param) == 4: |
791
|
|
|
self._check_command_str(plugin_param[3]) |
792
|
|
|
command += "." + plugin_param[3] |
793
|
|
|
else: |
794
|
|
|
dim, command = "", "" |
795
|
|
|
return plugin, subelem, dim, command |
796
|
|
|
|
797
|
|
|
def _check_command_str(self, command_str): |
798
|
|
|
"""Check the additional 1.1.dim.command for slice or 'expand' |
799
|
|
|
keywords |
800
|
|
|
""" |
801
|
|
|
command_list = ["expand", "start", "stop", "step", "chunk"] |
802
|
|
|
if command_str not in command_list: |
803
|
|
|
raise ValueError( |
804
|
|
|
"Following the dimension, use start/stop/step eg. " |
805
|
|
|
"'1.1.dim1.start' " |
806
|
|
|
) |
807
|
|
|
return command_str |
808
|
|
|
|
809
|
|
|
def insert(self, plugin, pos, str_pos, replace=False): |
810
|
|
|
plugin_dict = self.create_plugin_dict(plugin) |
811
|
|
|
plugin_dict["pos"] = str_pos |
812
|
|
|
if replace: |
813
|
|
|
self.plugin_list.plugin_list[pos] = plugin_dict |
814
|
|
|
else: |
815
|
|
|
self.plugin_list.plugin_list.insert(pos, plugin_dict) |
816
|
|
|
|
817
|
|
|
def create_plugin_dict(self, plugin): |
818
|
|
|
tools = plugin.get_plugin_tools() |
819
|
|
|
plugin_dict = {} |
820
|
|
|
plugin_dict["name"] = plugin.name |
821
|
|
|
plugin_dict["id"] = plugin.__module__ |
822
|
|
|
plugin_dict["data"] = plugin.parameters |
823
|
|
|
plugin_dict["active"] = True |
824
|
|
|
plugin_dict["tools"] = tools |
825
|
|
|
plugin_dict["param"] = tools.get_param_definitions() |
826
|
|
|
plugin_dict["doc"] = tools.docstring_info |
827
|
|
|
return plugin_dict |
828
|
|
|
|
829
|
|
|
def get(self, pos): |
830
|
|
|
return self.plugin_list.plugin_list[pos] |
831
|
|
|
|
832
|
|
|
def _separate_dimension_and_slice(self, command_str): |
833
|
|
|
"""Check the start stop step command |
834
|
|
|
|
835
|
|
|
param command_str: a string '1.1' containing the dimension |
836
|
|
|
and slice number seperated by a full stop |
837
|
|
|
|
838
|
|
|
:returns dim, slice |
839
|
|
|
""" |
840
|
|
|
if isinstance(command_str, str) and "." in command_str: |
841
|
|
|
# If the slice value is included |
842
|
|
|
slice_dict = {"start": 0, "stop": 1, "step": 2, "chunk": 3} |
843
|
|
|
_slice = slice_dict[command_str.split(".")[1]] |
844
|
|
|
dim = int(command_str.split(".")[0]) |
845
|
|
|
else: |
846
|
|
|
dim = int(command_str) |
847
|
|
|
_slice = "" |
848
|
|
|
return dim, _slice |
849
|
|
|
|
850
|
|
|
def dim_str_to_int(self, dim_str): |
851
|
|
|
"""Check the additional 1.1.dim keyword |
852
|
|
|
|
853
|
|
|
:param dim: A string 'dim1' specifying the dimension |
854
|
|
|
|
855
|
|
|
:return: dim - An integer dimension value |
856
|
|
|
""" |
857
|
|
|
number = "".join(l for l in dim_str if l.isdigit()) |
858
|
|
|
letters = "".join(l for l in dim_str if l.isalpha()) |
859
|
|
|
|
860
|
|
|
if letters == "dim" and number.strip(): |
861
|
|
|
dim = int(number) |
862
|
|
|
else: |
863
|
|
|
raise ValueError( |
864
|
|
|
"Following the second decimal place, please " |
865
|
|
|
"specify a dimension 1.1.dim1 or 1.preview.dim1" |
866
|
|
|
) |
867
|
|
|
return dim |
868
|
|
|
|
869
|
|
|
def modify_preview(self, parameters, param_name, value, dim, _slice): |
870
|
|
|
""" Check the entered value is valid and edit preview""" |
871
|
|
|
slice_list = [0, 1, 2, 3] |
872
|
|
|
type_check_value = pu._dumps(value) |
873
|
|
|
current_preview_value = pu._dumps(parameters[param_name]) |
874
|
|
|
pu.check_valid_dimension(dim, current_preview_value) |
875
|
|
|
if _slice in slice_list: |
876
|
|
|
# Modify this dimension and slice only |
877
|
|
|
if param_u._preview_dimension_singular(type_check_value): |
878
|
|
|
value = self._modify_preview_dimension_slice( |
879
|
|
|
value, current_preview_value, dim, _slice |
880
|
|
|
) |
881
|
|
|
else: |
882
|
|
|
raise ValueError( |
883
|
|
|
"Invalid preview dimension slice value. Please " |
884
|
|
|
"enter a float, an integer or a string including " |
885
|
|
|
"only mid and end keywords." |
886
|
|
|
) |
887
|
|
|
else: |
888
|
|
|
# If the entered value is a valid dimension value |
889
|
|
|
if param_u._preview_dimension(type_check_value): |
890
|
|
|
# Modify the whole dimension |
891
|
|
|
value = self._modify_preview_dimension( |
892
|
|
|
value, current_preview_value, dim |
893
|
|
|
) |
894
|
|
|
else: |
895
|
|
|
raise ValueError( |
896
|
|
|
"Invalid preview dimension value. Please " |
897
|
|
|
"enter a float, an integer or slice notation." |
898
|
|
|
) |
899
|
|
|
return value |
900
|
|
|
|
901
|
|
|
def _modify_preview_dimension_slice(self, value, current_val, dim, _slice): |
902
|
|
|
"""Modify the preview dimension slice value at the dimension (dim) |
903
|
|
|
provided |
904
|
|
|
|
905
|
|
|
:param value: The new value |
906
|
|
|
:param current_value: The current preview parameter value |
907
|
|
|
:param dim: The dimension to modify |
908
|
|
|
:param _slice: The slice value to modify |
909
|
|
|
:return: The modified value |
910
|
|
|
""" |
911
|
|
|
if not current_val: |
912
|
|
|
current_val = self._set_empty_list( |
913
|
|
|
dim, self._set_empty_dimension_slice(value, _slice) |
914
|
|
|
) |
915
|
|
|
else: |
916
|
|
|
current_val[dim - 1] = self._modified_slice_notation( |
917
|
|
|
current_val[dim - 1], value, _slice |
918
|
|
|
) |
919
|
|
|
return current_val |
920
|
|
|
|
921
|
|
|
def _modified_slice_notation(self, old_value, value, _slice): |
922
|
|
|
"""Change the current value at the provided slice |
923
|
|
|
|
924
|
|
|
:param old_value: Previous slice notation |
925
|
|
|
:param value: New value to set |
926
|
|
|
:param _slice: Slice to modify |
927
|
|
|
:return: Changed value (str/int) |
928
|
|
|
""" |
929
|
|
|
old_value = self._set_incomplete_slices(str(old_value), _slice) |
930
|
|
|
if pu.is_slice_notation(old_value): |
931
|
|
|
start_stop_split = old_value.split(":") |
932
|
|
|
return self._get_modified_slice(start_stop_split, value, _slice) |
933
|
|
|
elif _slice == 0: |
934
|
|
|
# If there is no slice notation, only allow first slice to |
935
|
|
|
# be modified |
936
|
|
|
return value |
937
|
|
|
else: |
938
|
|
|
raise Exception( |
939
|
|
|
"There is no existing slice notation to modify." |
940
|
|
|
) |
941
|
|
|
|
942
|
|
|
def _get_modified_slice(self, start_stop_split, value, _slice): |
943
|
|
|
if all(v == "" for v in start_stop_split): |
944
|
|
|
return self._set_empty_dimension_slice(value, _slice) |
945
|
|
|
else: |
946
|
|
|
start_stop_split[_slice] = str(value) |
947
|
|
|
start_stop_split = ":".join(start_stop_split) |
948
|
|
|
return start_stop_split |
949
|
|
|
|
950
|
|
|
def _modify_preview_dimension(self, value, current_preview, dim): |
951
|
|
|
"""Modify the preview list value at the dimension provided (dim) |
952
|
|
|
|
953
|
|
|
:param value: The new value |
954
|
|
|
:param current_value: The current preview parameter list value |
955
|
|
|
:param dim: The dimension to modify |
956
|
|
|
:return: The modified value |
957
|
|
|
""" |
958
|
|
|
if not current_preview: |
959
|
|
|
return self._set_empty_list(dim, value) |
960
|
|
|
current_preview[dim - 1] = value |
961
|
|
|
# Save the altered preview value |
962
|
|
|
return current_preview |
963
|
|
|
|
964
|
|
|
def _set_empty_dimension_slice(self, value, _slice): |
965
|
|
|
"""Set the empty dimension and insert colons to indicate |
966
|
|
|
the correct slice notation. |
967
|
|
|
|
968
|
|
|
:param value: New value to set |
969
|
|
|
:param _slice: start/stop/step/chunk value |
970
|
|
|
:return: String for the new value |
971
|
|
|
""" |
972
|
|
|
return _slice * ":" + str(value) |
973
|
|
|
|
974
|
|
|
def _set_incomplete_slices(self, old_value, _slice): |
975
|
|
|
"""Append default slice values.to the current string value, in order |
976
|
|
|
to allow later slice values to be set |
977
|
|
|
|
978
|
|
|
:param old_value: Current string value with slice notation |
979
|
|
|
:param _slice: slice notation index to be edited |
980
|
|
|
:return: String with default slice notation entries set |
981
|
|
|
""" |
982
|
|
|
while old_value.count(":") < _slice: |
983
|
|
|
old_value += ":" |
984
|
|
|
return old_value |
985
|
|
|
|
986
|
|
|
def _set_empty_list(self, dim, value): |
987
|
|
|
"""If the dimension is 1 then allow the whole empty list |
988
|
|
|
to be set. |
989
|
|
|
|
990
|
|
|
:param dim: Dimension to be altered |
991
|
|
|
:param value: New value |
992
|
|
|
:return: List containing new value |
993
|
|
|
""" |
994
|
|
|
if dim == 1: |
995
|
|
|
return [value] |
996
|
|
|
else: |
997
|
|
|
raise ValueError("You have not set earlier dimensions") |
998
|
|
|
|
999
|
|
|
def level(self, level): |
1000
|
|
|
""" Set the visibility level of parameters """ |
1001
|
|
|
if level: |
1002
|
|
|
self.disp_level = level |
1003
|
|
|
print(f"Level set to '{level}'") |
1004
|
|
|
else: |
1005
|
|
|
print(f"Level is set at '{self.disp_level}'") |
1006
|
|
|
|
1007
|
|
|
def remove(self, pos): |
1008
|
|
|
if pos >= self.size: |
1009
|
|
|
raise Exception( |
1010
|
|
|
"Cannot remove plugin %s as it does not exist." |
1011
|
|
|
% self.plugin_list.plugin_list[pos]["name"] |
1012
|
|
|
) |
1013
|
|
|
pos_str = self.plugin_list.plugin_list[pos]["pos"] |
1014
|
|
|
self.plugin_list.plugin_list.pop(pos) |
1015
|
|
|
pos_list = self.get_split_positions() |
1016
|
|
|
self.inc_positions(pos, pos_list, pos_str, -1) |
1017
|
|
|
|
1018
|
|
|
@property |
1019
|
|
|
def size(self): |
1020
|
|
|
return len(self.plugin_list.plugin_list) |
1021
|
|
|
|