datalab-platform 0.0.1.dev0__py3-none-any.whl → 1.0.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.
Files changed (496) hide show
  1. datalab/__init__.py +35 -2
  2. datalab/adapters_metadata/__init__.py +31 -0
  3. datalab/adapters_metadata/base_adapter.py +316 -0
  4. datalab/adapters_metadata/common.py +422 -0
  5. datalab/adapters_metadata/geometry_adapter.py +98 -0
  6. datalab/adapters_metadata/table_adapter.py +84 -0
  7. datalab/adapters_plotpy/__init__.py +54 -0
  8. datalab/adapters_plotpy/annotations.py +124 -0
  9. datalab/adapters_plotpy/base.py +110 -0
  10. datalab/adapters_plotpy/converters.py +86 -0
  11. datalab/adapters_plotpy/factories.py +80 -0
  12. datalab/adapters_plotpy/objects/__init__.py +0 -0
  13. datalab/adapters_plotpy/objects/base.py +197 -0
  14. datalab/adapters_plotpy/objects/image.py +157 -0
  15. datalab/adapters_plotpy/objects/scalar.py +565 -0
  16. datalab/adapters_plotpy/objects/signal.py +264 -0
  17. datalab/adapters_plotpy/roi/__init__.py +0 -0
  18. datalab/adapters_plotpy/roi/base.py +146 -0
  19. datalab/adapters_plotpy/roi/factory.py +93 -0
  20. datalab/adapters_plotpy/roi/image.py +207 -0
  21. datalab/adapters_plotpy/roi/signal.py +72 -0
  22. datalab/app.py +98 -0
  23. datalab/config.py +817 -0
  24. datalab/control/__init__.py +0 -0
  25. datalab/control/baseproxy.py +776 -0
  26. datalab/control/proxy.py +343 -0
  27. datalab/control/remote.py +1005 -0
  28. datalab/data/doc/DataLab_en.pdf +0 -0
  29. datalab/data/doc/DataLab_fr.pdf +0 -0
  30. datalab/data/icons/analysis/delete_results.svg +109 -0
  31. datalab/data/icons/analysis/fw1e2.svg +156 -0
  32. datalab/data/icons/analysis/fwhm.svg +156 -0
  33. datalab/data/icons/analysis/histogram.svg +49 -0
  34. datalab/data/icons/analysis/peak_detect.svg +160 -0
  35. datalab/data/icons/analysis/plot_results.svg +151 -0
  36. datalab/data/icons/analysis/show_results.svg +83 -0
  37. datalab/data/icons/analysis/stats.svg +49 -0
  38. datalab/data/icons/analysis.svg +120 -0
  39. datalab/data/icons/apply.svg +3 -0
  40. datalab/data/icons/check_all.svg +15 -0
  41. datalab/data/icons/collapse.svg +44 -0
  42. datalab/data/icons/collapse_selection.svg +63 -0
  43. datalab/data/icons/console.svg +101 -0
  44. datalab/data/icons/create/1d-normal.svg +8 -0
  45. datalab/data/icons/create/1d-poisson.svg +9 -0
  46. datalab/data/icons/create/1d-uniform.svg +8 -0
  47. datalab/data/icons/create/1d-zero.svg +57 -0
  48. datalab/data/icons/create/2d-gaussian.svg +56 -0
  49. datalab/data/icons/create/2d-normal.svg +38 -0
  50. datalab/data/icons/create/2d-poisson.svg +38 -0
  51. datalab/data/icons/create/2d-ramp.svg +90 -0
  52. datalab/data/icons/create/2d-sinc.svg +62 -0
  53. datalab/data/icons/create/2d-uniform.svg +38 -0
  54. datalab/data/icons/create/2d-zero.svg +13 -0
  55. datalab/data/icons/create/checkerboard.svg +39 -0
  56. datalab/data/icons/create/cosine.svg +12 -0
  57. datalab/data/icons/create/exponential.svg +55 -0
  58. datalab/data/icons/create/gaussian.svg +12 -0
  59. datalab/data/icons/create/grating.svg +29 -0
  60. datalab/data/icons/create/linear_chirp.svg +7 -0
  61. datalab/data/icons/create/logistic.svg +7 -0
  62. datalab/data/icons/create/lorentzian.svg +12 -0
  63. datalab/data/icons/create/planck.svg +12 -0
  64. datalab/data/icons/create/polynomial.svg +7 -0
  65. datalab/data/icons/create/pulse.svg +12 -0
  66. datalab/data/icons/create/ring.svg +18 -0
  67. datalab/data/icons/create/sawtooth.svg +7 -0
  68. datalab/data/icons/create/siemens.svg +35 -0
  69. datalab/data/icons/create/sinc.svg +12 -0
  70. datalab/data/icons/create/sine.svg +7 -0
  71. datalab/data/icons/create/square.svg +7 -0
  72. datalab/data/icons/create/square_pulse.svg +7 -0
  73. datalab/data/icons/create/step.svg +7 -0
  74. datalab/data/icons/create/step_pulse.svg +12 -0
  75. datalab/data/icons/create/triangle.svg +7 -0
  76. datalab/data/icons/create/voigt.svg +12 -0
  77. datalab/data/icons/edit/annotations.svg +72 -0
  78. datalab/data/icons/edit/annotations_copy.svg +114 -0
  79. datalab/data/icons/edit/annotations_delete.svg +83 -0
  80. datalab/data/icons/edit/annotations_edit.svg +98 -0
  81. datalab/data/icons/edit/annotations_export.svg +85 -0
  82. datalab/data/icons/edit/annotations_import.svg +85 -0
  83. datalab/data/icons/edit/annotations_paste.svg +100 -0
  84. datalab/data/icons/edit/copy_titles.svg +109 -0
  85. datalab/data/icons/edit/delete.svg +84 -0
  86. datalab/data/icons/edit/delete_all.svg +214 -0
  87. datalab/data/icons/edit/duplicate.svg +64 -0
  88. datalab/data/icons/edit/goto_source.svg +60 -0
  89. datalab/data/icons/edit/metadata.svg +60 -0
  90. datalab/data/icons/edit/metadata_add.svg +80 -0
  91. datalab/data/icons/edit/metadata_copy.svg +96 -0
  92. datalab/data/icons/edit/metadata_delete.svg +62 -0
  93. datalab/data/icons/edit/metadata_export.svg +68 -0
  94. datalab/data/icons/edit/metadata_import.svg +68 -0
  95. datalab/data/icons/edit/metadata_paste.svg +79 -0
  96. datalab/data/icons/edit/move_down.svg +55 -0
  97. datalab/data/icons/edit/move_up.svg +54 -0
  98. datalab/data/icons/edit/new_group.svg +76 -0
  99. datalab/data/icons/edit/recompute.svg +60 -0
  100. datalab/data/icons/edit/rename.svg +49 -0
  101. datalab/data/icons/edit.svg +16 -0
  102. datalab/data/icons/expand.svg +44 -0
  103. datalab/data/icons/expand_selection.svg +63 -0
  104. datalab/data/icons/fit/cdf_fit.svg +56 -0
  105. datalab/data/icons/fit/exponential_fit.svg +55 -0
  106. datalab/data/icons/fit/gaussian_fit.svg +62 -0
  107. datalab/data/icons/fit/interactive_fit.svg +101 -0
  108. datalab/data/icons/fit/linear_fit.svg +57 -0
  109. datalab/data/icons/fit/lorentzian_fit.svg +209 -0
  110. datalab/data/icons/fit/multigaussian_fit.svg +85 -0
  111. datalab/data/icons/fit/multilorentzian_fit.svg +85 -0
  112. datalab/data/icons/fit/piecewiseexponential_fit.svg +209 -0
  113. datalab/data/icons/fit/planckian_fit.svg +62 -0
  114. datalab/data/icons/fit/polynomial_fit.svg +59 -0
  115. datalab/data/icons/fit/sigmoid_fit.svg +56 -0
  116. datalab/data/icons/fit/sinusoidal_fit.svg +72 -0
  117. datalab/data/icons/fit/twohalfgaussian_fit.svg +63 -0
  118. datalab/data/icons/fit/voigt_fit.svg +57 -0
  119. datalab/data/icons/group.svg +56 -0
  120. datalab/data/icons/h5/h5array.svg +59 -0
  121. datalab/data/icons/h5/h5attrs.svg +75 -0
  122. datalab/data/icons/h5/h5browser.svg +133 -0
  123. datalab/data/icons/h5/h5file.svg +69 -0
  124. datalab/data/icons/h5/h5group.svg +49 -0
  125. datalab/data/icons/h5/h5scalar.svg +1 -0
  126. datalab/data/icons/help_pdf.svg +46 -0
  127. datalab/data/icons/history.svg +7 -0
  128. datalab/data/icons/image.svg +135 -0
  129. datalab/data/icons/io/fileopen_directory.svg +60 -0
  130. datalab/data/icons/io/fileopen_h5.svg +84 -0
  131. datalab/data/icons/io/fileopen_ima.svg +187 -0
  132. datalab/data/icons/io/fileopen_py.svg +123 -0
  133. datalab/data/icons/io/fileopen_sig.svg +138 -0
  134. datalab/data/icons/io/filesave_h5.svg +97 -0
  135. datalab/data/icons/io/filesave_ima.svg +200 -0
  136. datalab/data/icons/io/filesave_py.svg +136 -0
  137. datalab/data/icons/io/filesave_sig.svg +151 -0
  138. datalab/data/icons/io/import_text.svg +144 -0
  139. datalab/data/icons/io/save_to_directory.svg +134 -0
  140. datalab/data/icons/io.svg +84 -0
  141. datalab/data/icons/libre-camera-flash-off.svg +1 -0
  142. datalab/data/icons/libre-camera-flash-on.svg +1 -0
  143. datalab/data/icons/libre-gui-about.svg +1 -0
  144. datalab/data/icons/libre-gui-action-delete.svg +1 -0
  145. datalab/data/icons/libre-gui-add.svg +1 -0
  146. datalab/data/icons/libre-gui-arrow-down.svg +1 -0
  147. datalab/data/icons/libre-gui-arrow-left.svg +1 -0
  148. datalab/data/icons/libre-gui-arrow-right.svg +1 -0
  149. datalab/data/icons/libre-gui-arrow-up.svg +1 -0
  150. datalab/data/icons/libre-gui-close.svg +40 -0
  151. datalab/data/icons/libre-gui-cogs.svg +1 -0
  152. datalab/data/icons/libre-gui-globe.svg +1 -0
  153. datalab/data/icons/libre-gui-help.svg +1 -0
  154. datalab/data/icons/libre-gui-link.svg +1 -0
  155. datalab/data/icons/libre-gui-menu.svg +1 -0
  156. datalab/data/icons/libre-gui-pencil.svg +1 -0
  157. datalab/data/icons/libre-gui-plugin.svg +1 -0
  158. datalab/data/icons/libre-gui-questions.svg +1 -0
  159. datalab/data/icons/libre-gui-settings.svg +1 -0
  160. datalab/data/icons/libre-gui-unlink.svg +1 -0
  161. datalab/data/icons/libre-tech-ram.svg +1 -0
  162. datalab/data/icons/libre-toolbox.svg +1 -0
  163. datalab/data/icons/logs.svg +1 -0
  164. datalab/data/icons/markers.svg +74 -0
  165. datalab/data/icons/menu.svg +13 -0
  166. datalab/data/icons/new_ima.svg +148 -0
  167. datalab/data/icons/new_sig.svg +123 -0
  168. datalab/data/icons/operations/abs.svg +116 -0
  169. datalab/data/icons/operations/arithmetic.svg +123 -0
  170. datalab/data/icons/operations/average.svg +124 -0
  171. datalab/data/icons/operations/complex_from_magnitude_phase.svg +116 -0
  172. datalab/data/icons/operations/complex_from_real_imag.svg +124 -0
  173. datalab/data/icons/operations/constant.svg +116 -0
  174. datalab/data/icons/operations/constant_add.svg +109 -0
  175. datalab/data/icons/operations/constant_divide.svg +109 -0
  176. datalab/data/icons/operations/constant_multiply.svg +109 -0
  177. datalab/data/icons/operations/constant_subtract.svg +109 -0
  178. datalab/data/icons/operations/convert_dtype.svg +117 -0
  179. datalab/data/icons/operations/convolution.svg +46 -0
  180. datalab/data/icons/operations/deconvolution.svg +57 -0
  181. datalab/data/icons/operations/derivative.svg +127 -0
  182. datalab/data/icons/operations/difference.svg +52 -0
  183. datalab/data/icons/operations/division.svg +139 -0
  184. datalab/data/icons/operations/exp.svg +116 -0
  185. datalab/data/icons/operations/flip_horizontally.svg +69 -0
  186. datalab/data/icons/operations/flip_vertically.svg +74 -0
  187. datalab/data/icons/operations/im.svg +124 -0
  188. datalab/data/icons/operations/integral.svg +50 -0
  189. datalab/data/icons/operations/inverse.svg +143 -0
  190. datalab/data/icons/operations/log10.svg +109 -0
  191. datalab/data/icons/operations/phase.svg +116 -0
  192. datalab/data/icons/operations/power.svg +118 -0
  193. datalab/data/icons/operations/product.svg +124 -0
  194. datalab/data/icons/operations/profile.svg +379 -0
  195. datalab/data/icons/operations/profile_average.svg +399 -0
  196. datalab/data/icons/operations/profile_radial.svg +261 -0
  197. datalab/data/icons/operations/profile_segment.svg +262 -0
  198. datalab/data/icons/operations/quadratic_difference.svg +84 -0
  199. datalab/data/icons/operations/re.svg +124 -0
  200. datalab/data/icons/operations/rotate_left.svg +72 -0
  201. datalab/data/icons/operations/rotate_right.svg +72 -0
  202. datalab/data/icons/operations/signals_to_image.svg +314 -0
  203. datalab/data/icons/operations/sqrt.svg +110 -0
  204. datalab/data/icons/operations/std.svg +124 -0
  205. datalab/data/icons/operations/sum.svg +102 -0
  206. datalab/data/icons/play_demo.svg +9 -0
  207. datalab/data/icons/processing/axis_transform.svg +62 -0
  208. datalab/data/icons/processing/bandpass.svg +79 -0
  209. datalab/data/icons/processing/bandstop.svg +71 -0
  210. datalab/data/icons/processing/binning.svg +126 -0
  211. datalab/data/icons/processing/clip.svg +119 -0
  212. datalab/data/icons/processing/detrending.svg +173 -0
  213. datalab/data/icons/processing/distribute_on_grid.svg +769 -0
  214. datalab/data/icons/processing/edge_detection.svg +46 -0
  215. datalab/data/icons/processing/erase.svg +1 -0
  216. datalab/data/icons/processing/exposure.svg +143 -0
  217. datalab/data/icons/processing/fourier.svg +104 -0
  218. datalab/data/icons/processing/highpass.svg +59 -0
  219. datalab/data/icons/processing/interpolation.svg +71 -0
  220. datalab/data/icons/processing/level_adjustment.svg +70 -0
  221. datalab/data/icons/processing/lowpass.svg +60 -0
  222. datalab/data/icons/processing/morphology.svg +49 -0
  223. datalab/data/icons/processing/noise_addition.svg +114 -0
  224. datalab/data/icons/processing/noise_reduction.svg +38 -0
  225. datalab/data/icons/processing/normalize.svg +84 -0
  226. datalab/data/icons/processing/offset_correction.svg +131 -0
  227. datalab/data/icons/processing/resampling1d.svg +101 -0
  228. datalab/data/icons/processing/resampling2d.svg +240 -0
  229. datalab/data/icons/processing/reset_positions.svg +185 -0
  230. datalab/data/icons/processing/resize.svg +9 -0
  231. datalab/data/icons/processing/reverse_signal_x.svg +171 -0
  232. datalab/data/icons/processing/stability.svg +11 -0
  233. datalab/data/icons/processing/swap_x_y.svg +65 -0
  234. datalab/data/icons/processing/thresholding.svg +63 -0
  235. datalab/data/icons/processing/windowing.svg +45 -0
  236. datalab/data/icons/properties.svg +26 -0
  237. datalab/data/icons/reset.svg +9 -0
  238. datalab/data/icons/restore.svg +40 -0
  239. datalab/data/icons/roi/roi.svg +76 -0
  240. datalab/data/icons/roi/roi_coordinate.svg +78 -0
  241. datalab/data/icons/roi/roi_copy.svg +112 -0
  242. datalab/data/icons/roi/roi_delete.svg +81 -0
  243. datalab/data/icons/roi/roi_export.svg +87 -0
  244. datalab/data/icons/roi/roi_graphical.svg +78 -0
  245. datalab/data/icons/roi/roi_grid.svg +67 -0
  246. datalab/data/icons/roi/roi_ima.svg +188 -0
  247. datalab/data/icons/roi/roi_import.svg +87 -0
  248. datalab/data/icons/roi/roi_new.svg +81 -0
  249. datalab/data/icons/roi/roi_new_circle.svg +95 -0
  250. datalab/data/icons/roi/roi_new_polygon.svg +110 -0
  251. datalab/data/icons/roi/roi_new_rectangle.svg +70 -0
  252. datalab/data/icons/roi/roi_paste.svg +98 -0
  253. datalab/data/icons/roi/roi_sig.svg +124 -0
  254. datalab/data/icons/shapes.svg +134 -0
  255. datalab/data/icons/signal.svg +103 -0
  256. datalab/data/icons/table.svg +85 -0
  257. datalab/data/icons/table_unavailable.svg +102 -0
  258. datalab/data/icons/to_signal.svg +124 -0
  259. datalab/data/icons/tour/next.svg +44 -0
  260. datalab/data/icons/tour/previous.svg +44 -0
  261. datalab/data/icons/tour/rewind.svg +51 -0
  262. datalab/data/icons/tour/stop.svg +47 -0
  263. datalab/data/icons/tour/tour.svg +16 -0
  264. datalab/data/icons/uncheck_all.svg +78 -0
  265. datalab/data/icons/view/curve_antialiasing.svg +50 -0
  266. datalab/data/icons/view/new_window.svg +98 -0
  267. datalab/data/icons/view/refresh-auto.svg +57 -0
  268. datalab/data/icons/view/refresh-manual.svg +51 -0
  269. datalab/data/icons/view/reset_curve_styles.svg +96 -0
  270. datalab/data/icons/view/show_first.svg +55 -0
  271. datalab/data/icons/view/show_titles.svg +46 -0
  272. datalab/data/icons/visualization.svg +51 -0
  273. datalab/data/logo/DataLab-Banner-150.png +0 -0
  274. datalab/data/logo/DataLab-Banner-200.png +0 -0
  275. datalab/data/logo/DataLab-Banner2-100.png +0 -0
  276. datalab/data/logo/DataLab-Splash.png +0 -0
  277. datalab/data/logo/DataLab-watermark.png +0 -0
  278. datalab/data/logo/DataLab.svg +83 -0
  279. datalab/data/tests/reordering_test.h5 +0 -0
  280. datalab/data/tutorials/fabry_perot/fabry-perot1.jpg +0 -0
  281. datalab/data/tutorials/fabry_perot/fabry-perot2.jpg +0 -0
  282. datalab/data/tutorials/laser_beam/TEM00_z_13.jpg +0 -0
  283. datalab/data/tutorials/laser_beam/TEM00_z_18.jpg +0 -0
  284. datalab/data/tutorials/laser_beam/TEM00_z_23.jpg +0 -0
  285. datalab/data/tutorials/laser_beam/TEM00_z_30.jpg +0 -0
  286. datalab/data/tutorials/laser_beam/TEM00_z_35.jpg +0 -0
  287. datalab/data/tutorials/laser_beam/TEM00_z_40.jpg +0 -0
  288. datalab/data/tutorials/laser_beam/TEM00_z_45.jpg +0 -0
  289. datalab/data/tutorials/laser_beam/TEM00_z_50.jpg +0 -0
  290. datalab/data/tutorials/laser_beam/TEM00_z_55.jpg +0 -0
  291. datalab/data/tutorials/laser_beam/TEM00_z_60.jpg +0 -0
  292. datalab/data/tutorials/laser_beam/TEM00_z_65.jpg +0 -0
  293. datalab/data/tutorials/laser_beam/TEM00_z_70.jpg +0 -0
  294. datalab/data/tutorials/laser_beam/TEM00_z_75.jpg +0 -0
  295. datalab/data/tutorials/laser_beam/TEM00_z_80.jpg +0 -0
  296. datalab/env.py +542 -0
  297. datalab/gui/__init__.py +89 -0
  298. datalab/gui/actionhandler.py +1701 -0
  299. datalab/gui/docks.py +473 -0
  300. datalab/gui/h5io.py +150 -0
  301. datalab/gui/macroeditor.py +310 -0
  302. datalab/gui/main.py +2081 -0
  303. datalab/gui/newobject.py +217 -0
  304. datalab/gui/objectview.py +766 -0
  305. datalab/gui/panel/__init__.py +48 -0
  306. datalab/gui/panel/base.py +3254 -0
  307. datalab/gui/panel/image.py +157 -0
  308. datalab/gui/panel/macro.py +607 -0
  309. datalab/gui/panel/signal.py +164 -0
  310. datalab/gui/plothandler.py +800 -0
  311. datalab/gui/processor/__init__.py +84 -0
  312. datalab/gui/processor/base.py +2456 -0
  313. datalab/gui/processor/catcher.py +75 -0
  314. datalab/gui/processor/image.py +1214 -0
  315. datalab/gui/processor/signal.py +755 -0
  316. datalab/gui/profiledialog.py +333 -0
  317. datalab/gui/roieditor.py +633 -0
  318. datalab/gui/roigrideditor.py +208 -0
  319. datalab/gui/settings.py +612 -0
  320. datalab/gui/tour.py +908 -0
  321. datalab/h5/__init__.py +12 -0
  322. datalab/h5/common.py +314 -0
  323. datalab/h5/generic.py +580 -0
  324. datalab/h5/native.py +39 -0
  325. datalab/h5/utils.py +95 -0
  326. datalab/objectmodel.py +640 -0
  327. datalab/plugins/_readme_.txt +9 -0
  328. datalab/plugins/datalab_imageformats.py +175 -0
  329. datalab/plugins/datalab_testdata.py +190 -0
  330. datalab/plugins.py +355 -0
  331. datalab/tests/__init__.py +199 -0
  332. datalab/tests/backbone/__init__.py +1 -0
  333. datalab/tests/backbone/config_unit_test.py +170 -0
  334. datalab/tests/backbone/config_versioning_unit_test.py +34 -0
  335. datalab/tests/backbone/dictlistserial_app_test.py +38 -0
  336. datalab/tests/backbone/errorcatcher_unit_test.py +69 -0
  337. datalab/tests/backbone/errormsgbox_unit_test.py +50 -0
  338. datalab/tests/backbone/execenv_unit.py +262 -0
  339. datalab/tests/backbone/loadtest_gdi.py +147 -0
  340. datalab/tests/backbone/long_callback.py +96 -0
  341. datalab/tests/backbone/main_app_test.py +137 -0
  342. datalab/tests/backbone/memory_leak.py +43 -0
  343. datalab/tests/backbone/procisolation1_unit.py +128 -0
  344. datalab/tests/backbone/procisolation2_unit.py +171 -0
  345. datalab/tests/backbone/procisolation_unit_test.py +22 -0
  346. datalab/tests/backbone/profiling_app.py +27 -0
  347. datalab/tests/backbone/strings_unit_test.py +65 -0
  348. datalab/tests/backbone/title_formatting_unit_test.py +82 -0
  349. datalab/tests/conftest.py +131 -0
  350. datalab/tests/features/__init__.py +1 -0
  351. datalab/tests/features/applauncher/__init__.py +1 -0
  352. datalab/tests/features/applauncher/launcher1_app_test.py +28 -0
  353. datalab/tests/features/applauncher/launcher2_app_test.py +30 -0
  354. datalab/tests/features/common/__init__.py +1 -0
  355. datalab/tests/features/common/add_metadata_app_test.py +134 -0
  356. datalab/tests/features/common/add_metadata_unit_test.py +267 -0
  357. datalab/tests/features/common/annotations_management_unit_test.py +152 -0
  358. datalab/tests/features/common/auto_analysis_recompute_unit_test.py +240 -0
  359. datalab/tests/features/common/createobject_unit_test.py +50 -0
  360. datalab/tests/features/common/geometry_results_app_test.py +135 -0
  361. datalab/tests/features/common/interactive_processing_test.py +1109 -0
  362. datalab/tests/features/common/io_app_test.py +75 -0
  363. datalab/tests/features/common/large_results_app_test.py +187 -0
  364. datalab/tests/features/common/metadata_all_patterns_test.py +103 -0
  365. datalab/tests/features/common/metadata_app_test.py +139 -0
  366. datalab/tests/features/common/metadata_io_unit_test.py +60 -0
  367. datalab/tests/features/common/misc_app_test.py +236 -0
  368. datalab/tests/features/common/multiple_geometry_results_unit_test.py +122 -0
  369. datalab/tests/features/common/multiple_table_results_unit_test.py +64 -0
  370. datalab/tests/features/common/operation_modes_app_test.py +392 -0
  371. datalab/tests/features/common/plot_results_app_test.py +278 -0
  372. datalab/tests/features/common/reorder_app_test.py +75 -0
  373. datalab/tests/features/common/result_deletion_unit_test.py +96 -0
  374. datalab/tests/features/common/result_merged_label_unit_test.py +154 -0
  375. datalab/tests/features/common/result_shape_settings_unit_test.py +223 -0
  376. datalab/tests/features/common/roi_plotitem_unit_test.py +64 -0
  377. datalab/tests/features/common/roieditor_unit_test.py +102 -0
  378. datalab/tests/features/common/save_to_dir_app_test.py +163 -0
  379. datalab/tests/features/common/save_to_dir_unit_test.py +474 -0
  380. datalab/tests/features/common/stat_app_test.py +40 -0
  381. datalab/tests/features/common/stats_tools_unit_test.py +77 -0
  382. datalab/tests/features/common/table_results_app_test.py +52 -0
  383. datalab/tests/features/common/textimport_unit_test.py +131 -0
  384. datalab/tests/features/common/uuid_preservation_test.py +281 -0
  385. datalab/tests/features/common/worker_unit_test.py +402 -0
  386. datalab/tests/features/control/__init__.py +1 -0
  387. datalab/tests/features/control/connect_dialog.py +28 -0
  388. datalab/tests/features/control/embedded1_unit_test.py +304 -0
  389. datalab/tests/features/control/embedded2_unit_test.py +52 -0
  390. datalab/tests/features/control/remoteclient_app_test.py +219 -0
  391. datalab/tests/features/control/remoteclient_unit.py +75 -0
  392. datalab/tests/features/control/simpleclient_unit_test.py +321 -0
  393. datalab/tests/features/hdf5/__init__.py +1 -0
  394. datalab/tests/features/hdf5/h5browser1_unit_test.py +31 -0
  395. datalab/tests/features/hdf5/h5browser2_unit.py +55 -0
  396. datalab/tests/features/hdf5/h5browser_app_test.py +77 -0
  397. datalab/tests/features/hdf5/h5import_app_test.py +25 -0
  398. datalab/tests/features/hdf5/h5importer_app_test.py +34 -0
  399. datalab/tests/features/image/__init__.py +1 -0
  400. datalab/tests/features/image/annotations_app_test.py +28 -0
  401. datalab/tests/features/image/annotations_unit_test.py +80 -0
  402. datalab/tests/features/image/average_app_test.py +46 -0
  403. datalab/tests/features/image/background_dialog_test.py +70 -0
  404. datalab/tests/features/image/blobs_app_test.py +50 -0
  405. datalab/tests/features/image/contour_app_test.py +42 -0
  406. datalab/tests/features/image/contour_fabryperot_app_test.py +51 -0
  407. datalab/tests/features/image/denoise_app_test.py +31 -0
  408. datalab/tests/features/image/distribute_on_grid_app_test.py +95 -0
  409. datalab/tests/features/image/edges_app_test.py +31 -0
  410. datalab/tests/features/image/erase_app_test.py +21 -0
  411. datalab/tests/features/image/fft2d_app_test.py +27 -0
  412. datalab/tests/features/image/flatfield_app_test.py +40 -0
  413. datalab/tests/features/image/geometry_transform_unit_test.py +396 -0
  414. datalab/tests/features/image/imagetools_app_test.py +51 -0
  415. datalab/tests/features/image/imagetools_unit_test.py +27 -0
  416. datalab/tests/features/image/load_app_test.py +73 -0
  417. datalab/tests/features/image/morph_app_test.py +32 -0
  418. datalab/tests/features/image/offsetcorrection_app_test.py +30 -0
  419. datalab/tests/features/image/peak2d_app_test.py +53 -0
  420. datalab/tests/features/image/profile_app_test.py +73 -0
  421. datalab/tests/features/image/profile_dialog_test.py +56 -0
  422. datalab/tests/features/image/roi_app_test.py +98 -0
  423. datalab/tests/features/image/roi_circ_app_test.py +62 -0
  424. datalab/tests/features/image/roi_manipulation_app_test.py +268 -0
  425. datalab/tests/features/image/roigrid_unit_test.py +60 -0
  426. datalab/tests/features/image/side_by_side_app_test.py +52 -0
  427. datalab/tests/features/macro/__init__.py +1 -0
  428. datalab/tests/features/macro/macro_app_test.py +28 -0
  429. datalab/tests/features/macro/macroeditor_unit_test.py +102 -0
  430. datalab/tests/features/signal/__init__.py +1 -0
  431. datalab/tests/features/signal/baseline_dialog_test.py +53 -0
  432. datalab/tests/features/signal/deltax_dialog_unit_test.py +34 -0
  433. datalab/tests/features/signal/fft1d_app_test.py +26 -0
  434. datalab/tests/features/signal/filter_app_test.py +44 -0
  435. datalab/tests/features/signal/fitdialog_unit_test.py +50 -0
  436. datalab/tests/features/signal/interpolation_app_test.py +110 -0
  437. datalab/tests/features/signal/loadbigsignal_app_test.py +80 -0
  438. datalab/tests/features/signal/multiple_rois_unit_test.py +132 -0
  439. datalab/tests/features/signal/pulse_features_app_test.py +118 -0
  440. datalab/tests/features/signal/pulse_features_roi_app_test.py +55 -0
  441. datalab/tests/features/signal/roi_app_test.py +78 -0
  442. datalab/tests/features/signal/roi_manipulation_app_test.py +261 -0
  443. datalab/tests/features/signal/select_xy_cursor_unit_test.py +46 -0
  444. datalab/tests/features/signal/signalpeakdetection_dialog_test.py +33 -0
  445. datalab/tests/features/signal/signals_to_image_app_test.py +98 -0
  446. datalab/tests/features/signal/xarray_compat_app_test.py +128 -0
  447. datalab/tests/features/tour_unit_test.py +22 -0
  448. datalab/tests/features/utilities/__init__.py +1 -0
  449. datalab/tests/features/utilities/installconf_unit_test.py +21 -0
  450. datalab/tests/features/utilities/logview_app_test.py +21 -0
  451. datalab/tests/features/utilities/logview_error.py +24 -0
  452. datalab/tests/features/utilities/logview_unit_test.py +21 -0
  453. datalab/tests/features/utilities/memstatus_app_test.py +42 -0
  454. datalab/tests/features/utilities/settings_unit_test.py +88 -0
  455. datalab/tests/scenarios/__init__.py +1 -0
  456. datalab/tests/scenarios/beautiful_app.py +121 -0
  457. datalab/tests/scenarios/common.py +463 -0
  458. datalab/tests/scenarios/demo.py +212 -0
  459. datalab/tests/scenarios/example_app_test.py +47 -0
  460. datalab/tests/scenarios/scenario_h5_app_test.py +75 -0
  461. datalab/tests/scenarios/scenario_ima1_app_test.py +34 -0
  462. datalab/tests/scenarios/scenario_ima2_app_test.py +34 -0
  463. datalab/tests/scenarios/scenario_mac_app_test.py +58 -0
  464. datalab/tests/scenarios/scenario_sig1_app_test.py +36 -0
  465. datalab/tests/scenarios/scenario_sig2_app_test.py +35 -0
  466. datalab/utils/__init__.py +1 -0
  467. datalab/utils/conf.py +304 -0
  468. datalab/utils/dephash.py +105 -0
  469. datalab/utils/qthelpers.py +633 -0
  470. datalab/utils/strings.py +34 -0
  471. datalab/utils/tests.py +0 -0
  472. datalab/widgets/__init__.py +1 -0
  473. datalab/widgets/connection.py +138 -0
  474. datalab/widgets/filedialog.py +91 -0
  475. datalab/widgets/fileviewer.py +84 -0
  476. datalab/widgets/fitdialog.py +788 -0
  477. datalab/widgets/h5browser.py +1048 -0
  478. datalab/widgets/imagebackground.py +111 -0
  479. datalab/widgets/instconfviewer.py +175 -0
  480. datalab/widgets/logviewer.py +80 -0
  481. datalab/widgets/signalbaseline.py +90 -0
  482. datalab/widgets/signalcursor.py +208 -0
  483. datalab/widgets/signaldeltax.py +151 -0
  484. datalab/widgets/signalpeak.py +199 -0
  485. datalab/widgets/status.py +249 -0
  486. datalab/widgets/textimport.py +786 -0
  487. datalab/widgets/warningerror.py +223 -0
  488. datalab/widgets/wizard.py +286 -0
  489. datalab_platform-1.0.1.dist-info/METADATA +121 -0
  490. datalab_platform-1.0.1.dist-info/RECORD +494 -0
  491. datalab_platform-0.0.1.dev0.dist-info/METADATA +0 -67
  492. datalab_platform-0.0.1.dev0.dist-info/RECORD +0 -7
  493. {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/WHEEL +0 -0
  494. {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/entry_points.txt +0 -0
  495. {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/licenses/LICENSE +0 -0
  496. {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,170 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Configuration test
5
+
6
+ Checking .ini configuration file management.
7
+ """
8
+
9
+ # guitest: show
10
+
11
+ import os
12
+ import os.path as osp
13
+
14
+ from qtpy import QtCore as QC
15
+ from qtpy import QtWidgets as QW
16
+
17
+ from datalab import app
18
+ from datalab.config import Conf
19
+ from datalab.env import execenv
20
+ from datalab.tests import helpers
21
+ from datalab.utils.conf import CONF
22
+ from datalab.utils.qthelpers import datalab_app_context
23
+
24
+ SEC_MAIN = Conf.main
25
+ OPT_MAX = SEC_MAIN.window_maximized
26
+ OPT_POS = SEC_MAIN.window_position
27
+ OPT_SIZ = SEC_MAIN.window_size
28
+ OPT_DIR = SEC_MAIN.base_dir
29
+
30
+ SEC_CONS = Conf.console
31
+ OPT_CON = SEC_CONS.console_enabled
32
+
33
+ CONFIGS = (
34
+ {
35
+ SEC_MAIN.get_name(): {
36
+ OPT_MAX.option: False,
37
+ OPT_POS.option: (250, 250),
38
+ OPT_SIZ.option: (1300, 700),
39
+ OPT_DIR.option: "",
40
+ },
41
+ SEC_CONS.get_name(): {
42
+ OPT_CON.option: False,
43
+ },
44
+ },
45
+ {
46
+ SEC_MAIN.get_name(): {
47
+ OPT_MAX.option: False,
48
+ OPT_POS.option: (100, 100),
49
+ OPT_SIZ.option: (750, 600),
50
+ OPT_DIR.option: osp.dirname(__file__),
51
+ },
52
+ SEC_CONS.get_name(): {
53
+ OPT_CON.option: False,
54
+ },
55
+ },
56
+ {
57
+ SEC_MAIN.get_name(): {
58
+ OPT_MAX.option: True,
59
+ OPT_POS.option: (10, 10),
60
+ OPT_SIZ.option: (750, 600),
61
+ OPT_DIR.option: "",
62
+ },
63
+ SEC_CONS.get_name(): {
64
+ OPT_CON.option: True,
65
+ },
66
+ },
67
+ )
68
+
69
+
70
+ def apply_conf(conf, name):
71
+ """Apply configuration"""
72
+ execenv.print(f" Applying configuration {name}:")
73
+ fname = CONF.filename()
74
+ try:
75
+ os.remove(fname)
76
+ execenv.print(f" Removed configuration file {fname}")
77
+ except FileNotFoundError:
78
+ execenv.print(f" Configuration file {fname} was not found")
79
+ for section, settings in conf.items():
80
+ for option, value in settings.items():
81
+ execenv.print(f" Writing [{section}][{option}] = {value}")
82
+ CONF.set(section, option, value)
83
+ CONF.save()
84
+
85
+
86
+ def is_wsl() -> bool:
87
+ """Return True if running on Windows Subsystem for Linux (WSL)"""
88
+ if os.name == "posix":
89
+ return "WSL" in os.uname().release # pylint: disable=no-member
90
+ return False
91
+
92
+
93
+ def is_offscreen() -> bool:
94
+ """Return True if running in offscreen mode (e.g. in CI or pytest session)"""
95
+ return os.environ.get("QT_QPA_PLATFORM", "") == "offscreen"
96
+
97
+
98
+ def assert_in_interval(val1, val2, interval, context):
99
+ """Raise an AssertionError if val1 is in [val2-interval/2,val2+interval/2]"""
100
+ itv1, itv2 = val2 - 0.5 * interval, val2 + 0.5 * interval
101
+ try:
102
+ assert itv1 <= val1 <= itv2
103
+ except AssertionError as exc:
104
+ if is_wsl() or is_offscreen():
105
+ # Ignore this assertion error in two cases:
106
+ # 1. If running on WSL, as the position of windows is not reliable
107
+ # 2. If running in offscreen mode (e.g. in CI or pytest session),
108
+ # as the position of windows may not be set correctly in offscreen mode
109
+ pass
110
+ else:
111
+ raise AssertionError(f"{context}: {itv1} <= {val1} <= {itv2}") from exc
112
+
113
+
114
+ def check_conf(conf, name, win: QW.QMainWindow, h5files):
115
+ """Check configuration"""
116
+ execenv.print(f" Checking configuration {name}: ")
117
+ sec_main_name = SEC_MAIN.get_name()
118
+ sec_cons_name = SEC_CONS.get_name()
119
+ sec_main = conf[sec_main_name]
120
+ sec_cons = conf[sec_cons_name]
121
+ execenv.print(f" Checking [{sec_main_name}][{OPT_MAX.option}]: ", end="")
122
+ assert sec_main[OPT_MAX.option] == (
123
+ win.windowState() == QC.Qt.WindowState.WindowMaximized
124
+ )
125
+ execenv.print("OK")
126
+ execenv.print(f" Checking [{sec_main_name}][{OPT_POS.option}]: ", end="")
127
+ if not sec_main[OPT_MAX.option]: # Check position/size only when not maximized
128
+ # Check position, taking into account screen offset (e.g. Linux/Gnome)
129
+ conf_x, conf_y = sec_main[OPT_POS.option]
130
+ conf_w, conf_h = sec_main[OPT_SIZ.option]
131
+ available_go = QW.QDesktopWidget().availableGeometry()
132
+ x_offset, y_offset = available_go.x(), available_go.y()
133
+ assert_in_interval(win.x(), conf_x - x_offset, 0, "X position")
134
+ assert_in_interval(win.y(), conf_y - y_offset / 2, 15 + y_offset, "Y position")
135
+ # Check size
136
+ assert_in_interval(win.width(), conf_w, 5, "Width")
137
+ assert_in_interval(win.height(), conf_h, 5, "Height")
138
+ execenv.print(f"OK {win.x(), win.y(), win.width(), win.height()}")
139
+ else:
140
+ execenv.print("Passed (maximized)")
141
+ execenv.print(f" Checking [{sec_cons_name}][{OPT_CON.option}]: ", end="")
142
+ assert sec_cons[OPT_CON.option] == (win.console is not None)
143
+ execenv.print("OK")
144
+ execenv.print(f" Checking [{sec_main_name}][{OPT_DIR.option}]: ", end="")
145
+ if h5files is None:
146
+ assert conf[SEC_MAIN.get_name()][OPT_DIR.option] == OPT_DIR.get()
147
+ execenv.print("OK (written in conf file)")
148
+ else:
149
+ assert OPT_DIR.get() == osp.dirname(h5files[0])
150
+ execenv.print("OK (changed to HDF5 file path)")
151
+
152
+
153
+ def test_config():
154
+ """Testing DataLab configuration file"""
155
+ with execenv.context(unattended=True):
156
+ h5files = [helpers.get_test_fnames("*.h5")[1]]
157
+ execenv.print("Testing DataLab configuration settings:")
158
+ for index, conf in enumerate(CONFIGS):
159
+ name = f"CONFIG{index}"
160
+ apply_conf(conf, name)
161
+ with datalab_app_context(exec_loop=True) as qapp:
162
+ win = app.create(splash=False, h5files=h5files)
163
+ qapp.processEvents()
164
+ check_conf(conf, name, win, h5files)
165
+ h5files = None
166
+ execenv.print("=> Everything is OK")
167
+
168
+
169
+ if __name__ == "__main__":
170
+ test_config()
@@ -0,0 +1,34 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Configuration versioning test.
5
+
6
+ Test that the configuration folder name is versioned correctly.
7
+ """
8
+
9
+ import datalab
10
+ from datalab.config import get_config_app_name
11
+
12
+
13
+ def test_config_app_name():
14
+ """Test configuration app name versioning."""
15
+ config_name = get_config_app_name()
16
+ major_version = datalab.__version__.split(".", maxsplit=1)[0]
17
+
18
+ print(f"DataLab version: {datalab.__version__}")
19
+ print(f"Major version: {major_version}")
20
+ print(f"Config app name: {config_name}")
21
+
22
+ # For v0.x, the config name should be "DataLab" (no suffix)
23
+ if major_version == "0":
24
+ assert config_name == "DataLab", f"Expected 'DataLab', got '{config_name}'"
25
+ print("✓ v0.x uses legacy config folder name: .DataLab")
26
+ else:
27
+ # For v1.x, v2.x, etc., the config name should include version suffix
28
+ expected = f"DataLab_v{major_version}"
29
+ assert config_name == expected, f"Expected '{expected}', got '{config_name}'"
30
+ print(f"✓ v{major_version}.x uses versioned config folder: .{config_name}")
31
+
32
+
33
+ if __name__ == "__main__":
34
+ test_config_app_name()
@@ -0,0 +1,38 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Testing (de)serialization of Dictionnary/List inside object metadata
5
+ """
6
+
7
+ # guitest: show
8
+
9
+ import os.path as osp
10
+
11
+ from sigima.tests.data import create_test_image_with_metadata
12
+
13
+ from datalab.env import execenv
14
+ from datalab.tests import datalab_test_app_context, helpers
15
+
16
+
17
+ def test_dict_serialization():
18
+ """Dictionnary/List in metadata (de)serialization test"""
19
+ with execenv.context(unattended=True):
20
+ with helpers.WorkdirRestoringTempDir() as tmpdir:
21
+ with datalab_test_app_context(console=False) as win:
22
+ panel = win.imagepanel
23
+ image = create_test_image_with_metadata()
24
+ panel.add_object(image)
25
+ fname = osp.join(tmpdir, "test.h5")
26
+ win.save_to_h5_file(fname)
27
+ win.reset_all()
28
+ win.open_h5_files([fname], import_all=True)
29
+ execenv.print("Dictionary/List (de)serialization:")
30
+ oids = panel.objmodel.get_object_ids()
31
+ first_image = panel.objmodel[oids[0]]
32
+ helpers.compare_metadata(
33
+ image.metadata, first_image.metadata.copy(), raise_on_diff=True
34
+ )
35
+
36
+
37
+ if __name__ == "__main__":
38
+ test_dict_serialization()
@@ -0,0 +1,69 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Catch error and warning test (during computation)
5
+
6
+ Unit test for BaseProcessor.handle_output method: catching error and warning
7
+ during computation. This test runs a computation function that raises an
8
+ error and/or a warning, and checks that the error and/or warning are/is correctly
9
+ caught and displayed in the GUI.
10
+ """
11
+
12
+ # pylint: disable=invalid-name # Allows short reference names like x, y, ...
13
+ # pylint: disable=duplicate-code
14
+ # guitest: show
15
+
16
+ import warnings
17
+
18
+ from sigima.objects import SignalObj
19
+ from sigima.tests import data as test_data
20
+
21
+ from datalab.config import Conf
22
+ from datalab.env import execenv
23
+ from datalab.tests import datalab_test_app_context
24
+
25
+
26
+ def comp_error(src: SignalObj) -> SignalObj: # pylint: disable=unused-argument
27
+ """Computation function that raises an error"""
28
+ raise ValueError("This is a test error")
29
+
30
+
31
+ def comp_warning(src: SignalObj) -> SignalObj: # pylint: disable=unused-argument
32
+ """Computation function that raises a warning"""
33
+ warnings.warn("This is a test warning")
34
+ return src.copy()
35
+
36
+
37
+ def comp_warning_error(src: SignalObj) -> SignalObj: # pylint: disable=unused-argument
38
+ """Computation function that raises a warning and an error"""
39
+ warnings.warn("This is a test warning")
40
+ raise ValueError("This is a test error")
41
+
42
+
43
+ def comp_no_error(src: SignalObj) -> SignalObj: # pylint: disable=unused-argument
44
+ """Computation function that does not raise an error"""
45
+ return src.copy()
46
+
47
+
48
+ def test_catcher():
49
+ """Catch error and warning test"""
50
+ with execenv.context(catcher_test=True):
51
+ with datalab_test_app_context() as win:
52
+ panel = win.signalpanel
53
+ sig = test_data.create_paracetamol_signal()
54
+ panel.add_object(sig)
55
+ panel.processor.compute_1_to_1(comp_no_error, title="Test no error")
56
+ panel.processor.compute_1_to_1(comp_error, title="Test error")
57
+ Conf.proc.ignore_warnings.set(True)
58
+ panel.processor.compute_1_to_1(comp_warning, title="Test warning (ignored)")
59
+ Conf.proc.ignore_warnings.set(False)
60
+ panel.processor.compute_1_to_1(
61
+ comp_warning, title="Test warning (not ignored)"
62
+ )
63
+ panel.processor.compute_1_to_1(
64
+ comp_warning_error, title="Test warning + error"
65
+ )
66
+
67
+
68
+ if __name__ == "__main__":
69
+ test_catcher()
@@ -0,0 +1,50 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ Error message box test
5
+ """
6
+
7
+ # guitest: show
8
+
9
+ from guidata.qthelpers import exec_dialog, qt_app_context
10
+ from qtpy import QtWidgets as QW
11
+
12
+ from datalab.widgets.warningerror import WarningErrorMessageBox
13
+
14
+
15
+ def error_message_box(category: str):
16
+ """Test error message box
17
+
18
+ Args:
19
+ category (str): Error category
20
+ Valid values are: "error", "warning"
21
+ """
22
+ with qt_app_context():
23
+ win = QW.QMainWindow()
24
+ win.setWindowTitle(f"DataLab {category.capitalize()} Message Box test")
25
+ win.show()
26
+ if category == "error":
27
+ try:
28
+ raise ValueError("Test error message box")
29
+ except ValueError:
30
+ context = "Test_error_message_box." * 5
31
+ tip = "This error may occured when testing the error message box. " * 10
32
+ dlg = WarningErrorMessageBox(win, "error", context, tip=tip)
33
+ exec_dialog(dlg)
34
+ elif category == "warning":
35
+ context = "Test_warning_message_box." * 5
36
+ message = "Test warning message box" * 10
37
+ dlg = WarningErrorMessageBox(win, "warning", context, message)
38
+ exec_dialog(dlg)
39
+ else:
40
+ raise ValueError(f"Invalid category: {category}")
41
+
42
+
43
+ def test_error_message_box():
44
+ """Test error message box"""
45
+ error_message_box("error")
46
+ error_message_box("warning")
47
+
48
+
49
+ if __name__ == "__main__":
50
+ test_error_message_box()
@@ -0,0 +1,262 @@
1
+ # Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
2
+
3
+ """
4
+ DLExecEnv test
5
+ ---------------
6
+
7
+ Checking DataLab execution environment management.
8
+ """
9
+
10
+ # guitest: skip (only needed for regression tests)
11
+
12
+ from __future__ import annotations
13
+
14
+ import os
15
+ import sys
16
+
17
+ import datalab
18
+ from datalab.env import VerbosityLevels, execenv
19
+ from datalab.tests import helpers
20
+
21
+ ARGV_TEST = "--execenvtest"
22
+
23
+
24
+ def print_execenv() -> None:
25
+ """Print DL execution environment"""
26
+ sys.argv.remove(ARGV_TEST)
27
+ print(str(execenv.to_dict()))
28
+
29
+
30
+ def get_subprocess_execenv_dict(args: list[str], env: dict | None = None) -> dict:
31
+ """Get DL execution environment dict from subprocess
32
+
33
+ Args:
34
+ args (list[str]): command-line arguments
35
+ env (dict | None): environment variables to pass to subprocess
36
+
37
+ Returns:
38
+ dict[str, str | int | bool | None]: DL execution environment dict
39
+ """
40
+ output = helpers.get_script_output(__file__, args=args + [ARGV_TEST], env=env)
41
+ return eval(output) # pylint: disable=eval-used
42
+
43
+
44
+ def assert_two_dicts_are_equal(
45
+ dict1: dict, dict2: dict, exceptions: tuple[str] | None = None
46
+ ) -> None:
47
+ """Assert two dicts are equal
48
+
49
+ Args:
50
+ dict1 (dict): first dict
51
+ dict2 (dict): second dict
52
+ exceptions (tuple[str] | None): keys to ignore
53
+ """
54
+ diff_keys = []
55
+ for key in dict1:
56
+ if key in exceptions:
57
+ continue
58
+ if dict1[key] != dict2[key]:
59
+ diff_keys.append(key)
60
+ if diff_keys:
61
+ assert False, f"Dictionaries differ on keys: {diff_keys}"
62
+
63
+
64
+ def test_cli():
65
+ """Test DL execution environment from command-line"""
66
+ remove_all_datalab_envvars()
67
+
68
+ # Test default values
69
+ execenv.print("Testing command-line arguments:")
70
+ execenv.print(" Default values: ", end="")
71
+ execenvdict = get_subprocess_execenv_dict([])
72
+ execenv.print("OK")
73
+ assert execenvdict == execenv.to_dict()
74
+ # Testing boolean arguments
75
+ execenv.print(" Testing boolean arguments:")
76
+ for argname in ("unattended", "accept_dialogs", "screenshot"):
77
+ execenv.print(f" {argname}:", end="")
78
+ for val in (True, False):
79
+ execenv.print(f" {val}", end="")
80
+ if val:
81
+ args = [f"--{argname}"]
82
+ else:
83
+ args = [] # Default value is False
84
+ execenvdict = get_subprocess_execenv_dict(args)
85
+ assert_two_dicts_are_equal(execenvdict, execenv.to_dict(), (argname,))
86
+ assert execenvdict[argname] is val, (
87
+ f"execenvdict[{argname}] = {execenvdict[argname]} != {val}"
88
+ )
89
+ execenv.print()
90
+ # Testing integer arguments
91
+ execenv.print(" Testing integer arguments:")
92
+ for argname in ("delay", "xmlrpcport"):
93
+ execenv.print(f" {argname}:", end="")
94
+ for val in (None, 0, 1, 2):
95
+ if val is None:
96
+ args = []
97
+ else:
98
+ args = [f"--{argname}", str(val)]
99
+ execenv.print(f" {val}", end="")
100
+ execenvdict = get_subprocess_execenv_dict(args)
101
+ assert_two_dicts_are_equal(execenvdict, execenv.to_dict(), (argname,))
102
+ if val is None:
103
+ if argname == "delay":
104
+ # Default value is 0 for delay
105
+ assert execenvdict[argname] == 0
106
+ else:
107
+ # Default value is None for xmlrpcport
108
+ assert execenvdict[argname] is None
109
+ else:
110
+ assert execenvdict[argname] == val
111
+ execenv.print()
112
+ # Testing choice arguments
113
+ execenv.print(" Testing choice arguments:")
114
+ for argname in ("verbose",):
115
+ execenv.print(f" {argname}:", end="")
116
+ choices = {"verbose": [verb.value for verb in VerbosityLevels]}
117
+ defaultval = {"verbose": VerbosityLevels.NORMAL.value}[argname]
118
+ for val in [None] + choices[argname]:
119
+ if val is None:
120
+ args = []
121
+ else:
122
+ args = [f"--{argname}", val]
123
+ execenv.print(f" {val}", end="")
124
+ execenvdict = get_subprocess_execenv_dict(args)
125
+ assert_two_dicts_are_equal(execenvdict, execenv.to_dict(), (argname,))
126
+ if val is None:
127
+ assert execenvdict[argname] == defaultval
128
+ else:
129
+ assert execenvdict[argname] == val
130
+ execenv.print()
131
+ # Testing special arguments
132
+ execenv.print(" Testing special arguments:")
133
+ execenv.print(" version: ", end="")
134
+ args = ["--version"]
135
+ output = helpers.get_script_output(__file__, args=args + [ARGV_TEST])
136
+ execenv.print(output)
137
+ assert datalab.__version__ in output
138
+ execenv.print(" h5 positionnal argument: ", end="")
139
+ for h5files in (None, ["test.h5"], ["toto.h5", "tata.h5"]):
140
+ if h5files is None:
141
+ args = []
142
+ else:
143
+ args = [";".join(h5files)]
144
+ execenv.print(f" {h5files}", end="")
145
+ execenvdict = get_subprocess_execenv_dict(args)
146
+ assert execenvdict["h5files"] == h5files
147
+ execenv.print()
148
+ execenv.print(" h5browser argument:")
149
+ for argname in ("-b", "--h5browser"):
150
+ execenv.print(f" {argname}", end="")
151
+ for val in (None, "test.h5"):
152
+ if val is None:
153
+ args = []
154
+ else:
155
+ args = [argname, val]
156
+ execenv.print(f" {val}", end="")
157
+ execenvdict = get_subprocess_execenv_dict(args)
158
+ assert execenvdict["h5browser_file"] == val
159
+ execenv.print()
160
+ execenv.print("=> Everything is OK")
161
+
162
+
163
+ def remove_all_datalab_envvars():
164
+ """Remove all DL environment variables"""
165
+ for _attrname, envvar in execenv.iterate_over_attrs_envvars():
166
+ os.environ.pop(envvar, None)
167
+
168
+
169
+ def get_attr_to_envvar(
170
+ vartype: type,
171
+ default: int | str | None | bool,
172
+ values: list[int | str | None | bool] | None = None,
173
+ ) -> tuple:
174
+ """Get ATTR_TO_ENVVAR tuple for a given type"""
175
+ if vartype is bool:
176
+ if default is False:
177
+ ate = ((True, ("1", "true")), (False, (None, "", "0", "false")))
178
+ else:
179
+ ate = ((True, (None, "", "1", "true")), (False, ("0", "false")))
180
+ elif vartype is int:
181
+ ate = []
182
+ for val in values:
183
+ if val == default:
184
+ ate.append((val, (None, "", str(val))))
185
+ else:
186
+ ate.append((val, (str(val),)))
187
+ ate = tuple(ate)
188
+ if default is None:
189
+ ate = ((None, (None, "")),) + ate
190
+ elif vartype is str:
191
+ ate = ((None, (None, "")),)
192
+ elif vartype is list:
193
+ ate = []
194
+ for choice in values:
195
+ if choice == default:
196
+ ate.append((choice, (None, "", choice)))
197
+ else:
198
+ ate.append((choice, (choice,)))
199
+ ate = tuple(ate)
200
+ else:
201
+ raise ValueError(f"Unknown type {vartype}")
202
+ return ate
203
+
204
+
205
+ ATTR_TO_ENVVAR = {
206
+ "unattended": get_attr_to_envvar(bool, False),
207
+ "accept_dialogs": get_attr_to_envvar(bool, False),
208
+ "screenshot": get_attr_to_envvar(bool, False),
209
+ "do_not_quit": get_attr_to_envvar(bool, False),
210
+ "catcher_test": get_attr_to_envvar(bool, False),
211
+ "delay": get_attr_to_envvar(int, 0, [0, 10, 20]),
212
+ "xmlrpcport": get_attr_to_envvar(int, None, [9854, 1020, 213]),
213
+ "verbose": get_attr_to_envvar(
214
+ list, VerbosityLevels.NORMAL.value, [verb.value for verb in VerbosityLevels]
215
+ ),
216
+ }
217
+
218
+
219
+ def test_envvar():
220
+ """Testing DataLab configuration file"""
221
+ assert execenv.unattended is False, "This test must be run with unattended=False"
222
+ print("Testing DataLab execution environment:")
223
+ for attrname, envvar in execenv.iterate_over_attrs_envvars():
224
+ attr_to_envvar = ATTR_TO_ENVVAR[attrname]
225
+ print(f" Testing {attrname}:")
226
+ for value, envvals in attr_to_envvar:
227
+ print(f" {value}: [attr->env]", end="")
228
+ remove_all_datalab_envvars()
229
+ if value is not None:
230
+ setattr(execenv, attrname, value)
231
+ assert os.environ.get(envvar) in envvals, (
232
+ f"os.environ[{envvar}] = {os.environ.get(envvar)} != {envvals}"
233
+ )
234
+ print(" [env->attr]", end="")
235
+ remove_all_datalab_envvars()
236
+ for envval in envvals:
237
+ if envval is not None:
238
+ os.environ[envvar] = envval
239
+ assert getattr(execenv, attrname) == value, (
240
+ f"execenv.{attrname} = {getattr(execenv, attrname)}"
241
+ f" != {value} (envval = {repr(envval)})"
242
+ )
243
+ print(" [env->subprocess->attr]", end="")
244
+ remove_all_datalab_envvars()
245
+ for envval in envvals:
246
+ if envval is not None:
247
+ os.environ[envvar] = envval
248
+ execenvdict = get_subprocess_execenv_dict([])
249
+ assert execenvdict[attrname] == value, (
250
+ f"execenvdict[{attrname}] = {execenvdict[attrname]}"
251
+ f" != {value} (envval = {repr(envval)})"
252
+ )
253
+ print()
254
+ print("=> Everything is OK")
255
+
256
+
257
+ if __name__ == "__main__":
258
+ if ARGV_TEST in sys.argv:
259
+ print_execenv()
260
+ else:
261
+ test_envvar()
262
+ test_cli()