scipion-pyworkflow 3.10.5__py3-none-any.whl → 3.11.0__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.
Files changed (127) hide show
  1. pyworkflow/config.py +131 -67
  2. pyworkflow/constants.py +12 -2
  3. pyworkflow/object.py +3 -2
  4. pyworkflow/plugin.py +93 -44
  5. pyworkflow/project/scripts/fix_links.py +4 -1
  6. pyworkflow/resources/showj/arrowDown.png +0 -0
  7. pyworkflow/resources/showj/arrowUp.png +0 -0
  8. pyworkflow/resources/showj/background_section.png +0 -0
  9. pyworkflow/resources/showj/colRowModeOff.png +0 -0
  10. pyworkflow/resources/showj/colRowModeOn.png +0 -0
  11. pyworkflow/resources/showj/delete.png +0 -0
  12. pyworkflow/resources/showj/doc_icon.png +0 -0
  13. pyworkflow/resources/showj/download_icon.png +0 -0
  14. pyworkflow/resources/showj/enabled_gallery.png +0 -0
  15. pyworkflow/resources/showj/galleryViewOff.png +0 -0
  16. pyworkflow/resources/showj/galleryViewOn.png +0 -0
  17. pyworkflow/resources/showj/goto.png +0 -0
  18. pyworkflow/resources/showj/menu.png +0 -0
  19. pyworkflow/resources/showj/separator.png +0 -0
  20. pyworkflow/resources/showj/tableViewOff.png +0 -0
  21. pyworkflow/resources/showj/tableViewOn.png +0 -0
  22. pyworkflow/resources/showj/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  23. pyworkflow/resources/showj/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  24. pyworkflow/resources/showj/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  25. pyworkflow/resources/showj/volumeOff.png +0 -0
  26. pyworkflow/resources/showj/volumeOn.png +0 -0
  27. pyworkflow/viewer.py +23 -1
  28. pyworkflowtests/objects.py +2 -2
  29. pyworkflowtests/protocols.py +1 -3
  30. {scipion_pyworkflow-3.10.5.dist-info → scipion_pyworkflow-3.11.0.dist-info}/METADATA +21 -25
  31. scipion_pyworkflow-3.11.0.dist-info/RECORD +71 -0
  32. {scipion_pyworkflow-3.10.5.dist-info → scipion_pyworkflow-3.11.0.dist-info}/WHEEL +1 -1
  33. scipion_pyworkflow-3.11.0.dist-info/entry_points.txt +2 -0
  34. pyworkflow/apps/__init__.py +0 -29
  35. pyworkflow/apps/pw_manager.py +0 -37
  36. pyworkflow/apps/pw_plot.py +0 -51
  37. pyworkflow/apps/pw_project.py +0 -113
  38. pyworkflow/apps/pw_protocol_list.py +0 -143
  39. pyworkflow/apps/pw_protocol_run.py +0 -51
  40. pyworkflow/apps/pw_run_tests.py +0 -267
  41. pyworkflow/apps/pw_schedule_run.py +0 -322
  42. pyworkflow/apps/pw_sleep.py +0 -37
  43. pyworkflow/apps/pw_sync_data.py +0 -439
  44. pyworkflow/apps/pw_viewer.py +0 -78
  45. pyworkflow/gui/__init__.py +0 -36
  46. pyworkflow/gui/browser.py +0 -726
  47. pyworkflow/gui/canvas.py +0 -1190
  48. pyworkflow/gui/dialog.py +0 -977
  49. pyworkflow/gui/form.py +0 -2637
  50. pyworkflow/gui/graph.py +0 -247
  51. pyworkflow/gui/graph_layout.py +0 -271
  52. pyworkflow/gui/gui.py +0 -566
  53. pyworkflow/gui/matplotlib_image.py +0 -233
  54. pyworkflow/gui/plotter.py +0 -247
  55. pyworkflow/gui/project/__init__.py +0 -25
  56. pyworkflow/gui/project/base.py +0 -192
  57. pyworkflow/gui/project/constants.py +0 -139
  58. pyworkflow/gui/project/labels.py +0 -205
  59. pyworkflow/gui/project/project.py +0 -492
  60. pyworkflow/gui/project/searchprotocol.py +0 -154
  61. pyworkflow/gui/project/searchrun.py +0 -181
  62. pyworkflow/gui/project/steps.py +0 -171
  63. pyworkflow/gui/project/utils.py +0 -332
  64. pyworkflow/gui/project/variables.py +0 -179
  65. pyworkflow/gui/project/viewdata.py +0 -472
  66. pyworkflow/gui/project/viewprojects.py +0 -510
  67. pyworkflow/gui/project/viewprotocols.py +0 -2093
  68. pyworkflow/gui/project/viewprotocols_extra.py +0 -560
  69. pyworkflow/gui/text.py +0 -771
  70. pyworkflow/gui/tooltip.py +0 -185
  71. pyworkflow/gui/tree.py +0 -684
  72. pyworkflow/gui/widgets.py +0 -307
  73. pyworkflow/mapper/__init__.py +0 -26
  74. pyworkflow/mapper/mapper.py +0 -222
  75. pyworkflow/mapper/sqlite.py +0 -1578
  76. pyworkflow/mapper/sqlite_db.py +0 -145
  77. pyworkflow/project/__init__.py +0 -31
  78. pyworkflow/project/config.py +0 -454
  79. pyworkflow/project/manager.py +0 -180
  80. pyworkflow/project/project.py +0 -2010
  81. pyworkflow/protocol/__init__.py +0 -38
  82. pyworkflow/protocol/bibtex.py +0 -48
  83. pyworkflow/protocol/constants.py +0 -87
  84. pyworkflow/protocol/executor.py +0 -455
  85. pyworkflow/protocol/hosts.py +0 -313
  86. pyworkflow/protocol/launch.py +0 -270
  87. pyworkflow/protocol/package.py +0 -42
  88. pyworkflow/protocol/params.py +0 -741
  89. pyworkflow/protocol/protocol.py +0 -2582
  90. pyworkflow/tests/__init__.py +0 -29
  91. pyworkflow/tests/test_utils.py +0 -25
  92. pyworkflow/tests/tests.py +0 -341
  93. pyworkflow/utils/__init__.py +0 -38
  94. pyworkflow/utils/dataset.py +0 -414
  95. pyworkflow/utils/echo.py +0 -104
  96. pyworkflow/utils/graph.py +0 -169
  97. pyworkflow/utils/log.py +0 -284
  98. pyworkflow/utils/path.py +0 -528
  99. pyworkflow/utils/process.py +0 -132
  100. pyworkflow/utils/profiler.py +0 -92
  101. pyworkflow/utils/progressbar.py +0 -154
  102. pyworkflow/utils/properties.py +0 -631
  103. pyworkflow/utils/reflection.py +0 -129
  104. pyworkflow/utils/utils.py +0 -879
  105. pyworkflow/utils/which.py +0 -229
  106. pyworkflow/webservices/__init__.py +0 -8
  107. pyworkflow/webservices/config.py +0 -11
  108. pyworkflow/webservices/notifier.py +0 -162
  109. pyworkflow/webservices/repository.py +0 -59
  110. pyworkflow/webservices/workflowhub.py +0 -74
  111. pyworkflowtests/tests/__init__.py +0 -0
  112. pyworkflowtests/tests/test_canvas.py +0 -72
  113. pyworkflowtests/tests/test_domain.py +0 -45
  114. pyworkflowtests/tests/test_logs.py +0 -74
  115. pyworkflowtests/tests/test_mappers.py +0 -392
  116. pyworkflowtests/tests/test_object.py +0 -507
  117. pyworkflowtests/tests/test_project.py +0 -42
  118. pyworkflowtests/tests/test_protocol_execution.py +0 -135
  119. pyworkflowtests/tests/test_protocol_export.py +0 -78
  120. pyworkflowtests/tests/test_protocol_output.py +0 -158
  121. pyworkflowtests/tests/test_streaming.py +0 -47
  122. pyworkflowtests/tests/test_utils.py +0 -210
  123. scipion_pyworkflow-3.10.5.dist-info/RECORD +0 -140
  124. scipion_pyworkflow-3.10.5.dist-info/dependency_links.txt +0 -1
  125. scipion_pyworkflow-3.10.5.dist-info/entry_points.txt +0 -5
  126. {scipion_pyworkflow-3.10.5.dist-info → scipion_pyworkflow-3.11.0.dist-info/licenses}/LICENSE.txt +0 -0
  127. {scipion_pyworkflow-3.10.5.dist-info → scipion_pyworkflow-3.11.0.dist-info}/top_level.txt +0 -0
@@ -1,181 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # **************************************************************************
3
- # *
4
- # * Authors: Pablo Conesa [1]
5
- # *
6
- # * [1] Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
7
- # *
8
- # * This program is free software: you can redistribute it and/or modify
9
- # * it under the terms of the GNU General Public License as published by
10
- # * the Free Software Foundation, either version 3 of the License, or
11
- # * (at your option) any later version.
12
- # *
13
- # * This program is distributed in the hope that it will be useful,
14
- # * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- # * GNU General Public License for more details.
17
- # *
18
- # * You should have received a copy of the GNU General Public License
19
- # * along with this program. If not, see <https://www.gnu.org/licenses/>.
20
- # *
21
- # * All comments concerning this program package may be sent to the
22
- # * e-mail address 'scipion@cnb.csic.es'
23
- # *
24
- # **************************************************************************
25
- """ This modules hosts code provider and window to search for a run"""
26
-
27
- import tkinter as tk
28
- from pyworkflow import Config
29
- import pyworkflow.protocol as pwprot
30
-
31
- from pyworkflow.gui import SearchBaseWindow
32
- from pyworkflow.gui.project.constants import *
33
- from pyworkflow.gui.tree import ProjectRunsTreeProvider
34
-
35
- class RunsTreeProvider(ProjectRunsTreeProvider):
36
- """Provide runs info to populate tree inside viewprotocols. Is more advanced
37
- than ProjectRunsTreeProvider extended, extended with right click actions."""
38
-
39
- def __init__(self, project, actionFunc):
40
- super().__init__(project)
41
- self.actionFunc = actionFunc # ProtocolsView._runActionClicked
42
- self._selection = project.getSettings().runSelection
43
-
44
- def getActionsFromSelection(self):
45
- """ Return the list of options available for selection. """
46
- n = len(self._selection)
47
- single = n == 1
48
- anyselected = n > 0
49
- if n:
50
- prot = self.project.getProtocol(self._selection[0], fromRuns=True)
51
- status = prot.getStatus()
52
- nodeInfo = self.project.getSettings().getNodeById(prot.getObjId())
53
- expanded = nodeInfo.isExpanded() if nodeInfo else True
54
- else:
55
- status = None
56
-
57
- stoppable = status in [pwprot.STATUS_RUNNING, pwprot.STATUS_SCHEDULED,
58
- pwprot.STATUS_LAUNCHED]
59
-
60
- # This list defines the order the icons are shown
61
- return [(ACTION_NEW, True),
62
- (ACTION_EDIT, single and status and expanded),
63
- (ACTION_BROWSE, single and status and expanded),
64
- (ACTION_RENAME, single and status and expanded),
65
- (ACTION_LABELS, True),
66
-
67
- (ACTION_DUPLICATE, status and expanded),
68
- (ACTION_COPY, status and expanded),
69
- (ACTION_PASTE, status and expanded),
70
- (ACTION_DELETE, status != pwprot.STATUS_RUNNING and status and expanded),
71
-
72
- (ACTION_SELECT_FROM, anyselected),
73
- (ACTION_SELECT_TO, anyselected),
74
- (ACTION_COLLAPSE, single and status and expanded),
75
- (ACTION_EXPAND, single and status and not expanded),
76
-
77
- (ACTION_STOP, stoppable and single),
78
- (ACTION_STOP_WORKFLOW, single),
79
- (ACTION_RESTART_WORKFLOW, single),
80
- (ACTION_CONTINUE_WORKFLOW, single),
81
- (ACTION_RESET_WORKFLOW, single),
82
-
83
- (ACTION_EXPORT, anyselected),
84
- (ACTION_EXPORT_UPLOAD, anyselected),
85
-
86
- (ACTION_STEPS, single and Config.debugOn() and status and expanded),
87
- (ACTION_DB, single and Config.debugOn() and status and expanded),
88
- ]
89
-
90
- def getObjectActions(self, obj, withEvent=False):
91
- """ Get actions available to perform.
92
-
93
- This method is called in 2 cases:
94
- 1.- Right-click on the tree (list of runs)
95
- 2.- Right-click on the canvas. When called from the canvas we need the event to get the click's position.
96
-
97
- :param obj: optional, if passed, actions on the object. otherwise generic actions
98
- :param withEvent: pass True if callback has to have the event as a parameter (call from canvas but not from tree)
99
-
100
- """
101
-
102
- def addAction(actionLabel):
103
- if actionLabel:
104
- text = actionLabel
105
- action = actionLabel
106
- if withEvent:
107
- callback=lambda e: self.actionFunc(action, e)
108
- else:
109
- callback=lambda: self.actionFunc(action)
110
-
111
- actionLabel = (text, callback,
112
- ActionIcons.get(action, None),
113
- ActionShortCuts.get(action,None))
114
- return actionLabel
115
-
116
- actions = [addAction(a)
117
- for a, cond in self.getActionsFromSelection() if cond]
118
-
119
- if obj is not None and hasattr(obj, 'getActions'):
120
- for text, action in obj.getActions():
121
- actions.append((text, action, None))
122
-
123
- return actions
124
-
125
-
126
- class SearchRunWindow(SearchBaseWindow):
127
-
128
- columnConfig = {
129
- '#0': (ProjectRunsTreeProvider.ID_COLUMN, {'width': 100, 'stretch': tk.NO}, 10),
130
- ProjectRunsTreeProvider.RUN_COLUMN: (ProjectRunsTreeProvider.RUN_COLUMN, {'width': 300, 'stretch': tk.TRUE}, 10),
131
- ProjectRunsTreeProvider.STATE_COLUMN: (ProjectRunsTreeProvider.STATE_COLUMN, {'width': 150, 'stretch': tk.FALSE}, 5),
132
- ProjectRunsTreeProvider.TIME_COLUMN: (ProjectRunsTreeProvider.TIME_COLUMN, {'width': 200, 'stretch': tk.FALSE}, 5),
133
- 'Comment': ('Comment', {'width': 300, 'stretch': tk.FALSE}, 5),
134
- 'Expanded': ('Expanded', {'width': 150, 'stretch': tk.FALSE}, 5),
135
- }
136
-
137
- def __init__(self, parentWindow, runsGraph, **kwargs):
138
-
139
-
140
- super().__init__(parentWindow,
141
- title="Locate a protocol in the graph",
142
- **kwargs)
143
- self.runsGraph = runsGraph
144
-
145
- def _onSearchClick(self, e=None):
146
-
147
- self._resultsTree.clear()
148
- keyword = self._searchVar.get().lower().strip()
149
-
150
- weightIndex = len(self.columnConfig)
151
- nodes = self.runsGraph.getNodes()
152
- protList = []
153
-
154
- for node in nodes:
155
- if node.run is not None:
156
- run = node.run
157
- key = run.getObjId()
158
- label = run.getRunName()
159
- status = run.getStatusMessage(),
160
- time = run.getObjCreation()
161
- comment = run.getObjComment()
162
- expanded = "expanded" if getattr(node, 'expanded', False) else "collapsed"
163
- line = (key, label, status, time, comment, expanded)
164
-
165
- line = self.addSearchWeight(line, keyword)
166
- # something was found: weight > 0
167
- if line[weightIndex] != 0:
168
- # Add the run
169
- protList.append(line)
170
-
171
- # Sort by weight
172
- protList.sort(reverse=True, key=lambda x: x[weightIndex])
173
-
174
- for line in protList:
175
-
176
- self._resultsTree.insert(
177
- '', 'end', line[0], text=line[0],
178
- values=line[1:])
179
-
180
-
181
-
@@ -1,171 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # **************************************************************************
3
- # *
4
- # * Authors: Pablo Conesa [1]
5
- # *
6
- # * [1] Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
7
- # *
8
- # * This program is free software: you can redistribute it and/or modify
9
- # * it under the terms of the GNU General Public License as published by
10
- # * the Free Software Foundation, either version 3 of the License, or
11
- # * (at your option) any later version.
12
- # *
13
- # * This program is distributed in the hope that it will be useful,
14
- # * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- # * GNU General Public License for more details.
17
- # *
18
- # * You should have received a copy of the GNU General Public License
19
- # * along with this program. If not, see <https://www.gnu.org/licenses/>.
20
- # *
21
- # * All comments concerning this program package may be sent to the
22
- # * e-mail address 'scipion@cnb.csic.es'
23
- # *
24
- # **************************************************************************
25
- """ This modules hosts gui code to visualize steps"""
26
- import json
27
- import tkinter as tk
28
-
29
- import pyworkflow.protocol as pwprot
30
- import pyworkflow.gui as pwgui
31
- import pyworkflow.utils as pwutils
32
-
33
- from pyworkflow import TK
34
- from pyworkflow.utils import Icon
35
-
36
-
37
- class StepsTreeProvider(pwgui.tree.TreeProvider):
38
- """Create the tree elements for a Protocol run"""
39
-
40
- def __init__(self, stepsList):
41
- for i, s in enumerate(stepsList):
42
- if not s._index:
43
- s._index = i + 1
44
-
45
- self._stepsList = stepsList
46
- self.getColumns = lambda: [('Index', 50), ('Step', 200), ('Status', 150),
47
- ('Time', 150), ('Class', 100)]
48
- self._parentDict = {}
49
-
50
- def getObjects(self):
51
- return self._stepsList
52
-
53
- @staticmethod
54
- def getObjectInfo(obj):
55
- info = {'key': obj._index,
56
- 'values': (str(obj), obj.getStatus(), pwutils.prettyDelta(obj.getElapsedTime()),
57
- obj.getClassName())}
58
- return info
59
-
60
- @staticmethod
61
- def getObjectPreview(obj: pwprot.Step):
62
-
63
- args = json.loads(obj.argsStr.get())
64
- msg = "*Prerequisites*: %s \n" % str(obj._prerequisites)
65
-
66
- msg += ("*Arguments*:\n")
67
- for arg in args:
68
- msg += " %s\n" % arg
69
-
70
- msg += "*Needs GPU*: %s" % obj.needsGPU()
71
-
72
- if hasattr(obj, 'resultFiles'):
73
- results = json.loads(obj.resultFiles.get())
74
- if len(results):
75
- msg += "\n*Result files:* " + '\n '.join(results)
76
-
77
- return None, msg
78
-
79
- class StepsWindow(pwgui.browser.BrowserWindow):
80
- def __init__(self, title, parentWindow, protocol, **args):
81
- self._protocol = protocol
82
- provider = StepsTreeProvider(protocol.loadSteps())
83
- pwgui.browser.BrowserWindow.__init__(self, title, parentWindow,
84
- weight=False, **args)
85
- # Create buttons toolbar
86
- self.root.columnconfigure(0, weight=1)
87
- self.root.rowconfigure(1, weight=1)
88
-
89
- self.fillToolBar()
90
-
91
- # Create and set browser
92
- browser = pwgui.browser.ObjectBrowser(self.root, provider,
93
- showPreviewTop=False)
94
- self.setBrowser(browser, row=1, column=0)
95
-
96
- def fillToolBar(self):
97
- # Tool bar
98
- toolbar = tk.Frame(self.root)
99
- toolbar.grid(row=0, column=0, sticky='nw', padx=5, pady=5)
100
-
101
- # Tree button
102
- btn = tk.Label(toolbar, text="Tree",
103
- image=self.getImage(Icon.CODE_BRANCH),
104
- compound=tk.LEFT, cursor='hand2')
105
- btn.bind(TK.LEFT_CLICK, self._showTree)
106
- btn.grid(row=0, column=0, sticky='nw')
107
-
108
- # Reset status
109
- btn = tk.Label(toolbar, text="Reset",
110
- image=self.getImage(Icon.BROOM),
111
- compound=tk.LEFT, cursor='hand2')
112
- btn.bind('<Button-1>', self._resetStep)
113
- btn.grid(row=0, column=1, sticky='nw')
114
-
115
- # Finish status
116
- btn = tk.Label(toolbar, text="Finish",
117
- image=self.getImage(Icon.CHECKED),
118
- compound=tk.LEFT, cursor='hand2')
119
- btn.bind('<Button-1>', self._finishStep)
120
- btn.grid(row=0, column=2, sticky='nw')
121
-
122
- def _setStepStatus(self, status):
123
-
124
- item = self.browser._lastSelected
125
- if item is not None:
126
- objId = item.getObjId()
127
- self._protocol._updateSteps(lambda step: step.setStatus(status), where="id='%s'" % objId)
128
- item.setStatus(status)
129
- self.browser.tree.update()
130
- def _resetStep(self, e=None):
131
- self._setStepStatus(pwprot.STATUS_NEW)
132
-
133
- def _finishStep(self, e=None):
134
- self._setStepStatus(pwprot.STATUS_FINISHED)
135
-
136
- # noinspection PyUnusedLocal
137
- def _showTree(self, e=None):
138
- g = self._protocol.getStepsGraph()
139
- w = pwgui.Window("Protocol steps", self, minsize=(800, 600))
140
- root = w.root
141
- canvas = pwgui.Canvas(root, width=600, height=500,
142
- tooltipCallback=self._stepTooltip,)
143
- canvas.grid(row=0, column=0, sticky='nsew')
144
- canvas.drawGraph(g, pwgui.LevelTreeLayout())
145
- w.show()
146
-
147
- def _stepTooltip(self, tw, item):
148
- """ Create the contents of the tooltip to be displayed
149
- for the given step.
150
- Params:
151
- tw: a tk.TopLevel instance (ToolTipWindow)
152
- item: the selected step.
153
- """
154
-
155
- if not hasattr(item.node, 'step'):
156
- return
157
-
158
- step = item.node.step
159
-
160
- tm = str(step.funcName)
161
-
162
- if not hasattr(tw, 'tooltipText'):
163
- frame = tk.Frame(tw)
164
- frame.grid(row=0, column=0)
165
- tw.tooltipText = pwgui.dialog.createMessageBody(
166
- frame, tm, None, textPad=0, textBg=pwutils.Color.ALT_COLOR_2)
167
- tw.tooltipText.config(bd=1, relief=tk.RAISED)
168
- else:
169
- pwgui.dialog.fillMessageText(tw.tooltipText, tm)
170
-
171
-
@@ -1,332 +0,0 @@
1
- # **************************************************************************
2
- # *
3
- # * Authors: Pablo Conesa (pconesa@cnb.csic.es)
4
- # *
5
- # * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6
- # *
7
- # * This program is free software; you can redistribute it and/or modify
8
- # * it under the terms of the GNU General Public License as published by
9
- # * the Free Software Foundation; either version 3 of the License, or
10
- # * (at your option) any later version.
11
- # *
12
- # * This program is distributed in the hope that it will be useful,
13
- # * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- # * GNU General Public License for more details.
16
- # *
17
- # * You should have received a copy of the GNU General Public License
18
- # * along with this program; if not, write to the Free Software
19
- # * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20
- # * 02111-1307 USA
21
- # *
22
- # * All comments concerning this program package may be sent to the
23
- # * e-mail address 'scipion@cnb.csic.es'
24
- # *
25
- # **************************************************************************
26
- import datetime
27
- import platform
28
- import abc
29
- from abc import ABC
30
-
31
- from pyworkflow.gui.project.constants import STATUS_COLORS, WARNING_COLOR
32
- from pyworkflow.protocol import STATUS_FAILED
33
- from pyworkflow.viewer import ProtocolViewer
34
-
35
-
36
- def getStatusColorFromNode(node):
37
- # If it is a run node (not PROJECT)
38
- return getStatusColorFromRun(node.run)
39
-
40
-
41
- def getStatusColorFromRun(prot):
42
- """ Returns the color associated with the status. """
43
- if prot:
44
- if prot.hasSummaryWarnings():
45
- return WARNING_COLOR
46
- else:
47
- return getStatusColor(prot.status.get(STATUS_FAILED))
48
- else:
49
- return getStatusColor()
50
-
51
-
52
- def getStatusColor(status=None, default='#ADD8E6'):
53
- """
54
- Parameters
55
- ----------
56
- status status of the protocol
57
-
58
- Returns the color associated with he status
59
- -------
60
-
61
- """
62
- return STATUS_COLORS[status] if status else default
63
-
64
- # OS dependent behaviour. Add any OS dependent method here and later we might move
65
- # or refactor this to a class or something else
66
-
67
-
68
- class OSHandler(abc.ABC):
69
- """ Abstract class: Handler for OS specific actions"""
70
- def maximizeWindow(root):
71
- pass
72
-
73
-
74
- class LinuxHandler(OSHandler, ABC):
75
-
76
- def maximizeWindow(root):
77
- root.attributes("-zoomed", True)
78
-
79
-
80
- class MacHandler(OSHandler, ABC):
81
-
82
- def maximizeWindow(root):
83
- root.state("zoomed")
84
-
85
-
86
- class WindowsHandler(OSHandler, ABC):
87
-
88
- def maximizeWindow(root):
89
- root.state("zoomed")
90
-
91
-
92
- class OS:
93
- _handler = None
94
-
95
- _handlers = {"Linux": LinuxHandler,
96
- "Darwin": MacHandler,
97
- "Windows": WindowsHandler} # Until testing this on windows
98
-
99
- @staticmethod
100
- def getPlatform():
101
- return platform.system()
102
-
103
- @classmethod
104
- def handler(cls):
105
- if cls._handler is None:
106
- cls._handler = cls._handlers[cls.getPlatform()]
107
-
108
- return cls._handler
109
-
110
-
111
- def isAFinalProtocol(v, k):
112
- if (issubclass(v, ProtocolViewer) or
113
- v.isBase() or v.isDisabled()):
114
- return False
115
-
116
- return v.__name__ == k
117
-
118
-
119
- def inspectObj(object, filename, prefix='', maxDeep=5, inspectDetail=2, memoryDict=None):
120
- """ Creates a .CSV file in the filename path with
121
- all its members and recursively with a certain maxDeep,
122
- if maxDeep=0 means no maxDeep (until all members are inspected).
123
-
124
- inspectDetail can be:
125
- - 1: All attributes are shown
126
- - 2: All attributes are shown and iterable values are also inspected
127
-
128
- prefix and memoryDict will be updated in the recursive entries:
129
- - prefix is a compound of the two first columns (DEEP and Tree)
130
- - memoryDict is a dictionary with the memory address and an identifier
131
- """
132
- END_LINE = '\n' # end of line char
133
- COL_DELIM = '\t' # column delimiter
134
- INDENT_COUNTER = '/' # character append in each indention (it's not written)
135
-
136
- NEW_CHILD = ' |------> ' # new item indention
137
- BAR_CHILD = ' | ' + INDENT_COUNTER # bar indention
138
- END_CHILD = (' -- ' + COL_DELIM) * 4 + END_LINE # Child ending
139
- column1 = ' - Name - ' + COL_DELIM
140
- column2 = ' - Type - ' + COL_DELIM
141
- column3 = ' - Value - ' + COL_DELIM
142
- column4 = ' - Memory Address -'
143
-
144
- # Constants to distinguish the first, last and middle rows
145
- IS_FIRST = 1
146
- IS_LAST = -1
147
- IS_MIDDLE = 0
148
-
149
- memoryDict = memoryDict or {}
150
-
151
- def writeRow(name, value, prefix, posList=False):
152
- """ Writes a row item. """
153
- # we will avoid to recursively print the items wrote before
154
- # (ie. with the same memory address), thus we store a dict with the
155
- # addresses and the flag isNew is properly set
156
- if str(hex(id(value))) in memoryDict:
157
- memorySTR = memoryDict[str(hex(id(value)))]
158
- isNew = False
159
- else:
160
- # if the item is new, we save its memory address in the memoryDict
161
- # and we pass the name and the line on the file as a reference.
162
- memorySTR = str(hex(id(value)))
163
- file = open(filename, 'r')
164
- lineNum = str(len(file.readlines()) + 1)
165
- file.close()
166
- nameDict = str(name)[0:15] + ' ...' if len(str(name)) > 25 else str(name)
167
- memoryDict[str(hex(id(value)))] = '>>> ' + nameDict + ' - L:' + lineNum
168
- isNew = True
169
-
170
- if posList:
171
- # if we have a List, the third column is 'pos/lenght'
172
- thirdCol = posList
173
- else:
174
- # else, we print the value avoiding the EndOfLine char (// instead)
175
- thirdCol = str(value).replace(END_LINE, ' // ')
176
-
177
- # we will print the indentation deep number in the first row
178
- indentionDeep = prefix.count(INDENT_COUNTER)
179
- deepStr = str(indentionDeep) + COL_DELIM
180
-
181
- # the prefix without the indentCounters is
182
- # the tree to be printed in the 2nd row
183
- prefixToWrite = prefix.replace(INDENT_COUNTER, '')
184
-
185
- file = open(filename, 'a')
186
- file.write(deepStr + prefixToWrite + COL_DELIM +
187
- str(name) + COL_DELIM +
188
- str(type(value)) + COL_DELIM +
189
- thirdCol + COL_DELIM +
190
- memorySTR + END_LINE)
191
- file.close()
192
-
193
- return isNew
194
-
195
- def recursivePrint(value, prefix, isFirstOrLast):
196
- """ We print the childs items of tuples, lists, dicts and classes. """
197
-
198
- # if it's the last item, its childs has not the bar indention
199
- if isFirstOrLast == IS_LAST: # void indention when no more items
200
- prefixList = prefix.split(INDENT_COUNTER)
201
- prefixList[-2] = prefixList[-2].replace('|', ' ')
202
- prefix = INDENT_COUNTER.join(prefixList)
203
-
204
- # recursive step with the new prefix and memory dict.
205
- inspectObj(value, filename, prefix + BAR_CHILD, maxDeep, inspectDetail,
206
- memoryDict)
207
-
208
- if isFirstOrLast == IS_FIRST:
209
- deepStr = str(indentionDeep) + COL_DELIM
210
- else:
211
- # When it was not the first item, the deep is increased
212
- # to improve the readability when filter
213
- deepStr = str(indentionDeep + 1) + COL_DELIM
214
-
215
- prefix = prefix.replace(INDENT_COUNTER, '') + COL_DELIM
216
-
217
- # We introduce the end of the child and
218
- # also the next header while it is not the last
219
- file = open(filename, 'a')
220
- file.write(deepStr + prefix + END_CHILD)
221
- if isFirstOrLast != IS_LAST:
222
- # header
223
- file.write(deepStr + prefix +
224
- column1 + column2 + column3 + column4 + END_LINE)
225
- file.close()
226
-
227
- def isIterable(obj):
228
- """ Returns true if obj is a tuple, list, dict or calls. """
229
- isTupleListDict = (isinstance(obj, tuple) or
230
- isinstance(obj, dict) or
231
- isinstance(obj, list)) and len(value) > 1
232
-
233
- # FIX ME: I don't know how to assert if is a class or not...
234
- isClass = str(type(obj))[1] == 'c'
235
-
236
- return isClass or (isTupleListDict and inspectDetail < 2)
237
-
238
- indentionDeep = prefix.count(INDENT_COUNTER)
239
- if indentionDeep == 0:
240
- prefix = ' - Root - '
241
-
242
- # dict with name and value pairs of the members
243
- if len(object) == 1:
244
- # if only one obj is passed in the input list,
245
- # we directly inspect that obj.
246
- obj_dict = object[0].__dict__
247
- object = object[0]
248
-
249
- # setting the header row
250
- treeHeader = ' - Print on ' + str(datetime.datetime.now())
251
- prefixHeader = '-DEEP-' + COL_DELIM + treeHeader + COL_DELIM
252
- col1 = ' - Name - (value for Lists and Tuples)' + COL_DELIM
253
- col3 = ' - Value - (Pos./Len for Lists and Tuples) ' + COL_DELIM
254
-
255
- # writing the header row
256
- file = open(filename, 'w')
257
- file.write(prefixHeader + col1 + column2 + col3 + column4 + END_LINE)
258
- file.close()
259
-
260
- # writing the root object
261
- writeRow(object.__class__.__name__, object, prefix)
262
- # adding the child bar to the prefix
263
- prefix = ' ' + BAR_CHILD
264
- else:
265
- # firsts settings depending on the type of the obj
266
- if str(type(object))[1] == 'c':
267
- obj_dict = object.__dict__
268
- elif (isinstance(object, tuple) or
269
- isinstance(object, list)):
270
- column1 = ' - Value - ' + COL_DELIM
271
- column3 = ' - Pos./Len. - ' + COL_DELIM
272
- elif isinstance(object, dict):
273
- column1 = ' - Key - ' + COL_DELIM
274
- obj_dict = object
275
- else: # if is not of the type above it not make sense to continue
276
- return
277
-
278
- indentionDeep = prefix.count(INDENT_COUNTER)
279
- deepStr = str(indentionDeep) + COL_DELIM
280
- isBelowMaxDeep = indentionDeep < maxDeep if maxDeep > 0 else True
281
-
282
- prefixToWrite = prefix.replace(INDENT_COUNTER, '') + COL_DELIM
283
- file = open(filename, 'a')
284
- file.write(deepStr + prefixToWrite +
285
- column1 + column2 + column3 + column4 + END_LINE)
286
- file.close()
287
-
288
- # we update the prefix to put the NEW_CHILD string ( |----> )
289
- prefixList = prefix.split(INDENT_COUNTER)
290
- prefixList[-2] = NEW_CHILD
291
- # we return to the string structure
292
- # with a certain indention if it's the root
293
- prefixToWrite = ' ' + INDENT_COUNTER.join(prefixList) if indentionDeep == 1 \
294
- else INDENT_COUNTER.join(prefixList)
295
-
296
- isNew = True
297
- if str(type(object))[1] == 'c' or isinstance(object, dict):
298
- counter = 0
299
- for key, value in obj_dict.items():
300
- counter += 1
301
- # write the variable
302
- isNew = writeRow(key, value, prefixToWrite)
303
-
304
- # managing the extremes of the loop
305
- if counter == 1:
306
- isFirstOrLast = IS_FIRST
307
- elif counter == len(obj_dict):
308
- isFirstOrLast = IS_LAST
309
- else:
310
- isFirstOrLast = IS_MIDDLE
311
-
312
- # show attributes for objects and items for lists and tuples
313
- if isBelowMaxDeep and isNew and isIterable(value):
314
- recursivePrint(value, prefix, isFirstOrLast)
315
- else:
316
- for i in range(0, len(object)):
317
- # write the variable
318
- isNew = writeRow(object[i], object[i], prefixToWrite,
319
- str(i + 1) + '/' + str(len(object)))
320
-
321
- # managing the extremes of the loop
322
- if i == 0:
323
- isFirstOrLast = IS_FIRST
324
- elif len(object) == i + 1:
325
- isFirstOrLast = IS_LAST
326
- else:
327
- isFirstOrLast = IS_MIDDLE
328
-
329
- # show attributes for objects and items for lists and tuples
330
- if isBelowMaxDeep and isNew and isIterable(object[i]):
331
- recursivePrint(object[i], prefix, isFirstOrLast)
332
-