fmu-manipulation-toolbox 1.8.4.3b0__py3-none-any.whl → 1.9__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.
- fmu_manipulation_toolbox/__init__.py +0 -1
- fmu_manipulation_toolbox/__main__.py +1 -1
- fmu_manipulation_toolbox/__version__.py +1 -1
- fmu_manipulation_toolbox/assembly.py +21 -12
- fmu_manipulation_toolbox/checker.py +11 -8
- fmu_manipulation_toolbox/cli/__init__.py +0 -0
- fmu_manipulation_toolbox/cli/fmucontainer.py +105 -0
- fmu_manipulation_toolbox/cli/fmusplit.py +48 -0
- fmu_manipulation_toolbox/cli/fmutool.py +127 -0
- fmu_manipulation_toolbox/cli/utils.py +36 -0
- fmu_manipulation_toolbox/container.py +534 -247
- fmu_manipulation_toolbox/gui.py +47 -55
- fmu_manipulation_toolbox/gui_style.py +8 -0
- fmu_manipulation_toolbox/help.py +3 -0
- fmu_manipulation_toolbox/operations.py +251 -179
- fmu_manipulation_toolbox/remoting.py +107 -0
- fmu_manipulation_toolbox/resources/darwin64/container.dylib +0 -0
- fmu_manipulation_toolbox/resources/linux32/client_sm.so +0 -0
- fmu_manipulation_toolbox/resources/linux32/server_sm +0 -0
- fmu_manipulation_toolbox/resources/linux64/client_sm.so +0 -0
- fmu_manipulation_toolbox/resources/linux64/container.so +0 -0
- fmu_manipulation_toolbox/resources/linux64/server_sm +0 -0
- fmu_manipulation_toolbox/resources/win32/client_sm.dll +0 -0
- fmu_manipulation_toolbox/resources/win32/server_sm.exe +0 -0
- fmu_manipulation_toolbox/resources/win64/client_sm.dll +0 -0
- fmu_manipulation_toolbox/resources/win64/container.dll +0 -0
- fmu_manipulation_toolbox/resources/win64/server_sm.exe +0 -0
- fmu_manipulation_toolbox/split.py +67 -34
- {fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9.dist-info}/METADATA +1 -1
- {fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9.dist-info}/RECORD +34 -27
- {fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9.dist-info}/WHEEL +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9.dist-info}/entry_points.txt +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9.dist-info}/licenses/LICENSE.txt +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9.dist-info}/top_level.txt +0 -0
fmu_manipulation_toolbox/gui.py
CHANGED
|
@@ -2,22 +2,26 @@ import os.path
|
|
|
2
2
|
import sys
|
|
3
3
|
import textwrap
|
|
4
4
|
|
|
5
|
-
from PySide6.QtCore import Qt,
|
|
5
|
+
from PySide6.QtCore import Qt, QUrl, QDir, Signal, QPoint, QModelIndex
|
|
6
6
|
from PySide6.QtWidgets import (QApplication, QWidget, QGridLayout, QLabel, QLineEdit, QPushButton, QFileDialog,
|
|
7
7
|
QTextBrowser, QInputDialog, QMenu, QTreeView, QAbstractItemView, QTabWidget, QTableView,
|
|
8
8
|
QCheckBox)
|
|
9
9
|
from PySide6.QtGui import (QPixmap, QTextCursor, QStandardItem, QIcon, QDesktopServices, QAction,
|
|
10
10
|
QPainter, QColor, QImage, QStandardItemModel)
|
|
11
11
|
from functools import partial
|
|
12
|
-
from typing import Optional
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
|
|
14
|
+
from .gui_style import gui_style, log_color
|
|
15
15
|
from .operations import *
|
|
16
|
+
from .remoting import (OperationAddRemotingWin32, OperationAddRemotingWin64, OperationAddFrontendWin32,
|
|
17
|
+
OperationAddFrontendWin64)
|
|
16
18
|
from .assembly import Assembly, AssemblyNode
|
|
17
19
|
from .checker import checker_list
|
|
18
20
|
from .help import Help
|
|
19
21
|
from .version import __version__ as version
|
|
20
22
|
|
|
23
|
+
logger = logging.getLogger("fmu_manipulation_toolbox")
|
|
24
|
+
|
|
21
25
|
|
|
22
26
|
class DropZoneWidget(QLabel):
|
|
23
27
|
WIDTH = 150
|
|
@@ -51,7 +55,7 @@ class DropZoneWidget(QLabel):
|
|
|
51
55
|
try:
|
|
52
56
|
file_path = event.mimeData().urls()[0].toLocalFile()
|
|
53
57
|
except IndexError:
|
|
54
|
-
|
|
58
|
+
logger.error("Please select a regular file.")
|
|
55
59
|
return
|
|
56
60
|
self.set_fmu(file_path)
|
|
57
61
|
event.accept()
|
|
@@ -98,54 +102,41 @@ class DropZoneWidget(QLabel):
|
|
|
98
102
|
self.fmu = FMU(filename)
|
|
99
103
|
self.set_image(os.path.join(self.fmu.tmp_directory, "model.png"))
|
|
100
104
|
except Exception as e:
|
|
101
|
-
|
|
105
|
+
logger.error(f"Cannot load this FMU: {e}")
|
|
102
106
|
self.set_image(None)
|
|
103
107
|
self.fmu = None
|
|
104
108
|
self.clicked.emit()
|
|
105
109
|
|
|
106
110
|
|
|
111
|
+
class LogHandler(logging.Handler):
|
|
112
|
+
LOG_COLOR = {
|
|
113
|
+
logging.DEBUG: QColor(log_color["DEBUG"]),
|
|
114
|
+
logging.INFO: QColor(log_color["INFO"]),
|
|
115
|
+
logging.WARNING: QColor(log_color["WARNING"]),
|
|
116
|
+
logging.ERROR: QColor(log_color["ERROR"]),
|
|
117
|
+
logging.CRITICAL: QColor(log_color["CRITICAL"]),
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
def __init__(self, text_browser, level):
|
|
121
|
+
super().__init__(level)
|
|
122
|
+
self.text_browser: QTextBrowser = text_browser
|
|
123
|
+
logger.addHandler(self)
|
|
124
|
+
logger.setLevel(level)
|
|
125
|
+
|
|
126
|
+
def emit(self, record) -> None:
|
|
127
|
+
self.text_browser.setTextColor(self.LOG_COLOR[record.levelno])
|
|
128
|
+
self.text_browser.insertPlainText(record.msg+"\n")
|
|
129
|
+
|
|
130
|
+
|
|
107
131
|
class LogWidget(QTextBrowser):
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
_stderr = None
|
|
111
|
-
messageWritten = Signal(str)
|
|
112
|
-
|
|
113
|
-
def __init__(self):
|
|
114
|
-
super().__init__()
|
|
115
|
-
|
|
116
|
-
def flush(self):
|
|
117
|
-
pass
|
|
118
|
-
|
|
119
|
-
@staticmethod
|
|
120
|
-
def fileno():
|
|
121
|
-
return -1
|
|
122
|
-
|
|
123
|
-
def write(self, msg):
|
|
124
|
-
if not self.signalsBlocked():
|
|
125
|
-
self.messageWritten.emit(msg)
|
|
126
|
-
|
|
127
|
-
@staticmethod
|
|
128
|
-
def stdout():
|
|
129
|
-
if not LogWidget.XStream._stdout:
|
|
130
|
-
LogWidget.XStream._stdout = LogWidget.XStream()
|
|
131
|
-
sys.stdout = LogWidget.XStream._stdout
|
|
132
|
-
return LogWidget.XStream._stdout
|
|
133
|
-
|
|
134
|
-
@staticmethod
|
|
135
|
-
def stderr():
|
|
136
|
-
if not LogWidget.XStream._stderr:
|
|
137
|
-
LogWidget.XStream._stderr = LogWidget.XStream()
|
|
138
|
-
sys.stderr = LogWidget.XStream._stderr
|
|
139
|
-
return LogWidget.XStream._stderr
|
|
132
|
+
def __init__(self, parent=None, level=logging.INFO):
|
|
133
|
+
super().__init__(parent)
|
|
140
134
|
|
|
141
|
-
def __init__(self):
|
|
142
|
-
super().__init__()
|
|
143
135
|
self.setMinimumWidth(900)
|
|
144
136
|
self.setMinimumHeight(500)
|
|
145
137
|
self.setSearchPaths([os.path.join(os.path.dirname(__file__), "resources")])
|
|
146
138
|
self.insertHtml('<center><img src="fmu_manipulation_toolbox.png"/></center><br/>')
|
|
147
|
-
|
|
148
|
-
LogWidget.XStream.stderr().messageWritten.connect(self.insertPlainText)
|
|
139
|
+
self.log_handler = LogHandler(self, logging.DEBUG)
|
|
149
140
|
|
|
150
141
|
def loadResource(self, _, name):
|
|
151
142
|
image_path = os.path.join(os.path.dirname(__file__), "resources", name.toString())
|
|
@@ -255,10 +246,10 @@ class AssemblyTreeWidget(QTreeView):
|
|
|
255
246
|
|
|
256
247
|
def removeRows(self, row, count, parent=QModelIndex()):
|
|
257
248
|
if not self.dnd_target_node:
|
|
258
|
-
|
|
249
|
+
logger.error("NO DROP NODE!?")
|
|
259
250
|
|
|
260
251
|
source_index = self.itemFromIndex(parent).child(row, 0).data(role=Qt.ItemDataRole.UserRole+1)
|
|
261
|
-
|
|
252
|
+
logger.debug(f"{source_index} ==> {self.dnd_target_node.name}")
|
|
262
253
|
|
|
263
254
|
self.dnd_target_node = None
|
|
264
255
|
return super().removeRows(row, count, parent)
|
|
@@ -289,7 +280,7 @@ class AssemblyTreeWidget(QTreeView):
|
|
|
289
280
|
|
|
290
281
|
def setTopIndex(self):
|
|
291
282
|
topIndex = self.model.index(0, 0, self.rootIndex())
|
|
292
|
-
|
|
283
|
+
logger.debug(topIndex.isValid(), topIndex.model())
|
|
293
284
|
if topIndex.isValid():
|
|
294
285
|
self.setCurrentIndex(topIndex)
|
|
295
286
|
if self.layoutCheck:
|
|
@@ -318,9 +309,9 @@ class AssemblyTreeWidget(QTreeView):
|
|
|
318
309
|
try:
|
|
319
310
|
file_path = event.mimeData().urls()[0].toLocalFile()
|
|
320
311
|
except IndexError:
|
|
321
|
-
|
|
312
|
+
logger.error("Please select a regular file.")
|
|
322
313
|
return
|
|
323
|
-
|
|
314
|
+
logger.debug(f"DROP: {file_path}")
|
|
324
315
|
event.accept()
|
|
325
316
|
else:
|
|
326
317
|
event.ignore()
|
|
@@ -518,7 +509,7 @@ class MainWindow(WindowWithLayout):
|
|
|
518
509
|
"FMU files (*.fmu)")
|
|
519
510
|
if ok and filename:
|
|
520
511
|
fmu.repack(filename)
|
|
521
|
-
|
|
512
|
+
logger.info(f"Modified version saved as {filename}.")
|
|
522
513
|
|
|
523
514
|
def save_log(self):
|
|
524
515
|
if self.dropped_fmu.fmu:
|
|
@@ -533,7 +524,7 @@ class MainWindow(WindowWithLayout):
|
|
|
533
524
|
with open(filename, "wt") as file:
|
|
534
525
|
file.write(str(self.log_widget.toPlainText()))
|
|
535
526
|
except Exception as e:
|
|
536
|
-
|
|
527
|
+
logger.error(f"{e}")
|
|
537
528
|
|
|
538
529
|
def add_operation(self, name, usage, severity, operation, x, y, prompt=None, prompt_file=None, arg=None,
|
|
539
530
|
func=None):
|
|
@@ -603,18 +594,18 @@ class MainWindow(WindowWithLayout):
|
|
|
603
594
|
if self.dropped_fmu.fmu:
|
|
604
595
|
self.log_widget.moveCursor(QTextCursor.MoveOperation.End)
|
|
605
596
|
fmu_filename = os.path.basename(self.dropped_fmu.fmu.fmu_filename)
|
|
606
|
-
|
|
597
|
+
logger.info('-' * 100)
|
|
607
598
|
self.log_widget.insertHtml(f"<strong>{fmu_filename}: {operation}</strong><br>")
|
|
608
599
|
|
|
609
600
|
apply_on = self.filter_list.get()
|
|
610
601
|
if apply_on:
|
|
611
602
|
self.log_widget.insertHtml(f"<i>Applied only for ports with causality = " +
|
|
612
603
|
", ".join(apply_on) + "</i><br>")
|
|
613
|
-
|
|
604
|
+
logger.info('-' * 100)
|
|
614
605
|
try:
|
|
615
606
|
self.dropped_fmu.fmu.apply_operation(operation, apply_on=apply_on)
|
|
616
607
|
except Exception as e:
|
|
617
|
-
|
|
608
|
+
logger.error(f"{e}")
|
|
618
609
|
|
|
619
610
|
scroll_bar = self.log_widget.verticalScrollBar()
|
|
620
611
|
scroll_bar.setValue(scroll_bar.maximum())
|
|
@@ -712,7 +703,7 @@ class ContainerWindow(WindowWithLayout):
|
|
|
712
703
|
self.last_directory = os.path.dirname(filename)
|
|
713
704
|
self.assembly_tree.load_container(filename)
|
|
714
705
|
except Exception as e:
|
|
715
|
-
|
|
706
|
+
logger.error(e)
|
|
716
707
|
|
|
717
708
|
|
|
718
709
|
class Application(QApplication):
|
|
@@ -724,8 +715,9 @@ Communicating with the FMU-developer and adapting the way the FMU is generated,
|
|
|
724
715
|
|
|
725
716
|
"""
|
|
726
717
|
def __init__(self, *args, **kwargs):
|
|
727
|
-
super().__init__(*args, **kwargs)
|
|
728
718
|
self.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.RoundPreferFloor)
|
|
719
|
+
super().__init__(*args, **kwargs)
|
|
720
|
+
|
|
729
721
|
|
|
730
722
|
QDir.addSearchPath('images', os.path.join(os.path.dirname(__file__), "resources"))
|
|
731
723
|
self.setStyleSheet(gui_style)
|
|
@@ -747,8 +739,8 @@ Communicating with the FMU-developer and adapting the way the FMU is generated,
|
|
|
747
739
|
def main():
|
|
748
740
|
application = Application(sys.argv)
|
|
749
741
|
|
|
750
|
-
|
|
751
|
-
|
|
742
|
+
logger.info(" " * 80 + f"Version {version}")
|
|
743
|
+
logger.info(application.__doc__)
|
|
752
744
|
|
|
753
745
|
sys.exit(application.exec())
|
|
754
746
|
|
fmu_manipulation_toolbox/help.py
CHANGED
|
@@ -73,6 +73,9 @@ class Help:
|
|
|
73
73
|
'-only-outputs': "apply operation only on ports with causality = 'output'. This "
|
|
74
74
|
"option is available from version 1.3.",
|
|
75
75
|
|
|
76
|
+
'-only-locals': "apply operation only on ports with causality = 'local'. This "
|
|
77
|
+
"option is available from version 1.9.",
|
|
78
|
+
|
|
76
79
|
'-summary': "display useful information regarding the FMU.",
|
|
77
80
|
|
|
78
81
|
'-check': "performs some check of FMU and display Errors or Warnings. This is useful to avoid later "
|