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,158 @@
1
+ # **************************************************************************
2
+ # *
3
+ # * Authors: Pablo Conesa (pconesa@cnb.csic.es) [1]
4
+ # * J.M. De la Rosa Trevin (delarosatrevin@scilifelab.se) [2]
5
+ # *
6
+ # * [1] Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
7
+ # * [2] SciLifeLab, Stockholm University
8
+ # *
9
+ # * This program is free software; you can redistribute it and/or modify
10
+ # * it under the terms of the GNU General Public License as published by
11
+ # * the Free Software Foundation; either version 3 of the License, or
12
+ # * (at your option) any later version.
13
+ # *
14
+ # * This program is distributed in the hope that it will be useful,
15
+ # * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # * GNU General Public License for more details.
18
+ # *
19
+ # * You should have received a copy of the GNU General Public License
20
+ # * along with this program; if not, write to the Free Software
21
+ # * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22
+ # * 02111-1307 USA
23
+ # *
24
+ # * All comments concerning this program package may be sent to the
25
+ # * e-mail address 'scipion@cnb.csic.es'
26
+ # *
27
+ # **************************************************************************
28
+ import os
29
+
30
+ import pyworkflow as pw
31
+ import pyworkflow.object as pwobj
32
+ import pyworkflow.tests as pwtests
33
+ import pyworkflow.mapper as pwmapper
34
+ import pyworkflow.protocol as pwprot
35
+ from pyworkflow.project import Project
36
+ from pyworkflowtests.protocols import ProtOutputTest
37
+ from pyworkflowtests import Domain, MockObject
38
+
39
+
40
+ # Protocol to output of basic scipion objects
41
+ class TestProtocolOutputs(pwtests.BaseTest):
42
+ @classmethod
43
+ def setUpClass(cls):
44
+ pwtests.setupTestProject(cls, writeLocalConfig=True)
45
+ pwtests.setupTestOutput(cls)
46
+
47
+ # Set the application domain
48
+ pw.Config.setDomain("pyworkflowtests")
49
+
50
+ def test_basicObjectOutput(self):
51
+ """Test the list with several Complex"""
52
+ fn = self.getOutputPath("protocol.sqlite")
53
+
54
+ # Discover objects and protocols
55
+ mapperDict = Domain.getMapperDict()
56
+
57
+ mapper = pwmapper.SqliteMapper(fn, mapperDict)
58
+ # Associate the project
59
+ proj = Project(Domain, path=self.getOutputPath(''))
60
+
61
+ prot = ProtOutputTest(mapper=mapper, n=2, project=proj,
62
+ workingDir=self.getOutputPath(''))
63
+
64
+ # Add and old style o, not in the outputs dictionary
65
+ prot.output1 = MockObject()
66
+
67
+ self.assertFalse(prot._useOutputList.get(),
68
+ "useOutputList wrongly initialized")
69
+
70
+ outputs = [o for o in prot.iterOutputAttributes()]
71
+ self.assertTrue(1, len(outputs))
72
+
73
+ prot._stepsExecutor = pwprot.StepExecutor(hostConfig=None)
74
+
75
+ #Create the logs folder
76
+ prot.makeWorkingDir()
77
+
78
+ prot.run()
79
+
80
+ self.assertEqual(prot._steps[0].getStatus(),
81
+ pwprot.STATUS_FINISHED)
82
+
83
+ # Check there is an output
84
+ self.assertOutput(prot)
85
+
86
+ outputs = [o for o in prot.iterOutputAttributes()]
87
+
88
+ # We are intentionally ignoring a protocol with o (EMObject)
89
+ # That has been continued, We do not find a real case now.
90
+ self.assertEqual(1, len(outputs),
91
+ msg="Integer o not registered properly.")
92
+
93
+ outputs = [o for o in prot.iterOutputAttributes(pwobj.Integer)]
94
+
95
+ # Test passing a filter
96
+ self.assertEqual(1, len(outputs),
97
+ msg="Integer not matched when filtering outputs.")
98
+
99
+ # Test with non existing class
100
+ class NotRealClass:
101
+ pass
102
+
103
+ outputs = [o for o in prot.iterOutputAttributes(NotRealClass)]
104
+
105
+ # Test passing a class
106
+ self.assertEqual(0, len(outputs),
107
+ msg="Filter by class in iterOutputAttributes does "
108
+ "not work.")
109
+
110
+ self.assertTrue(prot._useOutputList.get(),
111
+ "useOutputList not activated")
112
+
113
+ def test_basicObjectInProject(self):
114
+ prot = self.newProtocol(ProtOutputTest,
115
+ objLabel='to generate basic input')
116
+ print("working dir: %s" % prot.getWorkingDir())
117
+ # Define a negative output for later tests
118
+ prot._defineOutputs(negative=pwobj.Integer(-20))
119
+ self.launchProtocol(prot)
120
+
121
+ # Default value is 10 so output is 20
122
+ self.assertOutput(prot)
123
+
124
+ # Second protocol to test linking
125
+ prot2 = self.newProtocol(ProtOutputTest,
126
+ objLabel='to read basic input')
127
+
128
+ # Set the pointer for the integer
129
+ prot2.iBoxSize.setPointer(pwobj.Pointer(prot, extended="oBoxSize"))
130
+ self.launchProtocol(prot2)
131
+ self.assertOutput(prot2, value=40)
132
+
133
+ # Test validation: only positive numbers are allowed
134
+ prot3 = self.newProtocol(ProtOutputTest,
135
+ objLabel='invalid input',
136
+ iBoxSize=-10)
137
+ # We expect this to fail
138
+ with self.assertRaises(Exception):
139
+ self.launchProtocol(prot3)
140
+ # Test validation: pointer value is validated
141
+ prot4 = self.newProtocol(ProtOutputTest,
142
+ objLabel='invalid pointer input')
143
+ # Now use negative pointer output
144
+ prot4.iBoxSize.setPointer(pwobj.Pointer(prot, extended="negative"))
145
+
146
+ # We expect this to fail
147
+ with self.assertRaises(Exception):
148
+ self.launchProtocol(prot4)
149
+
150
+ def assertOutput(self, prot, value=20):
151
+ # Check there is an output
152
+ self.assertTrue(hasattr(prot, 'oBoxSize'),
153
+ msg="Protocol output boxSize (OInteger) not registered"
154
+ " as attribute.")
155
+
156
+ self.assertEqual(value, prot.oBoxSize.get(),
157
+ "oBoxSize value is wrong: %s , expected %s" %
158
+ (prot.oBoxSize, value))
@@ -0,0 +1,47 @@
1
+ # -*- coding: utf-8 -*-
2
+ # **************************************************************************
3
+ # *
4
+ # * Authors: J.M. De la Rosa Trevin (delarosatrevin@scilifelab.se) [1]
5
+ # *
6
+ # * [1] SciLifeLab, Stockholm University
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
+
26
+ import pyworkflow.tests as pwtests
27
+
28
+ from pyworkflow import Config
29
+ from pyworkflowtests.protocols import ConcurrencyProtocol
30
+
31
+
32
+ class TestConcurrency(pwtests.BaseTest):
33
+
34
+ @classmethod
35
+ def setUpClass(cls):
36
+ pwtests.setupTestOutput(cls)
37
+
38
+
39
+ # Set the application domain
40
+ Config.setDomain("pyworkflowtests")
41
+ pwtests.setupTestProject(cls)
42
+
43
+
44
+ def test_simple_steps_concurrency(self):
45
+ prot = self.newProtocol(ConcurrencyProtocol, numberOfThreads=3)
46
+
47
+ self.launchProtocol(prot)
@@ -0,0 +1,210 @@
1
+ #!/usr/bin/env python
2
+ # coding: latin-1
3
+ """
4
+ Created on Mar 25, 2014
5
+
6
+ @author: airen
7
+ @author: roberto.marabini
8
+ """
9
+ import datetime
10
+ import os
11
+ from subprocess import Popen
12
+ from io import StringIO
13
+
14
+ from pyworkflow import APPS, Variable
15
+ from pyworkflow.utils.process import killWithChilds
16
+ from pyworkflow.tests import *
17
+ from pyworkflow.utils import utils, prettyDict, getListFromValues, strToDuration
18
+ from pyworkflow.utils import ProgressBar
19
+
20
+
21
+ class TestBibtex(BaseTest):
22
+ """ Some minor tests to the bibtexparser library. """
23
+
24
+ @classmethod
25
+ def setUpClass(cls):
26
+ setupTestOutput(cls)
27
+
28
+ def test_Parsing(self):
29
+ bibtex = """
30
+
31
+ @article{delaRosaTrevin2013,
32
+ title = "Xmipp 3.0: An improved software suite for image processing in electron microscopy ",
33
+ journal = "Journal of Structural Biology ",
34
+ volume = "184",
35
+ number = "2",
36
+ pages = "321 - 328",
37
+ year = "2013",
38
+ issn = "1047-8477",
39
+ doi = "http://dx.doi.org/10.1016/j.jsb.2013.09.015",
40
+ url = "http://www.sciencedirect.com/science/article/pii/S1047847713002566",
41
+ author = "J.M. de la Rosa-Trevín and J. Otón and R. Marabini and A. Zaldívar and J. Vargas and J.M. Carazo and C.O.S. Sorzano",
42
+ keywords = "Electron microscopy, Single particles analysis, Image processing, Software package "
43
+ }
44
+
45
+ @incollection{Sorzano2013,
46
+ title = "Semiautomatic, High-Throughput, High-Resolution Protocol for Three-Dimensional Reconstruction of Single Particles in Electron Microscopy",
47
+ booktitle = "Nanoimaging",
48
+ year = "2013",
49
+ isbn = "978-1-62703-136-3",
50
+ volume = "950",
51
+ series = "Methods in Molecular Biology",
52
+ editor = "Sousa, Alioscka A. and Kruhlak, Michael J.",
53
+ doi = "10.1007/978-1-62703-137-0_11",
54
+ url = "http://dx.doi.org/10.1007/978-1-62703-137-0_11",
55
+ publisher = "Humana Press",
56
+ keywords = "Single particle analysis; Electron microscopy; Image processing; 3D reconstruction; Workflows",
57
+ author = "Sorzano, CarlosOscar and Rosa Trevín, J.M. and Otón, J. and Vega, J.J. and Cuenca, J. and Zaldívar-Peraza, A. and Gómez-Blanco, J. and Vargas, J. and Quintana, A. and Marabini, Roberto and Carazo, JoséMaría",
58
+ pages = "171-193",
59
+ }
60
+ """
61
+
62
+ prettyDict(utils.parseBibTex(bibtex))
63
+
64
+
65
+ class TestProccess(BaseTest):
66
+ """ Some tests for utils.process module. """
67
+
68
+ @classmethod
69
+ def setUpClass(cls):
70
+ setupTestOutput(cls)
71
+
72
+ def test_Process(self):
73
+ prog = pw.join(APPS, 'pw_sleep.py')
74
+ p = Popen('python %s 500' % prog, shell=True)
75
+ print("pid: %s" % p.pid)
76
+ time.sleep(5)
77
+ killWithChilds(p.pid)
78
+
79
+
80
+ class TestGetListFromRangeString(BaseTest):
81
+
82
+ def test_getListFromRangeString(self):
83
+ inputStrings = ["1,5-8,10" , "2,6,9-11" , "2 5, 6-8" , "1-4 8"]
84
+ outputLists = [[1, 5, 6, 7, 8, 10], [2, 6, 9, 10, 11], [2, 5, 6, 7, 8], [1,2,3,4, 8]]
85
+
86
+ for s, o in zip(inputStrings, outputLists):
87
+ self.assertEqual(o, pwutils.getListFromRangeString(s))
88
+ # Check that also works properly with spaces as delimiters
89
+ s2 = s.replace(',', ' ')
90
+ self.assertEqual(o, pwutils.getListFromRangeString(s2))
91
+
92
+
93
+ class TestListFromValues(unittest.TestCase):
94
+ """ Tests list created from str"""
95
+
96
+ def _callAndAssert(self, strValue, expected, length=None, caster=str):
97
+
98
+ result = getListFromValues( strValue, length, caster)
99
+
100
+ self.assertEqual(result, expected, "List from string does not work for %s" % strValue)
101
+
102
+ def test_getListFromValues(self):
103
+ """ Test numeric list definitions like:
104
+ '1 1 2x2 4 4' -> ['1', '1', '2', '2', '4', '4']
105
+ '2x3, 3x4, 1' -> ['3', '3', '4', '4', '4', '1']"
106
+ """
107
+
108
+ self._callAndAssert('1 1 2x2 4 4', ['1', '1', '2x2', '4', '4'])
109
+ self._callAndAssert('1 1 2x2 4 4', [1, 1, 2, 2, 4, 4], caster=int)
110
+ self._callAndAssert('2,3,4,1', [2, 3, 4, 1], caster=int)
111
+ self._callAndAssert('2 , 3 , 4 , 1', [2, 3, 4, 1], caster=int)
112
+ self._callAndAssert('2,3.3,4', [2.0, 3.3, 4.0], caster=float)
113
+
114
+
115
+
116
+ class TestProgressBar(unittest.TestCase):
117
+
118
+ def caller(self, total, step, fmt, resultGold):
119
+ ti = time.time()
120
+ result = StringIO()
121
+ pb = ProgressBar(total=total, fmt=fmt, output=result,
122
+ extraArgs={'objectId': 33})
123
+
124
+ pb.start()
125
+ for i in range(total):
126
+ if i % step == 0:
127
+ pb.update(i+1)
128
+ pb.finish()
129
+ self.assertEqual(resultGold.strip(), result.getvalue().strip())
130
+ result.close()
131
+ tf = time.time()
132
+ print("%d iterations in %f sec" % (total, tf - ti))
133
+
134
+ def test_dot(self):
135
+ total = 1000000
136
+ step = 10000
137
+ ratio = int(total/step)
138
+ resultGold = '.' * (ratio+1)
139
+ self.caller(total=total, step=step,
140
+ fmt=ProgressBar.DOT, resultGold=resultGold)
141
+
142
+ def test_default(self):
143
+ total = 3
144
+ step = 1
145
+ resultGold = ('\rProgress: [ ] '
146
+ ' 0%\rProgress: [============= '
147
+ ' ] 33%\rProgress: [========================== '
148
+ ' ] 66%\rProgress: [=============================='
149
+ '==========] 100%')
150
+ self.caller(total=total, step=step,
151
+ fmt=ProgressBar.DEFAULT, resultGold=resultGold)
152
+
153
+ def test_full(self):
154
+ total = 3
155
+ step = 1
156
+ resultGold = ('\r[ ] 0/3 ( 0%)'
157
+ ' 3 to go\r[============= ] '
158
+ '1/3 ( 33%) 2 to go\r[========================== '
159
+ ' ] 2/3 ( 66%) 1 to go\r[======================'
160
+ '==================] 3/3 (100%) 0 to go')
161
+ self.caller(total=total, step=step,
162
+ fmt=ProgressBar.FULL, resultGold=resultGold)
163
+
164
+ def test_objectid(self):
165
+ total = 3
166
+ step = 1
167
+ ratio = int(total/step)
168
+ resultGold = ('\r[ ] 0/3 ( 0%)'
169
+ ' (objectId=33)\r[============= '
170
+ ' ] 1/3 ( 33%) (objectId=33)\r[========================'
171
+ '== ] 2/3 ( 66%) (objectId=33)\r[=========='
172
+ '==============================] 3/3 (100%) '
173
+ '(objectId=33)')
174
+ self.caller(total=total, step=step,
175
+ fmt=ProgressBar.OBJID, resultGold=resultGold)
176
+
177
+
178
+
179
+ class TestPathTools(unittest.TestCase):
180
+
181
+ def test_filemodificationtime(self):
182
+
183
+ # Test is file closed
184
+
185
+ import tempfile
186
+ import time
187
+
188
+ since = datetime.datetime.now()
189
+ time.sleep(1)
190
+
191
+ tmpFile = tempfile.NamedTemporaryFile()
192
+ self.assertFalse(pwutils.isFileFinished(tmpFile.name), "File is NOT finished")
193
+ time.sleep(1)
194
+
195
+ self.assertTrue(pwutils.isFileFinished(tmpFile.name, duration=0.5), "File is finished after 2 seconds")
196
+
197
+
198
+ self.assertTrue(pwutils.hasChangedSince(tmpFile.name, since ), "hasChanged should have returned true. False negative.")
199
+ since = datetime.datetime.now()
200
+ self.assertFalse(pwutils.hasChangedSince(tmpFile.name, since ), "hasChanged should have returned false. False positive.")
201
+
202
+
203
+
204
+ def test_durationstrings(self):
205
+
206
+ self.assertEqual(70, strToDuration("1m 10s"), "String duration wrongly converted")
207
+
208
+
209
+
210
+