scipion-pyworkflow 3.7.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 (140) hide show
  1. pyworkflow/__init__.py +33 -0
  2. pyworkflow/apps/__init__.py +29 -0
  3. pyworkflow/apps/pw_manager.py +37 -0
  4. pyworkflow/apps/pw_plot.py +51 -0
  5. pyworkflow/apps/pw_project.py +113 -0
  6. pyworkflow/apps/pw_protocol_list.py +143 -0
  7. pyworkflow/apps/pw_protocol_run.py +51 -0
  8. pyworkflow/apps/pw_run_tests.py +267 -0
  9. pyworkflow/apps/pw_schedule_run.py +322 -0
  10. pyworkflow/apps/pw_sleep.py +37 -0
  11. pyworkflow/apps/pw_sync_data.py +439 -0
  12. pyworkflow/apps/pw_viewer.py +78 -0
  13. pyworkflow/config.py +536 -0
  14. pyworkflow/constants.py +212 -0
  15. pyworkflow/exceptions.py +18 -0
  16. pyworkflow/gui/__init__.py +36 -0
  17. pyworkflow/gui/browser.py +726 -0
  18. pyworkflow/gui/canvas.py +1190 -0
  19. pyworkflow/gui/dialog.py +976 -0
  20. pyworkflow/gui/form.py +2627 -0
  21. pyworkflow/gui/graph.py +247 -0
  22. pyworkflow/gui/graph_layout.py +271 -0
  23. pyworkflow/gui/gui.py +566 -0
  24. pyworkflow/gui/matplotlib_image.py +233 -0
  25. pyworkflow/gui/plotter.py +247 -0
  26. pyworkflow/gui/project/__init__.py +25 -0
  27. pyworkflow/gui/project/base.py +192 -0
  28. pyworkflow/gui/project/constants.py +139 -0
  29. pyworkflow/gui/project/labels.py +205 -0
  30. pyworkflow/gui/project/project.py +484 -0
  31. pyworkflow/gui/project/searchprotocol.py +154 -0
  32. pyworkflow/gui/project/searchrun.py +181 -0
  33. pyworkflow/gui/project/steps.py +166 -0
  34. pyworkflow/gui/project/utils.py +332 -0
  35. pyworkflow/gui/project/variables.py +179 -0
  36. pyworkflow/gui/project/viewdata.py +472 -0
  37. pyworkflow/gui/project/viewprojects.py +510 -0
  38. pyworkflow/gui/project/viewprotocols.py +2093 -0
  39. pyworkflow/gui/project/viewprotocols_extra.py +560 -0
  40. pyworkflow/gui/text.py +771 -0
  41. pyworkflow/gui/tooltip.py +185 -0
  42. pyworkflow/gui/tree.py +684 -0
  43. pyworkflow/gui/widgets.py +307 -0
  44. pyworkflow/mapper/__init__.py +26 -0
  45. pyworkflow/mapper/mapper.py +222 -0
  46. pyworkflow/mapper/sqlite.py +1578 -0
  47. pyworkflow/mapper/sqlite_db.py +145 -0
  48. pyworkflow/object.py +1512 -0
  49. pyworkflow/plugin.py +712 -0
  50. pyworkflow/project/__init__.py +31 -0
  51. pyworkflow/project/config.py +451 -0
  52. pyworkflow/project/manager.py +179 -0
  53. pyworkflow/project/project.py +1990 -0
  54. pyworkflow/project/scripts/clean_projects.py +77 -0
  55. pyworkflow/project/scripts/config.py +92 -0
  56. pyworkflow/project/scripts/create.py +77 -0
  57. pyworkflow/project/scripts/edit_workflow.py +90 -0
  58. pyworkflow/project/scripts/fix_links.py +39 -0
  59. pyworkflow/project/scripts/load.py +87 -0
  60. pyworkflow/project/scripts/refresh.py +83 -0
  61. pyworkflow/project/scripts/schedule.py +111 -0
  62. pyworkflow/project/scripts/stack2volume.py +41 -0
  63. pyworkflow/project/scripts/stop.py +81 -0
  64. pyworkflow/protocol/__init__.py +38 -0
  65. pyworkflow/protocol/bibtex.py +48 -0
  66. pyworkflow/protocol/constants.py +86 -0
  67. pyworkflow/protocol/executor.py +334 -0
  68. pyworkflow/protocol/hosts.py +313 -0
  69. pyworkflow/protocol/launch.py +270 -0
  70. pyworkflow/protocol/package.py +42 -0
  71. pyworkflow/protocol/params.py +744 -0
  72. pyworkflow/protocol/protocol.py +2554 -0
  73. pyworkflow/resources/Imagej.png +0 -0
  74. pyworkflow/resources/chimera.png +0 -0
  75. pyworkflow/resources/fa-exclamation-triangle_alert.png +0 -0
  76. pyworkflow/resources/fa-info-circle_alert.png +0 -0
  77. pyworkflow/resources/fa-search.png +0 -0
  78. pyworkflow/resources/fa-times-circle_alert.png +0 -0
  79. pyworkflow/resources/file_vol.png +0 -0
  80. pyworkflow/resources/loading.gif +0 -0
  81. pyworkflow/resources/no-image128.png +0 -0
  82. pyworkflow/resources/scipion_bn.png +0 -0
  83. pyworkflow/resources/scipion_icon.png +0 -0
  84. pyworkflow/resources/scipion_icon.svg +397 -0
  85. pyworkflow/resources/scipion_icon_proj.png +0 -0
  86. pyworkflow/resources/scipion_icon_projs.png +0 -0
  87. pyworkflow/resources/scipion_icon_prot.png +0 -0
  88. pyworkflow/resources/scipion_logo.png +0 -0
  89. pyworkflow/resources/scipion_logo_normal.png +0 -0
  90. pyworkflow/resources/scipion_logo_small.png +0 -0
  91. pyworkflow/resources/sprites.png +0 -0
  92. pyworkflow/resources/sprites.xcf +0 -0
  93. pyworkflow/resources/wait.gif +0 -0
  94. pyworkflow/template.py +322 -0
  95. pyworkflow/tests/__init__.py +29 -0
  96. pyworkflow/tests/test_utils.py +25 -0
  97. pyworkflow/tests/tests.py +341 -0
  98. pyworkflow/utils/__init__.py +38 -0
  99. pyworkflow/utils/dataset.py +414 -0
  100. pyworkflow/utils/echo.py +104 -0
  101. pyworkflow/utils/graph.py +196 -0
  102. pyworkflow/utils/log.py +284 -0
  103. pyworkflow/utils/path.py +527 -0
  104. pyworkflow/utils/process.py +132 -0
  105. pyworkflow/utils/profiler.py +92 -0
  106. pyworkflow/utils/progressbar.py +154 -0
  107. pyworkflow/utils/properties.py +627 -0
  108. pyworkflow/utils/reflection.py +129 -0
  109. pyworkflow/utils/utils.py +877 -0
  110. pyworkflow/utils/which.py +229 -0
  111. pyworkflow/viewer.py +328 -0
  112. pyworkflow/webservices/__init__.py +8 -0
  113. pyworkflow/webservices/config.py +11 -0
  114. pyworkflow/webservices/notifier.py +162 -0
  115. pyworkflow/webservices/repository.py +59 -0
  116. pyworkflow/webservices/workflowhub.py +74 -0
  117. pyworkflow/wizard.py +64 -0
  118. pyworkflowtests/__init__.py +51 -0
  119. pyworkflowtests/bibtex.py +51 -0
  120. pyworkflowtests/objects.py +830 -0
  121. pyworkflowtests/protocols.py +154 -0
  122. pyworkflowtests/tests/__init__.py +0 -0
  123. pyworkflowtests/tests/test_canvas.py +72 -0
  124. pyworkflowtests/tests/test_domain.py +45 -0
  125. pyworkflowtests/tests/test_logs.py +74 -0
  126. pyworkflowtests/tests/test_mappers.py +392 -0
  127. pyworkflowtests/tests/test_object.py +507 -0
  128. pyworkflowtests/tests/test_project.py +42 -0
  129. pyworkflowtests/tests/test_protocol_execution.py +72 -0
  130. pyworkflowtests/tests/test_protocol_export.py +78 -0
  131. pyworkflowtests/tests/test_protocol_output.py +158 -0
  132. pyworkflowtests/tests/test_streaming.py +47 -0
  133. pyworkflowtests/tests/test_utils.py +210 -0
  134. scipion_pyworkflow-3.7.0.dist-info/LICENSE.txt +674 -0
  135. scipion_pyworkflow-3.7.0.dist-info/METADATA +107 -0
  136. scipion_pyworkflow-3.7.0.dist-info/RECORD +140 -0
  137. scipion_pyworkflow-3.7.0.dist-info/WHEEL +5 -0
  138. scipion_pyworkflow-3.7.0.dist-info/dependency_links.txt +1 -0
  139. scipion_pyworkflow-3.7.0.dist-info/entry_points.txt +5 -0
  140. scipion_pyworkflow-3.7.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,341 @@
1
+ import logging
2
+ logger = logging.getLogger(__name__)
3
+
4
+ import sys
5
+ import os
6
+ import time
7
+ from traceback import format_exception
8
+ import unittest
9
+ from os.path import join, relpath
10
+
11
+ import pyworkflow as pw
12
+ import pyworkflow.utils as pwutils
13
+ from pyworkflow.project import Manager
14
+ from pyworkflow.protocol import MODE_RESTART, getProtocolFromDb
15
+ from pyworkflow.object import Set
16
+
17
+ SMALL = 'small'
18
+ PULL_REQUEST = 'pull'
19
+ DAILY = 'daily'
20
+ WEEKLY = 'weekly'
21
+
22
+ # Type hint when creating protocols
23
+ from typing import TypeVar
24
+ T = TypeVar('T')
25
+
26
+ # Procedure to check if a test class has an attribute called _labels and if so
27
+ # then it checks if the class test matches any of the labels in input label parameter.
28
+ def hasLabel(TestClass, labels):
29
+ # Get _labels attributes in class if any.
30
+ classLabels = getattr(TestClass, '_labels', None)
31
+
32
+ # Check if no label in test class.
33
+ return classLabels is not None and any(l in classLabels for l in labels)
34
+
35
+
36
+ class DataSet:
37
+ _datasetDict = {} # store all created datasets
38
+
39
+ def __init__(self, name, folder, files, url=None):
40
+ """
41
+ Params:
42
+
43
+ #filesDict is dict with key, value pairs for each file
44
+ """
45
+ self._datasetDict[name] = self
46
+ self.folder = folder
47
+ self.path = join(pw.Config.SCIPION_TESTS, folder)
48
+ self.filesDict = files
49
+ self.url = url
50
+
51
+ def getFile(self, key):
52
+ if key in self.filesDict:
53
+ return join(self.path, self.filesDict[key])
54
+ return join(self.path, key)
55
+
56
+ def getPath(self):
57
+ return self.path
58
+
59
+ @classmethod
60
+ def getDataSet(cls, name):
61
+ """
62
+ This method is called every time the dataset want to be retrieved
63
+ """
64
+ assert name in cls._datasetDict, "Dataset: %s dataset doesn't exist." % name
65
+
66
+ ds = cls._datasetDict[name]
67
+ folder = ds.folder
68
+ url = '' if ds.url is None else ' -u ' + ds.url
69
+
70
+ if not pw.Config.SCIPION_TEST_NOSYNC:
71
+ command = ("%s %s --download %s %s"
72
+ % (pw.PYTHON, pw.getSyncDataScript(), folder, url))
73
+ logger.info(">>>> %s" % command)
74
+ os.system(command)
75
+
76
+ return cls._datasetDict[name]
77
+
78
+
79
+ class BaseTest(unittest.TestCase):
80
+ _labels = [WEEKLY]
81
+
82
+ @classmethod
83
+ def getOutputPath(cls, *filenames):
84
+ """Return the path to the SCIPION_HOME/tests/output dir
85
+ joined with filename"""
86
+ return join(cls.outputPath, *filenames)
87
+
88
+ @classmethod
89
+ def getRelPath(cls, basedir, filename):
90
+ """Return the path relative to SCIPION_HOME/tests"""
91
+ return relpath(filename, basedir)
92
+
93
+ @classmethod
94
+ def launchProtocol(cls, prot, **kwargs):
95
+ """ Launch a given protocol using cls.proj.
96
+
97
+ :param wait: if True the function will return after the protocol runs.
98
+ If not specified, then if waitForOutput is passed, wait is false.
99
+ :param waitForOutputs: a list of expected outputs, ignored if wait=True
100
+
101
+ """
102
+ wait = kwargs.get('wait', None)
103
+ waitForOutputs = kwargs.get('waitForOutput', [])
104
+
105
+ if wait is None:
106
+ wait = not waitForOutputs
107
+
108
+ if getattr(prot, '_run', True):
109
+ cls.proj.launchProtocol(prot, wait=wait)
110
+ if not wait and waitForOutputs:
111
+ while True:
112
+ time.sleep(10)
113
+ prot = cls.updateProtocol(prot)
114
+ if all(prot.hasAttribute(o) for o in waitForOutputs):
115
+ return prot
116
+
117
+ if prot.isFailed():
118
+
119
+ cls.printLastLogLines(prot)
120
+ raise Exception("Protocol %s execution failed. See last log lines above for more details." % prot.getRunName())
121
+
122
+ if not prot.isFinished() and not prot.useQueue(): # when queued is not finished yet
123
+
124
+ cls.printLastLogLines(prot)
125
+ raise Exception("Protocol %s didn't finish. See last log lines above for more details." % prot.getRunName())
126
+
127
+ return prot
128
+
129
+ @staticmethod
130
+ def printLastLogLines(prot):
131
+ """ Prints the last log lines (50 or 'PROT_LOGS_LAST_LINES' env variable) from stdout and stderr log files
132
+
133
+ :param prot: Protocol to take the logs from
134
+
135
+ """
136
+ logs = {"STD OUT": 0, "STD ERR":1}
137
+
138
+ lastLines = int(os.environ.get('PROT_LOGS_LAST_LINES', 50))
139
+
140
+ # For each log file to print
141
+ for key in logs:
142
+
143
+ logger.info(pwutils.cyanStr("\n*************** last %s lines of %s *********************\n" % (lastLines, key)))
144
+ logLines = prot.getLogsLastLines(lastLines, logFile=logs[key])
145
+ for i in range(0, len(logLines)):
146
+ logger.info(logLines[i])
147
+ logger.info(pwutils.cyanStr("\n*************** end of %s *********************\n" % key))
148
+
149
+ sys.stdout.flush()
150
+
151
+ @classmethod
152
+ def saveProtocol(cls, prot):
153
+ """ Saves a protocol using cls.proj """
154
+ cls.proj.saveProtocol(prot)
155
+
156
+ @classmethod
157
+ def _waitOutput(cls, prot, outputAttributeName, sleepTime=20, timeOut=5000):
158
+ """ Wait until the output is being generated by the protocol. """
159
+
160
+ def _loadProt():
161
+ # Load the last version of the protocol from its own database
162
+ loadedProt = getProtocolFromDb(prot.getProject().path,
163
+ prot.getDbPath(),
164
+ prot.getObjId())
165
+ # Close DB connections
166
+ loadedProt.getProject().closeMapper()
167
+ loadedProt.closeMappers()
168
+ return loadedProt
169
+
170
+ counter = 1
171
+ prot2 = _loadProt()
172
+
173
+ numberOfSleeps = timeOut/sleepTime
174
+
175
+ while (not prot2.hasAttribute(outputAttributeName)) and prot2.isActive():
176
+ time.sleep(sleepTime)
177
+ prot2 = _loadProt()
178
+ if counter > numberOfSleeps:
179
+ logger.warning("Timeout (%s) reached waiting for %s at %s" % (timeOut, outputAttributeName, prot))
180
+ break
181
+ counter += 1
182
+
183
+ # Update the protocol instance to get latest changes
184
+ cls.proj._updateProtocol(prot)
185
+
186
+ @classmethod
187
+ def newProtocol(cls, protocolClass:T, **kwargs)->T:
188
+ """ Create new protocols instances through the project
189
+ and return a newly created protocol of the given class
190
+ """
191
+ # Try to continue from previous execution
192
+ if pwutils.envVarOn('SCIPION_TEST_CONTINUE'):
193
+ candidates = cls.proj.mapper.selectByClass(protocolClass.__name__)
194
+ if candidates:
195
+ c = candidates[0]
196
+ if c.isFinished():
197
+ setattr(c, '_run', False)
198
+ else:
199
+ c.runMode.set(MODE_RESTART)
200
+ return c
201
+ return cls.proj.newProtocol(protocolClass, **kwargs)
202
+
203
+ @classmethod
204
+ def compareSets(cls, test, set1, set2):
205
+ """ Iterate the elements of both sets and check
206
+ that all elements have equal attributes. """
207
+ for item1, item2 in zip(set1, set2):
208
+ areEqual = item1.equalAttributes(item2)
209
+ if not areEqual:
210
+ logger.info("item 1 and item2 are different: ")
211
+ item1.printAll()
212
+ item2.printAll()
213
+ test.assertTrue(areEqual)
214
+
215
+ def compareSetProperties(self, set1:Set, set2:Set, ignore = ["_size", "_mapperPath"]):
216
+ """ Compares 2 sets' properties"""
217
+
218
+ self.assertTrue(set1.equalAttributes(set2, ignore=ignore, verbose=True), "Set1 (%s) properties differs from set2 (%s)." % (set1, set2))
219
+ self.assertTrue(set2.equalAttributes(set1, ignore=ignore, verbose=True), 'Set2 (%s) has properties that set1 (%s) does not have.' % (set2, set1))
220
+
221
+ def assertSetSize(self, setObject, size=None, msg=None, diffDelta=None):
222
+ """ Check if a pyworkflow Set is not None nor is empty, or of a determined size or
223
+ of a determined size with a percentage (base 1) of difference"""
224
+ self.assertIsNotNone(setObject, msg)
225
+ setObjSize = setObject.getSize()
226
+
227
+ if size is None:
228
+ # Test is not empty
229
+ self.assertNotEqual(setObjSize, 0, msg)
230
+ else:
231
+ if diffDelta:
232
+ self.assertLessEqual(abs(setObjSize - size), round(diffDelta * size), msg)
233
+ else:
234
+ self.assertEqual(setObjSize, size, msg)
235
+
236
+ def assertIsNotEmpty(self, setObject, msg=None):
237
+ """ Check if the pyworkflow object is not None nor is empty"""
238
+ self.assertIsNotNone(setObject, msg)
239
+
240
+ self.assertIsNotNone(setObject.get(), msg)
241
+
242
+ @classmethod
243
+ def setupTestOutput(cls):
244
+ setupTestOutput(cls)
245
+
246
+
247
+ def setupTestOutput(cls):
248
+ """ Create the output folder for a give Test class. """
249
+ cls.outputPath = join(pw.Config.SCIPION_TESTS_OUTPUT, cls.__name__)
250
+ pwutils.cleanPath(cls.outputPath)
251
+ pwutils.makePath(cls.outputPath)
252
+
253
+
254
+ def setupTestProject(cls, writeLocalConfig=False):
255
+ """ Create and setup a Project for a give Test class. """
256
+ projName = cls.__name__
257
+ hostsConfig = None
258
+
259
+ if writeLocalConfig:
260
+ hostsConfig = '/tmp/hosts.conf'
261
+ logger.info("Writing local config: %s" % hostsConfig)
262
+ import pyworkflow.protocol as pwprot
263
+ pwprot.HostConfig.writeBasic(hostsConfig)
264
+
265
+ if os.environ.get('SCIPION_TEST_CONTINUE', None) == '1':
266
+ proj = Manager().loadProject(projName)
267
+ else:
268
+ proj = Manager().createProject(projName, hostsConf=hostsConfig)
269
+
270
+ cls.outputPath = proj.path
271
+ # Create project does not change the working directory anymore
272
+ os.chdir(cls.outputPath)
273
+ cls.projName = projName
274
+ cls.proj = proj
275
+
276
+
277
+ class GTestResult(unittest.TestResult):
278
+ """ Subclass TestResult to output tests results with colors
279
+ (green for success and red for failure)
280
+ and write a report on an .xml file.
281
+ """
282
+ xml = None
283
+ testFailed = 0
284
+ numberTests = 0
285
+
286
+ def __init__(self):
287
+ unittest.TestResult.__init__(self)
288
+ self.startTimeAll = time.time()
289
+
290
+ def openXmlReport(self, classname, filename):
291
+ pass
292
+
293
+ def doReport(self):
294
+ secs = time.time() - self.startTimeAll
295
+ logger.info("\n%s run %d tests (%0.3f secs)\n" %
296
+ (pwutils.greenStr("[==========]"),
297
+ self.numberTests, secs))
298
+ if self.testFailed:
299
+ logger.info("%s %d tests\n"
300
+ % (pwutils.redStr("[ FAILED ]"),
301
+ self.testFailed))
302
+ logger.info("%s %d tests\n"
303
+ % (pwutils.greenStr("[ PASSED ]"),
304
+ self.numberTests - self.testFailed))
305
+
306
+ def tic(self):
307
+ self.startTime = time.time()
308
+
309
+ def toc(self):
310
+ return time.time() - self.startTime
311
+
312
+ def startTest(self, test):
313
+ self.tic()
314
+ self.numberTests += 1
315
+
316
+ @staticmethod
317
+ def getTestName(test):
318
+ parts = str(test).split()
319
+ name = parts[0]
320
+ parts = parts[1].split('.')
321
+ classname = parts[-1].replace(")", "")
322
+ return "%s.%s" % (classname, name)
323
+
324
+ def addSuccess(self, test):
325
+ secs = self.toc()
326
+ logger.info("%s %s (%0.3f secs)\n" %
327
+ (pwutils.greenStr('[ RUN OK ]'),
328
+ self.getTestName(test), secs))
329
+
330
+ def reportError(self, test, err):
331
+ logger.info("%s %s\n" % (pwutils.redStr('[ FAILED ]'),
332
+ self.getTestName(test)))
333
+ logger.info("\n%s"
334
+ % pwutils.redStr("".join(format_exception(*err))))
335
+ self.testFailed += 1
336
+
337
+ def addError(self, test, err):
338
+ self.reportError(test, err)
339
+
340
+ def addFailure(self, test, err):
341
+ self.reportError(test, err)
@@ -0,0 +1,38 @@
1
+ # **************************************************************************
2
+ # *
3
+ # * Authors: J.M. De la Rosa Trevin (jmdelarosa@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
+ """
27
+ This module contains utilities functions and classes.
28
+ """
29
+
30
+ from .utils import *
31
+ from .path import *
32
+ from .process import *
33
+ from .which import *
34
+ from .graph import *
35
+ from .reflection import *
36
+ from .log import *
37
+ from .properties import *
38
+ from .progressbar import ProgressBar