scipion-pyworkflow 3.10.6__py3-none-any.whl → 3.11.1__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.
- pyworkflow/config.py +131 -67
- pyworkflow/constants.py +2 -1
- pyworkflow/gui/browser.py +39 -5
- pyworkflow/gui/dialog.py +2 -0
- pyworkflow/gui/form.py +141 -52
- pyworkflow/gui/gui.py +8 -8
- pyworkflow/gui/project/project.py +6 -7
- pyworkflow/gui/project/searchprotocol.py +91 -7
- pyworkflow/gui/project/viewdata.py +1 -1
- pyworkflow/gui/project/viewprotocols.py +45 -22
- pyworkflow/gui/project/viewprotocols_extra.py +9 -6
- pyworkflow/gui/widgets.py +2 -2
- pyworkflow/mapper/sqlite.py +4 -4
- pyworkflow/plugin.py +93 -44
- pyworkflow/project/project.py +158 -70
- pyworkflow/project/usage.py +165 -0
- pyworkflow/protocol/executor.py +30 -18
- pyworkflow/protocol/hosts.py +9 -6
- pyworkflow/protocol/launch.py +15 -8
- pyworkflow/protocol/params.py +59 -19
- pyworkflow/protocol/protocol.py +124 -58
- pyworkflow/resources/showj/arrowDown.png +0 -0
- pyworkflow/resources/showj/arrowUp.png +0 -0
- pyworkflow/resources/showj/background_section.png +0 -0
- pyworkflow/resources/showj/colRowModeOff.png +0 -0
- pyworkflow/resources/showj/colRowModeOn.png +0 -0
- pyworkflow/resources/showj/delete.png +0 -0
- pyworkflow/resources/showj/doc_icon.png +0 -0
- pyworkflow/resources/showj/download_icon.png +0 -0
- pyworkflow/resources/showj/enabled_gallery.png +0 -0
- pyworkflow/resources/showj/galleryViewOff.png +0 -0
- pyworkflow/resources/showj/galleryViewOn.png +0 -0
- pyworkflow/resources/showj/goto.png +0 -0
- pyworkflow/resources/showj/menu.png +0 -0
- pyworkflow/resources/showj/separator.png +0 -0
- pyworkflow/resources/showj/tableViewOff.png +0 -0
- pyworkflow/resources/showj/tableViewOn.png +0 -0
- pyworkflow/resources/showj/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- pyworkflow/resources/showj/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- pyworkflow/resources/showj/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- pyworkflow/resources/showj/volumeOff.png +0 -0
- pyworkflow/resources/showj/volumeOn.png +0 -0
- pyworkflow/utils/log.py +15 -6
- pyworkflow/utils/properties.py +78 -92
- pyworkflow/utils/utils.py +3 -2
- pyworkflow/viewer.py +23 -1
- pyworkflow/webservices/config.py +0 -3
- pyworkflow/webservices/notifier.py +24 -34
- pyworkflowtests/protocols.py +1 -3
- pyworkflowtests/tests/test_protocol_execution.py +4 -0
- {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/METADATA +13 -27
- {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/RECORD +56 -35
- {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/WHEEL +1 -1
- scipion_pyworkflow-3.10.6.dist-info/dependency_links.txt +0 -1
- {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/entry_points.txt +0 -0
- {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/licenses/LICENSE.txt +0 -0
- {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/top_level.txt +0 -0
@@ -25,11 +25,11 @@
|
|
25
25
|
import logging
|
26
26
|
logger = logging.getLogger(__name__)
|
27
27
|
|
28
|
-
from pyworkflow import Config, DEFAULT_EXECUTION_ACTION_ASK, DEFAULT_EXECUTION_ACTION_SINGLE
|
28
|
+
from pyworkflow import Config, DEFAULT_EXECUTION_ACTION_ASK, DEFAULT_EXECUTION_ACTION_SINGLE, DOCSITEURLS
|
29
29
|
from pyworkflow.gui import LIST_TREEVIEW, \
|
30
|
-
ShortCut, ToolTip, RESULT_RUN_ALL, RESULT_RUN_SINGLE, RESULT_CANCEL, BORDERLESS_TREEVIEW
|
30
|
+
ShortCut, ToolTip, RESULT_RUN_ALL, RESULT_RUN_SINGLE, RESULT_CANCEL, BORDERLESS_TREEVIEW, showInfo
|
31
31
|
from pyworkflow.gui.project.constants import *
|
32
|
-
from pyworkflow.protocol import SIZE_1MB, SIZE_1GB, SIZE_1TB
|
32
|
+
from pyworkflow.protocol import SIZE_1MB, SIZE_1GB, SIZE_1TB, Protocol
|
33
33
|
|
34
34
|
INIT_REFRESH_SECONDS = Config.SCIPION_GUI_REFRESH_INITIAL_WAIT
|
35
35
|
|
@@ -299,7 +299,7 @@ class ProtocolsView(tk.Frame):
|
|
299
299
|
""" Call appropriate viewer for objId. """
|
300
300
|
proj = self.project
|
301
301
|
obj = proj.getObject(int(objId))
|
302
|
-
viewerClasses = self.domain.findViewers(obj
|
302
|
+
viewerClasses = self.domain.findViewers(obj, DESKTOP_TKINTER)
|
303
303
|
if not viewerClasses:
|
304
304
|
return # TODO: protest nicely
|
305
305
|
viewer = viewerClasses[0](project=proj, parent=self.window)
|
@@ -401,12 +401,12 @@ class ProtocolsView(tk.Frame):
|
|
401
401
|
def _findProtocol(self, event=None):
|
402
402
|
""" Find a desired protocol by typing some keyword. """
|
403
403
|
|
404
|
-
if event is not None and event.widget.widgetName=="canvas":
|
404
|
+
if event is not None and self._noSelection() and event.widget.widgetName=="canvas" and self:
|
405
405
|
position = self.runsGraphCanvas.getCoordinates(event)
|
406
406
|
else:
|
407
407
|
position = None
|
408
408
|
|
409
|
-
window = SearchProtocolWindow(self.window, position=position)
|
409
|
+
window = SearchProtocolWindow(self.window, position=position, selectionGetter=self.getSelectedProtocol)
|
410
410
|
window.show()
|
411
411
|
|
412
412
|
def _locateProtocol(self, e=None):
|
@@ -1035,16 +1035,34 @@ class ProtocolsView(tk.Frame):
|
|
1035
1035
|
self.viewButtons[ACTION_TREE].grid(row=0, column=1)
|
1036
1036
|
|
1037
1037
|
def _protocolItemClick(self, e=None, position=None):
|
1038
|
-
""" Callback for the window to add a new protocol.
|
1038
|
+
""" Callback for the window to add a new protocol.
|
1039
|
+
"""
|
1039
1040
|
|
1040
1041
|
# Get the tree widget that originated the event
|
1041
1042
|
# it could be the left panel protocols tree or just
|
1042
|
-
# the search protocol dialog tree
|
1043
|
+
# the search protocol dialog tree. In this case now non installed protocols are listed from the suggestions
|
1043
1044
|
tree = e.widget
|
1045
|
+
|
1046
|
+
# Get the class name
|
1044
1047
|
protClassName = tree.getFirst().split('.')[-1]
|
1048
|
+
|
1049
|
+
# Get the class: Now it may not be installed!!
|
1045
1050
|
protClass = self.domain.getProtocols().get(protClassName)
|
1046
|
-
|
1047
|
-
|
1051
|
+
|
1052
|
+
# If found continue to open the protocol form to ask for parameters
|
1053
|
+
if protClass is not None:
|
1054
|
+
prot = self.project.newProtocol(protClass)
|
1055
|
+
self._openProtocolForm(prot, disableRunMode=True, position=position, previousProt=self.getSelectedProtocol())
|
1056
|
+
# Missing class: probably not installed. Inform
|
1057
|
+
else:
|
1058
|
+
# Get the value as populated in pyworkflow.gui.project.searchprotocol.py:235 comming from SearchProtocolWindow.addSuggestions
|
1059
|
+
rowValues = tree.item(protClassName)["values"]
|
1060
|
+
prot_label = rowValues[0]
|
1061
|
+
installedMsg = rowValues[2]
|
1062
|
+
msg = ("%s %s To get it use the plugin manager or installation "
|
1063
|
+
"command and restart Scipion. See %s .") % (prot_label, installedMsg, DOCSITEURLS.PLUGIN_MANAGER)
|
1064
|
+
showInfo("%s protocol is missing." % prot_label,
|
1065
|
+
msg, self)
|
1048
1066
|
|
1049
1067
|
def _toggleColorScheme(self, e=None):
|
1050
1068
|
|
@@ -1332,13 +1350,20 @@ class ProtocolsView(tk.Frame):
|
|
1332
1350
|
#
|
1333
1351
|
# if update is not None: self._updateSelection()
|
1334
1352
|
|
1335
|
-
def _openProtocolForm(self, prot, disableRunMode=False, position=None):
|
1336
|
-
"""Open the Protocol GUI Form given a Protocol instance
|
1353
|
+
def _openProtocolForm(self, prot, disableRunMode=False, position=None, previousProt=None):
|
1354
|
+
"""Open the Protocol GUI Form given a Protocol instance
|
1355
|
+
|
1356
|
+
:param prot: protocol to show and edit its parameters
|
1357
|
+
:param disableRunMode: to show the form it in read only mode
|
1358
|
+
:param position: Optional. Position to add the box once added to the graph.
|
1359
|
+
:param previousProt: Optional. If passed it will try to link this protocol to the previous protocol.
|
1360
|
+
|
1361
|
+
"""
|
1337
1362
|
|
1338
1363
|
w = FormWindow(Message.TITLE_NAME_RUN + prot.getClassName(),
|
1339
1364
|
prot, self._executeSaveProtocol, self.window,
|
1340
1365
|
updateProtocolCallback=self._updateProtocol,
|
1341
|
-
disableRunMode=disableRunMode, position=position)
|
1366
|
+
disableRunMode=disableRunMode, position=position, previousProt=previousProt)
|
1342
1367
|
w.adjustSize()
|
1343
1368
|
w.show(center=True)
|
1344
1369
|
|
@@ -1495,7 +1520,7 @@ class ProtocolsView(tk.Frame):
|
|
1495
1520
|
|
1496
1521
|
def _scheduleRunsUpdate(self, secs=1, position=None):
|
1497
1522
|
# self.runsTree.after(secs*1000, self.refreshRuns)
|
1498
|
-
self.window.enqueue(lambda
|
1523
|
+
self.window.enqueue(lambda: self.refreshRuns(position=position))
|
1499
1524
|
|
1500
1525
|
def executeProtocol(self, prot):
|
1501
1526
|
""" Function to execute a protocol called not
|
@@ -1509,7 +1534,6 @@ class ProtocolsView(tk.Frame):
|
|
1509
1534
|
if onlySave:
|
1510
1535
|
self.project.saveProtocol(prot)
|
1511
1536
|
msg = Message.LABEL_SAVED_FORM
|
1512
|
-
# msg = "Protocol successfully saved."
|
1513
1537
|
|
1514
1538
|
else:
|
1515
1539
|
if doSchedule:
|
@@ -1596,7 +1620,6 @@ class ProtocolsView(tk.Frame):
|
|
1596
1620
|
def _copyProtocolsToClipboard(self, e=None):
|
1597
1621
|
|
1598
1622
|
protocols = self._getSelectedProtocols()
|
1599
|
-
|
1600
1623
|
jsonStr = self.project.getProtocolsJson(protocols)
|
1601
1624
|
|
1602
1625
|
self.clipboard_clear()
|
@@ -1865,13 +1888,13 @@ class ProtocolsView(tk.Frame):
|
|
1865
1888
|
self._lastStatus = None # force logs to re-load
|
1866
1889
|
self._scheduleRunsUpdate()
|
1867
1890
|
|
1868
|
-
def _analyzeResults(self, prot, keyPressed):
|
1869
|
-
viewers = self.domain.findViewers(prot
|
1891
|
+
def _analyzeResults(self, prot:Protocol, keyPressed):
|
1892
|
+
viewers = self.domain.findViewers(prot, DESKTOP_TKINTER)
|
1870
1893
|
if len(viewers):
|
1871
1894
|
# Instantiate the first available viewer
|
1872
|
-
|
1873
|
-
|
1874
|
-
firstViewer =
|
1895
|
+
viewer = viewers[0]
|
1896
|
+
logger.info("Specific viewer found for protocol %s: %s" % (prot.getRunName, viewer))
|
1897
|
+
firstViewer = viewer(project=self.project, protocol=prot,
|
1875
1898
|
parent=self.window, keyPressed=keyPressed)
|
1876
1899
|
|
1877
1900
|
if isinstance(firstViewer, ProtocolViewer):
|
@@ -1884,7 +1907,7 @@ class ProtocolsView(tk.Frame):
|
|
1884
1907
|
outputList.append(output)
|
1885
1908
|
|
1886
1909
|
for output in outputList:
|
1887
|
-
viewers = self.domain.findViewers(output
|
1910
|
+
viewers = self.domain.findViewers(output, DESKTOP_TKINTER)
|
1888
1911
|
if len(viewers):
|
1889
1912
|
# Instantiate the first available viewer
|
1890
1913
|
# TODO: If there are more than one viewer we should display
|
@@ -27,8 +27,12 @@ import json
|
|
27
27
|
import os
|
28
28
|
from configparser import ConfigParser
|
29
29
|
|
30
|
+
import logging
|
31
|
+
logger = logging.getLogger(__name__)
|
32
|
+
|
33
|
+
|
30
34
|
from pyworkflow import Config
|
31
|
-
import
|
35
|
+
import pyworkflow.gui as pwgui
|
32
36
|
import pyworkflow.object as pwobj
|
33
37
|
import pyworkflow.utils as pwutils
|
34
38
|
from pyworkflow.gui.project.utils import isAFinalProtocol
|
@@ -113,7 +117,7 @@ class RunIOTreeProvider(pwgui.tree.TreeProvider):
|
|
113
117
|
% objLabel):
|
114
118
|
prot.getProject().deleteProtocolOutput(prot, obj)
|
115
119
|
self.parent._fillSummary()
|
116
|
-
|
120
|
+
logger.info("Object *%s* successfully deleted upon user request."
|
117
121
|
% objLabel)
|
118
122
|
except Exception as ex:
|
119
123
|
self.parent.window.showError(str(ex))
|
@@ -138,7 +142,7 @@ class RunIOTreeProvider(pwgui.tree.TreeProvider):
|
|
138
142
|
self._loggerCallback("Discovering viewers for the first time across all the plugins.")
|
139
143
|
|
140
144
|
|
141
|
-
viewers = Config.getDomain().findViewers(obj
|
145
|
+
viewers = Config.getDomain().findViewers(obj, DESKTOP_TKINTER)
|
142
146
|
|
143
147
|
def viewerCallback(viewer):
|
144
148
|
return lambda: self._visualizeObject(viewer, obj)
|
@@ -191,7 +195,7 @@ class RunIOTreeProvider(pwgui.tree.TreeProvider):
|
|
191
195
|
try:
|
192
196
|
value = str(label)
|
193
197
|
except Exception as e:
|
194
|
-
|
198
|
+
logger.info("Can not convert object %s - %s to string." % (key, name))
|
195
199
|
value = str(e)
|
196
200
|
|
197
201
|
return value
|
@@ -502,8 +506,7 @@ class ProtocolTreeConfig:
|
|
502
506
|
cls.__addProtocolsFromConf(protocols, protocolsConfPath)
|
503
507
|
|
504
508
|
except Exception as e:
|
505
|
-
|
506
|
-
'To solve it, fix %s and run again.' % (e, pluginName))
|
509
|
+
logger.info(f'Failed to read protocols.conf from {pluginName}. The reported error was:\n {e}\n')
|
507
510
|
|
508
511
|
# Clean empty sections
|
509
512
|
cls._hideEmptySections(protocols)
|
pyworkflow/gui/widgets.py
CHANGED
@@ -281,8 +281,8 @@ class GradientFrame(tk.Canvas):
|
|
281
281
|
|
282
282
|
def __init__(self, parent, **args):
|
283
283
|
tk.Canvas.__init__(self, parent, **args)
|
284
|
-
self._color1 = Config.SCIPION_BG_COLOR
|
285
|
-
self._color2 = Config.SCIPION_MAIN_COLOR
|
284
|
+
self._color1 = Config.SCIPION_BG_COLOR
|
285
|
+
self._color2 = Config.SCIPION_MAIN_COLOR
|
286
286
|
self.bind("<Configure>", self._draw_gradient)
|
287
287
|
|
288
288
|
def _draw_gradient(self, event=None):
|
pyworkflow/mapper/sqlite.py
CHANGED
@@ -1543,18 +1543,18 @@ class SqliteFlatDb(SqliteDb):
|
|
1543
1543
|
return self._results(iterate=False)
|
1544
1544
|
|
1545
1545
|
def count(self):
|
1546
|
-
""" Return the number of
|
1547
|
-
self.executeCommand(self.selectCmd(
|
1546
|
+
""" Return the number of elements in the table. """
|
1547
|
+
self.executeCommand(self.selectCmd(None, orderByStr="").replace('*', 'COUNT(*)'))
|
1548
1548
|
return self.cursor.fetchone()[0]
|
1549
1549
|
|
1550
1550
|
def maxId(self):
|
1551
1551
|
""" Return the maximum id from the Objects table. """
|
1552
|
-
self.executeCommand(self.selectCmd(
|
1552
|
+
self.executeCommand(self.selectCmd(None, orderByStr="").replace('*', 'MAX(id)'))
|
1553
1553
|
return self.cursor.fetchone()[0]
|
1554
1554
|
|
1555
1555
|
# FIXME: Seems to be duplicated and a subset of selectAll
|
1556
1556
|
def selectObjectsBy(self, iterate=False, **args):
|
1557
|
-
"""More flexible select where the
|
1557
|
+
"""More flexible select where the constraints can be passed
|
1558
1558
|
as a dictionary, the concatenation is done by an AND"""
|
1559
1559
|
whereList = ['%s=?' % k for k in args.keys()]
|
1560
1560
|
whereStr = ' AND '.join(whereList)
|
pyworkflow/plugin.py
CHANGED
@@ -28,6 +28,7 @@
|
|
28
28
|
# **************************************************************************
|
29
29
|
import logging
|
30
30
|
import sys
|
31
|
+
from functools import lru_cache
|
31
32
|
|
32
33
|
from pyworkflow import Variable, VariablesRegistry, VarTypes
|
33
34
|
from .protocol import Protocol
|
@@ -79,6 +80,9 @@ class Domain:
|
|
79
80
|
_viewers = {}
|
80
81
|
_wizards = {}
|
81
82
|
|
83
|
+
# Preferred viewers:
|
84
|
+
_preferred_viewers = None
|
85
|
+
|
82
86
|
@classmethod
|
83
87
|
def registerPlugin(cls, name):
|
84
88
|
""" Register a new plugin. This function should only be called when
|
@@ -113,15 +117,17 @@ class Domain:
|
|
113
117
|
|
114
118
|
# Catch any import exception, warn about it but continue.
|
115
119
|
except ModuleNotFoundError as e:
|
120
|
+
|
121
|
+
logger.debug("Module %s not found: %s" %(name, e))
|
116
122
|
if e.name == name:
|
117
123
|
# This is probably due to a priority package like pwchem not being installed
|
118
|
-
|
124
|
+
logger.debug("Name is different!!: e.name='%s', name='%s'" %( e.name , name))
|
119
125
|
else:
|
120
126
|
logger.warning("Plugin '%s' has import errors: %s. Maybe a missing dependency?. "
|
121
127
|
"Is it devel mode and need to be reinstalled?. Ignoring it and continuing." % (name, str(e)))
|
122
128
|
except Exception as e:
|
123
129
|
|
124
|
-
(pwutils.yellow("WARNING!!: Plugin containing module %s does not import properly. "
|
130
|
+
logger.info(pwutils.yellow("WARNING!!: Plugin containing module %s does not import properly. "
|
125
131
|
"All its content will be missing in this execution." % name))
|
126
132
|
logger.info("Please, contact developers at %s and send this ugly information below. They'll understand it!." % DOCSITEURLS.CONTACTUS)
|
127
133
|
logger.info("Error message: %s"% str(e))
|
@@ -390,56 +396,99 @@ class Domain:
|
|
390
396
|
@classmethod
|
391
397
|
def getPreferredViewers(cls, className):
|
392
398
|
""" Find and import the preferred viewers for this class. """
|
393
|
-
|
394
|
-
if
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
399
|
+
|
400
|
+
if cls._preferred_viewers is None:
|
401
|
+
logger.info("Caching preferred viewers from VIEWERS config variable.")
|
402
|
+
cls._preferred_viewers = dict()
|
403
|
+
|
404
|
+
for target, viewerNames in pw.Config.VIEWERS.items():
|
405
|
+
viewers = []
|
406
|
+
for prefViewerStr in viewerNames:
|
407
|
+
try:
|
408
|
+
viewerModule, viewerClassName = prefViewerStr.rsplit('.', 1)
|
409
|
+
prefViewer = cls.importFromPlugin(viewerModule,
|
410
|
+
viewerClassName,
|
411
|
+
doRaise=True)
|
412
|
+
viewers.append(prefViewer)
|
413
|
+
except Exception as e:
|
414
|
+
logger.error("Couldn't load \"%s\" as preferred viewer for %s.\n"
|
415
|
+
"There might be a typo in your VIEWERS variable "
|
416
|
+
"or an error in the viewer's plugin installation"
|
417
|
+
% (prefViewerStr, className), exc_info=e)
|
418
|
+
|
419
|
+
cls._preferred_viewers[target] = viewers
|
420
|
+
|
421
|
+
return cls._preferred_viewers.get(className, [])
|
422
|
+
|
423
|
+
@classmethod
|
424
|
+
@lru_cache
|
425
|
+
def getViewersSorted(cls):
|
426
|
+
""" Returns all viewers sorted by its class name"""
|
427
|
+
|
428
|
+
viewers = cls.getViewers()
|
429
|
+
return [viewers[key] for key in sorted(viewers)]
|
410
430
|
|
411
431
|
@classmethod
|
412
|
-
def findViewers(cls,
|
413
|
-
""" Find the available viewers in this Domain for this
|
432
|
+
def findViewers(cls, target, environment):
|
433
|
+
""" Find the available viewers in this Domain for this target.
|
434
|
+
|
435
|
+
Sorting criteria:
|
436
|
+
|
437
|
+
1st Will appear those viewers in VIEWERS variable (preferred viewers) in appearance order
|
438
|
+
2nd Viewers targeting specifically the target and not any super class of it
|
439
|
+
3rd rest.
|
440
|
+
|
441
|
+
In 2nd and 3rd case the order viewers are added depends on the alphabetical order the viewer when discovered.
|
442
|
+
This usually matches the viewer class name, but could be fine tune using import aliases like:
|
443
|
+
|
444
|
+
from my_viewer import MyViewer as AAAMyViewer in the viewers folder of the plugin.
|
445
|
+
|
446
|
+
In case viewers is a file and not a folder with an __init__, I'm afraid class name is what is taken into account
|
447
|
+
|
448
|
+
The import order is not possible to use since python sort them automatically.
|
449
|
+
|
450
|
+
"""
|
414
451
|
viewers = []
|
415
452
|
try:
|
416
|
-
|
453
|
+
instance = None
|
454
|
+
if isinstance(target, str):
|
455
|
+
logger.warning("DEVELOPERS: pass the instance/object instead of the class. This mode will be deprecated soon")
|
456
|
+
className = target
|
457
|
+
clazz = cls.findClass(className)
|
458
|
+
else:
|
459
|
+
className = target.__class__.__name__
|
460
|
+
clazz = target.__class__
|
461
|
+
instance = target
|
462
|
+
|
417
463
|
baseClasses = clazz.mro()
|
418
|
-
preferredViewers = cls.getPreferredViewers(className)
|
419
|
-
preferedFlag = 0
|
420
464
|
|
421
|
-
|
422
|
-
|
465
|
+
# Add preferred viewers
|
466
|
+
preferred_viewers = []
|
467
|
+
available_preferred_viewers = cls.getPreferredViewers(className)
|
468
|
+
for prefViewer in available_preferred_viewers:
|
469
|
+
if prefViewer.can_handle_this(baseClasses, instance=instance):
|
470
|
+
preferred_viewers.append(prefViewer)
|
471
|
+
|
472
|
+
|
473
|
+
specific_viewers = []
|
474
|
+
other_viewers=[]
|
475
|
+
# get all the viewers available
|
476
|
+
|
477
|
+
for viewer in cls.getViewersSorted():
|
478
|
+
|
423
479
|
if environment in viewer._environments:
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
480
|
+
|
481
|
+
if viewer not in preferred_viewers:
|
482
|
+
|
483
|
+
t = viewer.can_handle_this(baseClasses, target)
|
484
|
+
if t is not None:
|
485
|
+
if t == clazz:
|
486
|
+
specific_viewers.append(viewer)
|
487
|
+
|
432
488
|
else:
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
else:
|
437
|
-
viewers.append(viewer)
|
438
|
-
viewerAdded = True
|
439
|
-
break
|
440
|
-
|
441
|
-
if viewerAdded:
|
442
|
-
break
|
489
|
+
other_viewers.append(viewer)
|
490
|
+
|
491
|
+
viewers = preferred_viewers + specific_viewers + other_viewers
|
443
492
|
|
444
493
|
except Exception as e:
|
445
494
|
# Catch if there is a missing plugin, we will get Legacy which triggers and Exception
|