scipion-pyworkflow 3.10.6__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 (123) hide show
  1. pyworkflow/config.py +131 -67
  2. pyworkflow/constants.py +2 -1
  3. pyworkflow/plugin.py +93 -44
  4. pyworkflow/resources/showj/arrowDown.png +0 -0
  5. pyworkflow/resources/showj/arrowUp.png +0 -0
  6. pyworkflow/resources/showj/background_section.png +0 -0
  7. pyworkflow/resources/showj/colRowModeOff.png +0 -0
  8. pyworkflow/resources/showj/colRowModeOn.png +0 -0
  9. pyworkflow/resources/showj/delete.png +0 -0
  10. pyworkflow/resources/showj/doc_icon.png +0 -0
  11. pyworkflow/resources/showj/download_icon.png +0 -0
  12. pyworkflow/resources/showj/enabled_gallery.png +0 -0
  13. pyworkflow/resources/showj/galleryViewOff.png +0 -0
  14. pyworkflow/resources/showj/galleryViewOn.png +0 -0
  15. pyworkflow/resources/showj/goto.png +0 -0
  16. pyworkflow/resources/showj/menu.png +0 -0
  17. pyworkflow/resources/showj/separator.png +0 -0
  18. pyworkflow/resources/showj/tableViewOff.png +0 -0
  19. pyworkflow/resources/showj/tableViewOn.png +0 -0
  20. pyworkflow/resources/showj/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  21. pyworkflow/resources/showj/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  22. pyworkflow/resources/showj/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  23. pyworkflow/resources/showj/volumeOff.png +0 -0
  24. pyworkflow/resources/showj/volumeOn.png +0 -0
  25. pyworkflow/viewer.py +23 -1
  26. pyworkflowtests/protocols.py +1 -3
  27. {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.0.dist-info}/METADATA +13 -27
  28. scipion_pyworkflow-3.11.0.dist-info/RECORD +71 -0
  29. {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.0.dist-info}/WHEEL +1 -1
  30. pyworkflow/apps/__init__.py +0 -29
  31. pyworkflow/apps/pw_manager.py +0 -37
  32. pyworkflow/apps/pw_plot.py +0 -51
  33. pyworkflow/apps/pw_project.py +0 -113
  34. pyworkflow/apps/pw_protocol_list.py +0 -143
  35. pyworkflow/apps/pw_protocol_run.py +0 -51
  36. pyworkflow/apps/pw_run_tests.py +0 -267
  37. pyworkflow/apps/pw_schedule_run.py +0 -322
  38. pyworkflow/apps/pw_sleep.py +0 -37
  39. pyworkflow/apps/pw_sync_data.py +0 -439
  40. pyworkflow/apps/pw_viewer.py +0 -78
  41. pyworkflow/gui/__init__.py +0 -36
  42. pyworkflow/gui/browser.py +0 -726
  43. pyworkflow/gui/canvas.py +0 -1190
  44. pyworkflow/gui/dialog.py +0 -977
  45. pyworkflow/gui/form.py +0 -2637
  46. pyworkflow/gui/graph.py +0 -247
  47. pyworkflow/gui/graph_layout.py +0 -271
  48. pyworkflow/gui/gui.py +0 -566
  49. pyworkflow/gui/matplotlib_image.py +0 -233
  50. pyworkflow/gui/plotter.py +0 -247
  51. pyworkflow/gui/project/__init__.py +0 -25
  52. pyworkflow/gui/project/base.py +0 -192
  53. pyworkflow/gui/project/constants.py +0 -139
  54. pyworkflow/gui/project/labels.py +0 -205
  55. pyworkflow/gui/project/project.py +0 -492
  56. pyworkflow/gui/project/searchprotocol.py +0 -154
  57. pyworkflow/gui/project/searchrun.py +0 -181
  58. pyworkflow/gui/project/steps.py +0 -171
  59. pyworkflow/gui/project/utils.py +0 -332
  60. pyworkflow/gui/project/variables.py +0 -179
  61. pyworkflow/gui/project/viewdata.py +0 -472
  62. pyworkflow/gui/project/viewprojects.py +0 -510
  63. pyworkflow/gui/project/viewprotocols.py +0 -2093
  64. pyworkflow/gui/project/viewprotocols_extra.py +0 -559
  65. pyworkflow/gui/text.py +0 -771
  66. pyworkflow/gui/tooltip.py +0 -185
  67. pyworkflow/gui/tree.py +0 -684
  68. pyworkflow/gui/widgets.py +0 -307
  69. pyworkflow/mapper/__init__.py +0 -26
  70. pyworkflow/mapper/mapper.py +0 -222
  71. pyworkflow/mapper/sqlite.py +0 -1581
  72. pyworkflow/mapper/sqlite_db.py +0 -145
  73. pyworkflow/project/__init__.py +0 -31
  74. pyworkflow/project/config.py +0 -454
  75. pyworkflow/project/manager.py +0 -180
  76. pyworkflow/project/project.py +0 -2007
  77. pyworkflow/protocol/__init__.py +0 -38
  78. pyworkflow/protocol/bibtex.py +0 -48
  79. pyworkflow/protocol/constants.py +0 -87
  80. pyworkflow/protocol/executor.py +0 -471
  81. pyworkflow/protocol/hosts.py +0 -314
  82. pyworkflow/protocol/launch.py +0 -270
  83. pyworkflow/protocol/package.py +0 -42
  84. pyworkflow/protocol/params.py +0 -741
  85. pyworkflow/protocol/protocol.py +0 -2641
  86. pyworkflow/tests/__init__.py +0 -29
  87. pyworkflow/tests/test_utils.py +0 -25
  88. pyworkflow/tests/tests.py +0 -341
  89. pyworkflow/utils/__init__.py +0 -38
  90. pyworkflow/utils/dataset.py +0 -414
  91. pyworkflow/utils/echo.py +0 -104
  92. pyworkflow/utils/graph.py +0 -169
  93. pyworkflow/utils/log.py +0 -284
  94. pyworkflow/utils/path.py +0 -528
  95. pyworkflow/utils/process.py +0 -153
  96. pyworkflow/utils/profiler.py +0 -92
  97. pyworkflow/utils/progressbar.py +0 -154
  98. pyworkflow/utils/properties.py +0 -631
  99. pyworkflow/utils/reflection.py +0 -129
  100. pyworkflow/utils/utils.py +0 -879
  101. pyworkflow/utils/which.py +0 -229
  102. pyworkflow/webservices/__init__.py +0 -8
  103. pyworkflow/webservices/config.py +0 -11
  104. pyworkflow/webservices/notifier.py +0 -162
  105. pyworkflow/webservices/repository.py +0 -59
  106. pyworkflow/webservices/workflowhub.py +0 -74
  107. pyworkflowtests/tests/__init__.py +0 -0
  108. pyworkflowtests/tests/test_canvas.py +0 -72
  109. pyworkflowtests/tests/test_domain.py +0 -45
  110. pyworkflowtests/tests/test_logs.py +0 -74
  111. pyworkflowtests/tests/test_mappers.py +0 -392
  112. pyworkflowtests/tests/test_object.py +0 -507
  113. pyworkflowtests/tests/test_project.py +0 -42
  114. pyworkflowtests/tests/test_protocol_execution.py +0 -142
  115. pyworkflowtests/tests/test_protocol_export.py +0 -78
  116. pyworkflowtests/tests/test_protocol_output.py +0 -158
  117. pyworkflowtests/tests/test_streaming.py +0 -47
  118. pyworkflowtests/tests/test_utils.py +0 -210
  119. scipion_pyworkflow-3.10.6.dist-info/RECORD +0 -140
  120. scipion_pyworkflow-3.10.6.dist-info/dependency_links.txt +0 -1
  121. {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.0.dist-info}/entry_points.txt +0 -0
  122. {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.0.dist-info}/licenses/LICENSE.txt +0 -0
  123. {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.0.dist-info}/top_level.txt +0 -0
@@ -1,74 +0,0 @@
1
- #!/usr/bin/env python
2
-
3
- import logging
4
- import unittest
5
-
6
- from pyworkflow import Config
7
- from pyworkflow.utils import (getLineInFile,
8
- LoggingConfigurator, restoreStdoutAndErr)
9
- from pyworkflow.tests import BaseTest, setupTestOutput
10
- from pyworkflow.utils.process import runJob
11
-
12
-
13
- class TestLogs(BaseTest):
14
-
15
- @classmethod
16
- def setUpClass(cls):
17
- setupTestOutput(cls)
18
-
19
- def testSimpleFileLog(self):
20
-
21
- # Default generic configuration
22
- Config.SCIPION_LOG = self.getOutputPath("general.log")
23
- genLogFn = Config.SCIPION_LOG
24
- print("General log file at %s" % genLogFn)
25
- LoggingConfigurator.setupLogging()
26
- log1 = logging.getLogger('pyworkflow.test.log.test_scipion_log')
27
-
28
- def testMessage(message, msg_callback, file, shouldExist):
29
-
30
- if msg_callback:
31
- msg_callback(message)
32
-
33
- self.assertEqual(shouldExist, bool(getLineInFile(message, file)))
34
-
35
- testMessage("INFO to GEN", log1.info, genLogFn, True)
36
- testMessage("DEBUG missing in GEN", log1.debug, genLogFn, False)
37
- testMessage("WARNING in GEN", log1.warning, genLogFn, True)
38
- testMessage("ERROR in GEN", log1.error, genLogFn, True)
39
-
40
- # Protocol run logging configuration (this is propagating the messages,
41
- # so messages end un in general log too). This is to allow custom configurations to receive running protocol messages)
42
- logFn = self.getOutputPath('stdout.log')
43
- logErrFn = self.getOutputPath('stdErr.log')
44
- log2 = LoggingConfigurator.setUpProtocolRunLogging(logFn, logErrFn)
45
-
46
- fileInfoTest = 'INFO to FILE'
47
- testMessage(fileInfoTest, log2.info, logFn, True)
48
- testMessage(fileInfoTest, None, genLogFn, False)
49
-
50
- fileDebugMsg = "DEBUG does not reach FILE nor GEN"
51
- testMessage(fileDebugMsg, log2.debug, logFn, False)
52
- testMessage(fileDebugMsg, None, genLogFn, False)
53
-
54
- fileWarningTest = 'WARNING to FILE and not GEN'
55
- testMessage(fileWarningTest, log2.warning, logFn, True)
56
- testMessage(fileWarningTest, None, genLogFn, False)
57
-
58
- fileErrorTest = 'ERROR to FILE and not GEN'
59
- testMessage(fileErrorTest, log2.error, logErrFn, True)
60
- testMessage(fileErrorTest, None, genLogFn, False)
61
-
62
- # Test print goes to the log file (stdout is captured)
63
- printStdOut = "Print ends up in stdout FILE"
64
- print(printStdOut, flush=True)
65
- testMessage(printStdOut,None, logFn, True)
66
-
67
- subprocessOut = "subprocess output in stdout FILE"
68
- runJob(None,"echo", subprocessOut)
69
- testMessage(subprocessOut,None, logFn, True)
70
-
71
- restoreStdoutAndErr()
72
-
73
- if __name__ == '__main__':
74
- unittest.main()
@@ -1,392 +0,0 @@
1
- #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
- # **************************************************************************
4
- # *
5
- # * Authors: J.M. De la Rosa Trevin (delarosatrevin@scilifelab.se) [1]
6
- # *
7
- # * [1] 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, see <https://www.gnu.org/licenses/>.
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
-
28
- import pyworkflow as pw
29
- import pyworkflow.object as pwobj
30
- import pyworkflow.tests as pwtests
31
- import pyworkflow.mapper as pwmapper
32
- from pyworkflow.mapper.sqlite import ID
33
- from pyworkflowtests.objects import Complex, MockImage
34
- import pyworkflowtests
35
-
36
- IMAGES_STK = 'images.stk'
37
-
38
-
39
- class TestSqliteMapper(pwtests.BaseTest):
40
- @classmethod
41
- def setUpClass(cls):
42
- pwtests.setupTestOutput(cls)
43
-
44
- def test_SqliteMapper(self):
45
- fn = self.getOutputPath("basic.sqlite")
46
- mapper = pwmapper.SqliteMapper(fn)
47
-
48
- # Insert a Float
49
- f = pwobj.Float(5.4)
50
- mapper.insert(f)
51
-
52
- # Insert an pwobj.Integer
53
- i = pwobj.Integer(1)
54
- mapper.insert(i)
55
-
56
- # Insert two pwobj.Boolean
57
- b = pwobj.Boolean(False)
58
- b2 = pwobj.Boolean(True)
59
- mapper.insert(b)
60
- mapper.insert(b2)
61
-
62
- # Test storing pointers
63
- p = pwobj.Pointer(b)
64
- mapper.insert(p)
65
-
66
- # Store csv list
67
- strList = ['1', '2', '3']
68
- csv = pwobj.CsvList()
69
- csv += strList
70
- mapper.insert(csv)
71
-
72
- # Test normal List
73
- iList = pwobj.List()
74
- mapper.insert(iList) # Insert the list when empty
75
- i1 = pwobj.Integer(4)
76
- i2 = pwobj.Integer(3)
77
- iList.append(i1)
78
- iList.append(i2)
79
- mapper.update(iList) # now update with some items inside
80
-
81
- pList = pwobj.PointerList()
82
- p1 = pwobj.Pointer(b)
83
- # p1.set(b)
84
- p2 = pwobj.Pointer(b2)
85
- # p2.set(b2)
86
- pList.append(p1)
87
- pList.append(p2)
88
- mapper.store(pList)
89
-
90
- # Test to add relations
91
- relName = 'testRelation'
92
- creator = f
93
- mapper.insertRelation(relName, creator, i, b)
94
- mapper.insertRelation(relName, creator, i, b2)
95
-
96
- mapper.insertRelation(relName, creator, b, p)
97
- mapper.insertRelation(relName, creator, b2, p)
98
-
99
- # Save changes to file
100
- mapper.commit()
101
- self.assertEqual(1, mapper.db.getVersion())
102
- mapper.close()
103
-
104
- # Test using SqliteDb class
105
- db = pwmapper.SqliteDb()
106
- db._createConnection(fn, timeout=1000)
107
- tables = ['Objects', 'Relations']
108
- self.assertEqual(tables, db.getTables())
109
- # Test getting the version, for the gold file it should be 0
110
- self.assertEqual(1, db.getVersion())
111
- db.close()
112
-
113
- # Reading test
114
- mapper2 = pwmapper.SqliteMapper(fn, pw.Config.getDomain().getMapperDict())
115
- print("Checking that Relations table is updated and version to 1")
116
- self.assertEqual(1, mapper2.db.getVersion())
117
- # Check that the new column is properly added after updated to version 1
118
- colNamesGold = [u'id', u'parent_id', u'name', u'classname',
119
- u'value', u'label', u'comment', u'object_parent_id',
120
- u'object_child_id', u'creation',
121
- u'object_parent_extended', u'object_child_extended']
122
- colNames = [col[1] for col in mapper2.db.getTableColumns('Relations')]
123
- self.assertEqual(colNamesGold, colNames)
124
-
125
- l = mapper2.selectByClass('Integer')[0]
126
- self.assertEqual(l.get(), 1)
127
-
128
- f2 = mapper2.selectByClass('Float')[0]
129
- self.assertEqual(f, f2.get())
130
-
131
- b = mapper2.selectByClass('Boolean')[0]
132
- self.assertTrue(not b.get())
133
-
134
- p = mapper2.selectByClass('Pointer')[0]
135
- self.assertEqual(b.get(), p.get())
136
-
137
- csv2 = mapper2.selectByClass('CsvList')[0]
138
- self.assertTrue(list.__eq__(csv2, strList))
139
-
140
- # Iterate over all objects
141
- allObj = mapper2.selectAll()
142
- iterAllObj = mapper2.selectAll(iterate=True)
143
-
144
- for a1, a2 in zip(allObj, iterAllObj):
145
- # Note compare the scalar objects, which have a well-defined comparison
146
- if isinstance(a1, pwobj.Scalar):
147
- self.assertEqual(a1, a2)
148
-
149
- # Test select all batch approach
150
- allBatch = mapper2.selectAllBatch()
151
-
152
- # Test relations
153
- childs = mapper2.getRelationChilds(relName, i)
154
- parents = mapper2.getRelationParents(relName, p)
155
- # In this case both childs and parent should be the same
156
- for c, p in zip(childs, parents):
157
- self.assertEqual(c, p,
158
- "Childs of object i, should be the parents of object p")
159
-
160
- relations = mapper2.getRelationsByCreator(creator)
161
- for row in relations:
162
- print(dict(row))
163
-
164
- def test_StorePointers(self):
165
- """ Check that pointers are correctly stored. """
166
- fn = self.getOutputPath("pointers.sqlite")
167
-
168
- print(">>> Using db: ", fn)
169
-
170
- mapper = pwmapper.SqliteMapper(fn)
171
- # Insert a Complex
172
- c = Complex.createComplex() # real = 1, imag = 1
173
- mapper.insert(c)
174
- # Insert an pwobj.Integer
175
- p1 = pwobj.Pointer(c)
176
- p1.setExtended('real')
177
-
178
- mapper.store(c)
179
- mapper.store(p1)
180
-
181
- self.assertAlmostEqual(c.real.get(), p1.get().get())
182
-
183
- p1.set(None) # Reset value and check that is stored properly
184
-
185
- self.assertIsNone(p1._extended.get())
186
- mapper.store(p1)
187
- mapper.commit()
188
-
189
- mapper2 = pwmapper.SqliteMapper(fn, pw.Config.getDomain().getMapperDict())
190
- p2 = mapper2.selectByClass('Pointer')[0]
191
-
192
- # Check the mapper was properly stored when
193
- # set to None and the _extended property cleaned
194
- self.assertIsNone(p2.get())
195
-
196
- def test_removeFromLists(self):
197
- """ Check that lists are properly stored after removing some elements.
198
- """
199
- fn = self.getOutputPath("lists.sqlite")
200
-
201
- print(">>> Using db: ", fn)
202
-
203
- # Let's create a Mapper to store a simple List containing two integers
204
- mapper = pwmapper.SqliteMapper(fn, pw.Config.getDomain().getMapperDict())
205
- iList = pwobj.List()
206
- i1 = pwobj.Integer(4)
207
- i2 = pwobj.Integer(3)
208
- iList.append(i1)
209
- iList.append(i2)
210
- # Store the list and commit changes to db, then close db.
211
- mapper.store(iList)
212
- mapper.commit()
213
- mapper.close()
214
-
215
- # Now let's open again the db with a different connection
216
- # and load the previously stored list
217
- mapper2 = pwmapper.SqliteMapper(fn, pw.Config.getDomain().getMapperDict())
218
- iList2 = mapper2.selectByClass('List')[0]
219
- # Let's do some basic checks
220
- self.assertEqual(iList2.getSize(), 2)
221
- self.assertTrue(pwobj.Integer(4) in iList2)
222
- self.assertTrue(pwobj.Integer(3) in iList2)
223
-
224
- # Now remove one of the integers in the list
225
- # check consistency in the list elements
226
- iList2.remove(pwobj.Integer(4))
227
- self.assertEqual(iList2.getSize(), 1)
228
- self.assertTrue(pwobj.Integer(4) not in iList2)
229
- self.assertTrue(pwobj.Integer(3) in iList2)
230
- # Store once again the new list with one element
231
- mapper2.store(iList2)
232
- mapper2.commit()
233
- mapper2.close()
234
-
235
- # Open the db and load the list once again
236
- mapper3 = pwmapper.SqliteMapper(fn, pw.Config.getDomain().getMapperDict())
237
- iList3 = mapper3.selectByClass('List')[0]
238
- # Check the same consistency before it was stored
239
- self.assertEqual(iList3.getSize(), 1)
240
- self.assertTrue(pwobj.Integer(4) not in iList3)
241
- self.assertTrue(pwobj.Integer(3) in iList3)
242
-
243
-
244
- class TestSqliteFlatMapper(pwtests.BaseTest):
245
- """ Some tests for DataSet implementation. """
246
- _labels = [pwtests.SMALL]
247
-
248
- @classmethod
249
- def setUpClass(cls):
250
- pwtests.setupTestOutput(cls)
251
-
252
- # This isSet the application domain
253
- pyworkflowtests.Domain = pyworkflowtests.TestDomain
254
- pw.Config.setDomain("pyworkflowtests")
255
-
256
- # TODO: Maybe some mapper test for backward compatibility can be
257
- def test_insertObjects(self):
258
- dbName = self.getOutputPath('images.sqlite')
259
- print(">>> test_insertObjects: dbName = '%s'" % dbName)
260
- mapper = pwmapper.SqliteFlatMapper(dbName, pw.Config.getDomain().getMapperDict())
261
- self.assertEqual(0, mapper.count())
262
- self.assertEqual(0, mapper.maxId())
263
- n = 10
264
-
265
- indexes = list(range(1, n + 1))
266
- for i in indexes:
267
- img = MockImage()
268
- img.setLocation(i, IMAGES_STK)
269
- img.setSamplingRate(i%2)
270
- mapper.insert(img)
271
-
272
- self.assertEqual(n, mapper.count())
273
- self.assertEqual(n, mapper.maxId())
274
-
275
- # Store one more image with bigger id
276
- img = MockImage()
277
- bigId = 1000
278
- img.setLocation(i + 1, IMAGES_STK)
279
- img.setObjId(bigId)
280
- mapper.insert(img)
281
- self.assertEqual(bigId, mapper.maxId())
282
-
283
- # Insert another image with None as id, it should take bigId + 1
284
- img.setLocation(i + 2, IMAGES_STK)
285
- img.setObjId(None)
286
- mapper.insert(img)
287
- self.assertEqual(bigId + 1, mapper.maxId())
288
-
289
- mapper.setProperty('samplingRate', '3.0')
290
- mapper.setProperty('defocusU', 1000)
291
- mapper.setProperty('defocusV', 1000)
292
- mapper.setProperty('defocusU', 2000) # Test update a property value
293
- mapper.deleteProperty('defocusV') # Test delete a property
294
- mapper.commit()
295
- self.assertEqual(1, mapper.db.getVersion())
296
-
297
- # Test where parsing
298
- self.assertIsNone(mapper.db._whereToWhereStr(None), "A where = None does not return None")
299
- self.assertEqual(mapper.db._whereToWhereStr("missing1=missing2"), "missing1=missing2", "a where with missing fields does not work")
300
- self.assertEqual(mapper.db._whereToWhereStr("_samplingRate=value2"), "c03=value2", "simple = where does not work")
301
- self.assertEqual(mapper.db._whereToWhereStr("_samplingRate=_samplingRate"), "c03=c03", "simple = where with 2 fields does not work")
302
- self.assertEqual(mapper.db._whereToWhereStr("_samplingRate = _samplingRate"), "c03 = c03", "simple = spaced where with 2 fields does not work")
303
- self.assertEqual(mapper.db._whereToWhereStr("_samplingRate < 3"), "c03 < 3", "a where with < does not work")
304
- self.assertEqual(mapper.db._whereToWhereStr("_samplingRate >= 4"), "c03 >= 4", "a where with >= does not work")
305
- self.assertEqual(mapper.db._whereToWhereStr("5 <= _samplingRate"), "5 <= c03", "a where with <= does not work")
306
- self.assertEqual(mapper.db._whereToWhereStr("5 <= _samplingRate OR 3=_index"), "5 <= c03 OR 3=c01", "a where with OR does not work")
307
-
308
- # Tests actual where used in queries
309
- self.assertEqual(len(mapper.unique(ID, "_index = 1 OR _index = 2")), 2, "unique with OR in where does not work.")
310
- self.assertEqual(len(mapper.unique(ID, ID + " >= 20 ")), 2, "unique >= in where does not work.")
311
- mapper.close()
312
-
313
- # Test that values were stored properly
314
- mapper2 = pwmapper.SqliteFlatMapper(dbName, pw.Config.getDomain().getMapperDict())
315
- indexes.extend([bigId, bigId + 1])
316
- for i, obj in enumerate(mapper2.selectAll(iterate=True)):
317
- self.assertEqual(obj.getIndex(), i + 1)
318
- self.assertEqual(obj.getObjId(), indexes[i])
319
-
320
- self.assertTrue(mapper2.hasProperty('samplingRate'))
321
- self.assertTrue(mapper2.hasProperty('defocusU'))
322
- self.assertFalse(mapper2.hasProperty('defocusV'))
323
-
324
- self.assertEqual(mapper2.getProperty('samplingRate'), '3.0')
325
- self.assertEqual(mapper2.getProperty('defocusU'), '2000')
326
-
327
- # Make sure that maxId() returns the proper value after loading db
328
- self.assertEqual(bigId + 1, mapper2.maxId())
329
-
330
- # test aggregation
331
- result = mapper2.aggregate("COUNT", "id") # As strings
332
- self.assertEqual(result[0]["COUNT"], 12, "Aggregation fo count does not work")
333
-
334
- result = mapper2.aggregate(["COUNT"], ["id"]) # As lists
335
- self.assertEqual(result[0]["COUNT"], 12, "Aggregation as list of count does not work")
336
-
337
- result = mapper2.aggregate(["MAX","AVG"], "id")
338
- self.assertEqual(result[0]["MAX"], bigId+1, "Aggregation max, avg does not work")
339
- self.assertAlmostEqual(result[0]["AVG"], 171.33, places=2, msg="Aggregation max, avg does not work")
340
-
341
- result = mapper2.aggregate(["MAX", "COUNT"], "_samplingRate", "id")
342
- self.assertEqual(result[0]["MAX"], 1, "Aggregation max, grouped does not work")
343
- self.assertEqual(result[0]["COUNT"], 1, "Aggregation max, count does not work")
344
- self.assertEqual(result[0]["id"], 1, "Aggregation group field not returned")
345
-
346
- # Aggregation on more than one field
347
- result = mapper2.aggregate(["MAX"], ["id","_samplingRate"])
348
- self.assertEqual(result[0]["MAX"], 1001, "Aggregation max, grouped does not work")
349
- self.assertEqual(result[0]["MAX_samplingRate"], 1.0, "Aggregation max, count does not work")
350
-
351
- def test_emtpySet(self):
352
- dbName = self.getOutputPath('empty.sqlite')
353
- print(">>> test empty set: dbName = '%s'" % dbName)
354
- # Check that writing an emtpy set do not fail
355
- objSet = pwobj.Set(filename=dbName)
356
- objSet.write()
357
- objSet.close()
358
- # Now let's try to open an empty set
359
- objSet = pwobj.Set(filename=dbName)
360
- self.assertEqual(objSet.getSize(), 0)
361
- items = [obj.clone() for obj in objSet]
362
- self.assertEqual(len(items), 0)
363
-
364
-
365
- class TestDataSet(pwtests.BaseTest):
366
- """ Some tests for DataSet implementation. """
367
-
368
- @classmethod
369
- def setUpClass(cls):
370
- pwtests.setupTestOutput(cls)
371
-
372
- def test_Table(self):
373
- from pyworkflow.utils.dataset import Table, Column
374
- table = Table(Column('x', int, 5),
375
- Column('y', float, 0.0),
376
- Column('name', str))
377
-
378
- # Add a row to the table
379
- table.addRow(1, x=12, y=11.0, name='jose')
380
- table.addRow(2, x=22, y=21.0, name='juan')
381
- table.addRow(3, x=32, y=31.0, name='pedro')
382
- # Expect an exception, since name is not provided and have not default
383
- self.assertRaises(Exception, table.addRow, 100, y=3.0)
384
- row = table.getRow(1)
385
- print(row)
386
- self.assertEqual(table.getSize(), 3, "Bad table size")
387
-
388
- # Update a value of a row
389
- table.updateRow(1, name='pepe')
390
- row = table.getRow(1)
391
- print(row)
392
- self.assertEqual(row.name, 'pepe', "Error updating name in row")