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.
- datalab/__init__.py +35 -2
- datalab/adapters_metadata/__init__.py +31 -0
- datalab/adapters_metadata/base_adapter.py +316 -0
- datalab/adapters_metadata/common.py +422 -0
- datalab/adapters_metadata/geometry_adapter.py +98 -0
- datalab/adapters_metadata/table_adapter.py +84 -0
- datalab/adapters_plotpy/__init__.py +54 -0
- datalab/adapters_plotpy/annotations.py +124 -0
- datalab/adapters_plotpy/base.py +110 -0
- datalab/adapters_plotpy/converters.py +86 -0
- datalab/adapters_plotpy/factories.py +80 -0
- datalab/adapters_plotpy/objects/__init__.py +0 -0
- datalab/adapters_plotpy/objects/base.py +197 -0
- datalab/adapters_plotpy/objects/image.py +157 -0
- datalab/adapters_plotpy/objects/scalar.py +565 -0
- datalab/adapters_plotpy/objects/signal.py +264 -0
- datalab/adapters_plotpy/roi/__init__.py +0 -0
- datalab/adapters_plotpy/roi/base.py +146 -0
- datalab/adapters_plotpy/roi/factory.py +93 -0
- datalab/adapters_plotpy/roi/image.py +207 -0
- datalab/adapters_plotpy/roi/signal.py +72 -0
- datalab/app.py +98 -0
- datalab/config.py +817 -0
- datalab/control/__init__.py +0 -0
- datalab/control/baseproxy.py +776 -0
- datalab/control/proxy.py +343 -0
- datalab/control/remote.py +1005 -0
- datalab/data/doc/DataLab_en.pdf +0 -0
- datalab/data/doc/DataLab_fr.pdf +0 -0
- datalab/data/icons/analysis/delete_results.svg +109 -0
- datalab/data/icons/analysis/fw1e2.svg +156 -0
- datalab/data/icons/analysis/fwhm.svg +156 -0
- datalab/data/icons/analysis/histogram.svg +49 -0
- datalab/data/icons/analysis/peak_detect.svg +160 -0
- datalab/data/icons/analysis/plot_results.svg +151 -0
- datalab/data/icons/analysis/show_results.svg +83 -0
- datalab/data/icons/analysis/stats.svg +49 -0
- datalab/data/icons/analysis.svg +120 -0
- datalab/data/icons/apply.svg +3 -0
- datalab/data/icons/check_all.svg +15 -0
- datalab/data/icons/collapse.svg +44 -0
- datalab/data/icons/collapse_selection.svg +63 -0
- datalab/data/icons/console.svg +101 -0
- datalab/data/icons/create/1d-normal.svg +8 -0
- datalab/data/icons/create/1d-poisson.svg +9 -0
- datalab/data/icons/create/1d-uniform.svg +8 -0
- datalab/data/icons/create/1d-zero.svg +57 -0
- datalab/data/icons/create/2d-gaussian.svg +56 -0
- datalab/data/icons/create/2d-normal.svg +38 -0
- datalab/data/icons/create/2d-poisson.svg +38 -0
- datalab/data/icons/create/2d-ramp.svg +90 -0
- datalab/data/icons/create/2d-sinc.svg +62 -0
- datalab/data/icons/create/2d-uniform.svg +38 -0
- datalab/data/icons/create/2d-zero.svg +13 -0
- datalab/data/icons/create/checkerboard.svg +39 -0
- datalab/data/icons/create/cosine.svg +12 -0
- datalab/data/icons/create/exponential.svg +55 -0
- datalab/data/icons/create/gaussian.svg +12 -0
- datalab/data/icons/create/grating.svg +29 -0
- datalab/data/icons/create/linear_chirp.svg +7 -0
- datalab/data/icons/create/logistic.svg +7 -0
- datalab/data/icons/create/lorentzian.svg +12 -0
- datalab/data/icons/create/planck.svg +12 -0
- datalab/data/icons/create/polynomial.svg +7 -0
- datalab/data/icons/create/pulse.svg +12 -0
- datalab/data/icons/create/ring.svg +18 -0
- datalab/data/icons/create/sawtooth.svg +7 -0
- datalab/data/icons/create/siemens.svg +35 -0
- datalab/data/icons/create/sinc.svg +12 -0
- datalab/data/icons/create/sine.svg +7 -0
- datalab/data/icons/create/square.svg +7 -0
- datalab/data/icons/create/square_pulse.svg +7 -0
- datalab/data/icons/create/step.svg +7 -0
- datalab/data/icons/create/step_pulse.svg +12 -0
- datalab/data/icons/create/triangle.svg +7 -0
- datalab/data/icons/create/voigt.svg +12 -0
- datalab/data/icons/edit/annotations.svg +72 -0
- datalab/data/icons/edit/annotations_copy.svg +114 -0
- datalab/data/icons/edit/annotations_delete.svg +83 -0
- datalab/data/icons/edit/annotations_edit.svg +98 -0
- datalab/data/icons/edit/annotations_export.svg +85 -0
- datalab/data/icons/edit/annotations_import.svg +85 -0
- datalab/data/icons/edit/annotations_paste.svg +100 -0
- datalab/data/icons/edit/copy_titles.svg +109 -0
- datalab/data/icons/edit/delete.svg +84 -0
- datalab/data/icons/edit/delete_all.svg +214 -0
- datalab/data/icons/edit/duplicate.svg +64 -0
- datalab/data/icons/edit/goto_source.svg +60 -0
- datalab/data/icons/edit/metadata.svg +60 -0
- datalab/data/icons/edit/metadata_add.svg +80 -0
- datalab/data/icons/edit/metadata_copy.svg +96 -0
- datalab/data/icons/edit/metadata_delete.svg +62 -0
- datalab/data/icons/edit/metadata_export.svg +68 -0
- datalab/data/icons/edit/metadata_import.svg +68 -0
- datalab/data/icons/edit/metadata_paste.svg +79 -0
- datalab/data/icons/edit/move_down.svg +55 -0
- datalab/data/icons/edit/move_up.svg +54 -0
- datalab/data/icons/edit/new_group.svg +76 -0
- datalab/data/icons/edit/recompute.svg +60 -0
- datalab/data/icons/edit/rename.svg +49 -0
- datalab/data/icons/edit.svg +16 -0
- datalab/data/icons/expand.svg +44 -0
- datalab/data/icons/expand_selection.svg +63 -0
- datalab/data/icons/fit/cdf_fit.svg +56 -0
- datalab/data/icons/fit/exponential_fit.svg +55 -0
- datalab/data/icons/fit/gaussian_fit.svg +62 -0
- datalab/data/icons/fit/interactive_fit.svg +101 -0
- datalab/data/icons/fit/linear_fit.svg +57 -0
- datalab/data/icons/fit/lorentzian_fit.svg +209 -0
- datalab/data/icons/fit/multigaussian_fit.svg +85 -0
- datalab/data/icons/fit/multilorentzian_fit.svg +85 -0
- datalab/data/icons/fit/piecewiseexponential_fit.svg +209 -0
- datalab/data/icons/fit/planckian_fit.svg +62 -0
- datalab/data/icons/fit/polynomial_fit.svg +59 -0
- datalab/data/icons/fit/sigmoid_fit.svg +56 -0
- datalab/data/icons/fit/sinusoidal_fit.svg +72 -0
- datalab/data/icons/fit/twohalfgaussian_fit.svg +63 -0
- datalab/data/icons/fit/voigt_fit.svg +57 -0
- datalab/data/icons/group.svg +56 -0
- datalab/data/icons/h5/h5array.svg +59 -0
- datalab/data/icons/h5/h5attrs.svg +75 -0
- datalab/data/icons/h5/h5browser.svg +133 -0
- datalab/data/icons/h5/h5file.svg +69 -0
- datalab/data/icons/h5/h5group.svg +49 -0
- datalab/data/icons/h5/h5scalar.svg +1 -0
- datalab/data/icons/help_pdf.svg +46 -0
- datalab/data/icons/history.svg +7 -0
- datalab/data/icons/image.svg +135 -0
- datalab/data/icons/io/fileopen_directory.svg +60 -0
- datalab/data/icons/io/fileopen_h5.svg +84 -0
- datalab/data/icons/io/fileopen_ima.svg +187 -0
- datalab/data/icons/io/fileopen_py.svg +123 -0
- datalab/data/icons/io/fileopen_sig.svg +138 -0
- datalab/data/icons/io/filesave_h5.svg +97 -0
- datalab/data/icons/io/filesave_ima.svg +200 -0
- datalab/data/icons/io/filesave_py.svg +136 -0
- datalab/data/icons/io/filesave_sig.svg +151 -0
- datalab/data/icons/io/import_text.svg +144 -0
- datalab/data/icons/io/save_to_directory.svg +134 -0
- datalab/data/icons/io.svg +84 -0
- datalab/data/icons/libre-camera-flash-off.svg +1 -0
- datalab/data/icons/libre-camera-flash-on.svg +1 -0
- datalab/data/icons/libre-gui-about.svg +1 -0
- datalab/data/icons/libre-gui-action-delete.svg +1 -0
- datalab/data/icons/libre-gui-add.svg +1 -0
- datalab/data/icons/libre-gui-arrow-down.svg +1 -0
- datalab/data/icons/libre-gui-arrow-left.svg +1 -0
- datalab/data/icons/libre-gui-arrow-right.svg +1 -0
- datalab/data/icons/libre-gui-arrow-up.svg +1 -0
- datalab/data/icons/libre-gui-close.svg +40 -0
- datalab/data/icons/libre-gui-cogs.svg +1 -0
- datalab/data/icons/libre-gui-globe.svg +1 -0
- datalab/data/icons/libre-gui-help.svg +1 -0
- datalab/data/icons/libre-gui-link.svg +1 -0
- datalab/data/icons/libre-gui-menu.svg +1 -0
- datalab/data/icons/libre-gui-pencil.svg +1 -0
- datalab/data/icons/libre-gui-plugin.svg +1 -0
- datalab/data/icons/libre-gui-questions.svg +1 -0
- datalab/data/icons/libre-gui-settings.svg +1 -0
- datalab/data/icons/libre-gui-unlink.svg +1 -0
- datalab/data/icons/libre-tech-ram.svg +1 -0
- datalab/data/icons/libre-toolbox.svg +1 -0
- datalab/data/icons/logs.svg +1 -0
- datalab/data/icons/markers.svg +74 -0
- datalab/data/icons/menu.svg +13 -0
- datalab/data/icons/new_ima.svg +148 -0
- datalab/data/icons/new_sig.svg +123 -0
- datalab/data/icons/operations/abs.svg +116 -0
- datalab/data/icons/operations/arithmetic.svg +123 -0
- datalab/data/icons/operations/average.svg +124 -0
- datalab/data/icons/operations/complex_from_magnitude_phase.svg +116 -0
- datalab/data/icons/operations/complex_from_real_imag.svg +124 -0
- datalab/data/icons/operations/constant.svg +116 -0
- datalab/data/icons/operations/constant_add.svg +109 -0
- datalab/data/icons/operations/constant_divide.svg +109 -0
- datalab/data/icons/operations/constant_multiply.svg +109 -0
- datalab/data/icons/operations/constant_subtract.svg +109 -0
- datalab/data/icons/operations/convert_dtype.svg +117 -0
- datalab/data/icons/operations/convolution.svg +46 -0
- datalab/data/icons/operations/deconvolution.svg +57 -0
- datalab/data/icons/operations/derivative.svg +127 -0
- datalab/data/icons/operations/difference.svg +52 -0
- datalab/data/icons/operations/division.svg +139 -0
- datalab/data/icons/operations/exp.svg +116 -0
- datalab/data/icons/operations/flip_horizontally.svg +69 -0
- datalab/data/icons/operations/flip_vertically.svg +74 -0
- datalab/data/icons/operations/im.svg +124 -0
- datalab/data/icons/operations/integral.svg +50 -0
- datalab/data/icons/operations/inverse.svg +143 -0
- datalab/data/icons/operations/log10.svg +109 -0
- datalab/data/icons/operations/phase.svg +116 -0
- datalab/data/icons/operations/power.svg +118 -0
- datalab/data/icons/operations/product.svg +124 -0
- datalab/data/icons/operations/profile.svg +379 -0
- datalab/data/icons/operations/profile_average.svg +399 -0
- datalab/data/icons/operations/profile_radial.svg +261 -0
- datalab/data/icons/operations/profile_segment.svg +262 -0
- datalab/data/icons/operations/quadratic_difference.svg +84 -0
- datalab/data/icons/operations/re.svg +124 -0
- datalab/data/icons/operations/rotate_left.svg +72 -0
- datalab/data/icons/operations/rotate_right.svg +72 -0
- datalab/data/icons/operations/signals_to_image.svg +314 -0
- datalab/data/icons/operations/sqrt.svg +110 -0
- datalab/data/icons/operations/std.svg +124 -0
- datalab/data/icons/operations/sum.svg +102 -0
- datalab/data/icons/play_demo.svg +9 -0
- datalab/data/icons/processing/axis_transform.svg +62 -0
- datalab/data/icons/processing/bandpass.svg +79 -0
- datalab/data/icons/processing/bandstop.svg +71 -0
- datalab/data/icons/processing/binning.svg +126 -0
- datalab/data/icons/processing/clip.svg +119 -0
- datalab/data/icons/processing/detrending.svg +173 -0
- datalab/data/icons/processing/distribute_on_grid.svg +769 -0
- datalab/data/icons/processing/edge_detection.svg +46 -0
- datalab/data/icons/processing/erase.svg +1 -0
- datalab/data/icons/processing/exposure.svg +143 -0
- datalab/data/icons/processing/fourier.svg +104 -0
- datalab/data/icons/processing/highpass.svg +59 -0
- datalab/data/icons/processing/interpolation.svg +71 -0
- datalab/data/icons/processing/level_adjustment.svg +70 -0
- datalab/data/icons/processing/lowpass.svg +60 -0
- datalab/data/icons/processing/morphology.svg +49 -0
- datalab/data/icons/processing/noise_addition.svg +114 -0
- datalab/data/icons/processing/noise_reduction.svg +38 -0
- datalab/data/icons/processing/normalize.svg +84 -0
- datalab/data/icons/processing/offset_correction.svg +131 -0
- datalab/data/icons/processing/resampling1d.svg +101 -0
- datalab/data/icons/processing/resampling2d.svg +240 -0
- datalab/data/icons/processing/reset_positions.svg +185 -0
- datalab/data/icons/processing/resize.svg +9 -0
- datalab/data/icons/processing/reverse_signal_x.svg +171 -0
- datalab/data/icons/processing/stability.svg +11 -0
- datalab/data/icons/processing/swap_x_y.svg +65 -0
- datalab/data/icons/processing/thresholding.svg +63 -0
- datalab/data/icons/processing/windowing.svg +45 -0
- datalab/data/icons/properties.svg +26 -0
- datalab/data/icons/reset.svg +9 -0
- datalab/data/icons/restore.svg +40 -0
- datalab/data/icons/roi/roi.svg +76 -0
- datalab/data/icons/roi/roi_coordinate.svg +78 -0
- datalab/data/icons/roi/roi_copy.svg +112 -0
- datalab/data/icons/roi/roi_delete.svg +81 -0
- datalab/data/icons/roi/roi_export.svg +87 -0
- datalab/data/icons/roi/roi_graphical.svg +78 -0
- datalab/data/icons/roi/roi_grid.svg +67 -0
- datalab/data/icons/roi/roi_ima.svg +188 -0
- datalab/data/icons/roi/roi_import.svg +87 -0
- datalab/data/icons/roi/roi_new.svg +81 -0
- datalab/data/icons/roi/roi_new_circle.svg +95 -0
- datalab/data/icons/roi/roi_new_polygon.svg +110 -0
- datalab/data/icons/roi/roi_new_rectangle.svg +70 -0
- datalab/data/icons/roi/roi_paste.svg +98 -0
- datalab/data/icons/roi/roi_sig.svg +124 -0
- datalab/data/icons/shapes.svg +134 -0
- datalab/data/icons/signal.svg +103 -0
- datalab/data/icons/table.svg +85 -0
- datalab/data/icons/table_unavailable.svg +102 -0
- datalab/data/icons/to_signal.svg +124 -0
- datalab/data/icons/tour/next.svg +44 -0
- datalab/data/icons/tour/previous.svg +44 -0
- datalab/data/icons/tour/rewind.svg +51 -0
- datalab/data/icons/tour/stop.svg +47 -0
- datalab/data/icons/tour/tour.svg +16 -0
- datalab/data/icons/uncheck_all.svg +78 -0
- datalab/data/icons/view/curve_antialiasing.svg +50 -0
- datalab/data/icons/view/new_window.svg +98 -0
- datalab/data/icons/view/refresh-auto.svg +57 -0
- datalab/data/icons/view/refresh-manual.svg +51 -0
- datalab/data/icons/view/reset_curve_styles.svg +96 -0
- datalab/data/icons/view/show_first.svg +55 -0
- datalab/data/icons/view/show_titles.svg +46 -0
- datalab/data/icons/visualization.svg +51 -0
- datalab/data/logo/DataLab-Banner-150.png +0 -0
- datalab/data/logo/DataLab-Banner-200.png +0 -0
- datalab/data/logo/DataLab-Banner2-100.png +0 -0
- datalab/data/logo/DataLab-Splash.png +0 -0
- datalab/data/logo/DataLab-watermark.png +0 -0
- datalab/data/logo/DataLab.svg +83 -0
- datalab/data/tests/reordering_test.h5 +0 -0
- datalab/data/tutorials/fabry_perot/fabry-perot1.jpg +0 -0
- datalab/data/tutorials/fabry_perot/fabry-perot2.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_13.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_18.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_23.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_30.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_35.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_40.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_45.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_50.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_55.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_60.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_65.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_70.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_75.jpg +0 -0
- datalab/data/tutorials/laser_beam/TEM00_z_80.jpg +0 -0
- datalab/env.py +542 -0
- datalab/gui/__init__.py +89 -0
- datalab/gui/actionhandler.py +1701 -0
- datalab/gui/docks.py +473 -0
- datalab/gui/h5io.py +150 -0
- datalab/gui/macroeditor.py +310 -0
- datalab/gui/main.py +2081 -0
- datalab/gui/newobject.py +217 -0
- datalab/gui/objectview.py +766 -0
- datalab/gui/panel/__init__.py +48 -0
- datalab/gui/panel/base.py +3254 -0
- datalab/gui/panel/image.py +157 -0
- datalab/gui/panel/macro.py +607 -0
- datalab/gui/panel/signal.py +164 -0
- datalab/gui/plothandler.py +800 -0
- datalab/gui/processor/__init__.py +84 -0
- datalab/gui/processor/base.py +2456 -0
- datalab/gui/processor/catcher.py +75 -0
- datalab/gui/processor/image.py +1214 -0
- datalab/gui/processor/signal.py +755 -0
- datalab/gui/profiledialog.py +333 -0
- datalab/gui/roieditor.py +633 -0
- datalab/gui/roigrideditor.py +208 -0
- datalab/gui/settings.py +612 -0
- datalab/gui/tour.py +908 -0
- datalab/h5/__init__.py +12 -0
- datalab/h5/common.py +314 -0
- datalab/h5/generic.py +580 -0
- datalab/h5/native.py +39 -0
- datalab/h5/utils.py +95 -0
- datalab/objectmodel.py +640 -0
- datalab/plugins/_readme_.txt +9 -0
- datalab/plugins/datalab_imageformats.py +175 -0
- datalab/plugins/datalab_testdata.py +190 -0
- datalab/plugins.py +355 -0
- datalab/tests/__init__.py +199 -0
- datalab/tests/backbone/__init__.py +1 -0
- datalab/tests/backbone/config_unit_test.py +170 -0
- datalab/tests/backbone/config_versioning_unit_test.py +34 -0
- datalab/tests/backbone/dictlistserial_app_test.py +38 -0
- datalab/tests/backbone/errorcatcher_unit_test.py +69 -0
- datalab/tests/backbone/errormsgbox_unit_test.py +50 -0
- datalab/tests/backbone/execenv_unit.py +262 -0
- datalab/tests/backbone/loadtest_gdi.py +147 -0
- datalab/tests/backbone/long_callback.py +96 -0
- datalab/tests/backbone/main_app_test.py +137 -0
- datalab/tests/backbone/memory_leak.py +43 -0
- datalab/tests/backbone/procisolation1_unit.py +128 -0
- datalab/tests/backbone/procisolation2_unit.py +171 -0
- datalab/tests/backbone/procisolation_unit_test.py +22 -0
- datalab/tests/backbone/profiling_app.py +27 -0
- datalab/tests/backbone/strings_unit_test.py +65 -0
- datalab/tests/backbone/title_formatting_unit_test.py +82 -0
- datalab/tests/conftest.py +131 -0
- datalab/tests/features/__init__.py +1 -0
- datalab/tests/features/applauncher/__init__.py +1 -0
- datalab/tests/features/applauncher/launcher1_app_test.py +28 -0
- datalab/tests/features/applauncher/launcher2_app_test.py +30 -0
- datalab/tests/features/common/__init__.py +1 -0
- datalab/tests/features/common/add_metadata_app_test.py +134 -0
- datalab/tests/features/common/add_metadata_unit_test.py +267 -0
- datalab/tests/features/common/annotations_management_unit_test.py +152 -0
- datalab/tests/features/common/auto_analysis_recompute_unit_test.py +240 -0
- datalab/tests/features/common/createobject_unit_test.py +50 -0
- datalab/tests/features/common/geometry_results_app_test.py +135 -0
- datalab/tests/features/common/interactive_processing_test.py +1109 -0
- datalab/tests/features/common/io_app_test.py +75 -0
- datalab/tests/features/common/large_results_app_test.py +187 -0
- datalab/tests/features/common/metadata_all_patterns_test.py +103 -0
- datalab/tests/features/common/metadata_app_test.py +139 -0
- datalab/tests/features/common/metadata_io_unit_test.py +60 -0
- datalab/tests/features/common/misc_app_test.py +236 -0
- datalab/tests/features/common/multiple_geometry_results_unit_test.py +122 -0
- datalab/tests/features/common/multiple_table_results_unit_test.py +64 -0
- datalab/tests/features/common/operation_modes_app_test.py +392 -0
- datalab/tests/features/common/plot_results_app_test.py +278 -0
- datalab/tests/features/common/reorder_app_test.py +75 -0
- datalab/tests/features/common/result_deletion_unit_test.py +96 -0
- datalab/tests/features/common/result_merged_label_unit_test.py +154 -0
- datalab/tests/features/common/result_shape_settings_unit_test.py +223 -0
- datalab/tests/features/common/roi_plotitem_unit_test.py +64 -0
- datalab/tests/features/common/roieditor_unit_test.py +102 -0
- datalab/tests/features/common/save_to_dir_app_test.py +163 -0
- datalab/tests/features/common/save_to_dir_unit_test.py +474 -0
- datalab/tests/features/common/stat_app_test.py +40 -0
- datalab/tests/features/common/stats_tools_unit_test.py +77 -0
- datalab/tests/features/common/table_results_app_test.py +52 -0
- datalab/tests/features/common/textimport_unit_test.py +131 -0
- datalab/tests/features/common/uuid_preservation_test.py +281 -0
- datalab/tests/features/common/worker_unit_test.py +402 -0
- datalab/tests/features/control/__init__.py +1 -0
- datalab/tests/features/control/connect_dialog.py +28 -0
- datalab/tests/features/control/embedded1_unit_test.py +304 -0
- datalab/tests/features/control/embedded2_unit_test.py +52 -0
- datalab/tests/features/control/remoteclient_app_test.py +219 -0
- datalab/tests/features/control/remoteclient_unit.py +75 -0
- datalab/tests/features/control/simpleclient_unit_test.py +321 -0
- datalab/tests/features/hdf5/__init__.py +1 -0
- datalab/tests/features/hdf5/h5browser1_unit_test.py +31 -0
- datalab/tests/features/hdf5/h5browser2_unit.py +55 -0
- datalab/tests/features/hdf5/h5browser_app_test.py +77 -0
- datalab/tests/features/hdf5/h5import_app_test.py +25 -0
- datalab/tests/features/hdf5/h5importer_app_test.py +34 -0
- datalab/tests/features/image/__init__.py +1 -0
- datalab/tests/features/image/annotations_app_test.py +28 -0
- datalab/tests/features/image/annotations_unit_test.py +80 -0
- datalab/tests/features/image/average_app_test.py +46 -0
- datalab/tests/features/image/background_dialog_test.py +70 -0
- datalab/tests/features/image/blobs_app_test.py +50 -0
- datalab/tests/features/image/contour_app_test.py +42 -0
- datalab/tests/features/image/contour_fabryperot_app_test.py +51 -0
- datalab/tests/features/image/denoise_app_test.py +31 -0
- datalab/tests/features/image/distribute_on_grid_app_test.py +95 -0
- datalab/tests/features/image/edges_app_test.py +31 -0
- datalab/tests/features/image/erase_app_test.py +21 -0
- datalab/tests/features/image/fft2d_app_test.py +27 -0
- datalab/tests/features/image/flatfield_app_test.py +40 -0
- datalab/tests/features/image/geometry_transform_unit_test.py +396 -0
- datalab/tests/features/image/imagetools_app_test.py +51 -0
- datalab/tests/features/image/imagetools_unit_test.py +27 -0
- datalab/tests/features/image/load_app_test.py +73 -0
- datalab/tests/features/image/morph_app_test.py +32 -0
- datalab/tests/features/image/offsetcorrection_app_test.py +30 -0
- datalab/tests/features/image/peak2d_app_test.py +53 -0
- datalab/tests/features/image/profile_app_test.py +73 -0
- datalab/tests/features/image/profile_dialog_test.py +56 -0
- datalab/tests/features/image/roi_app_test.py +98 -0
- datalab/tests/features/image/roi_circ_app_test.py +62 -0
- datalab/tests/features/image/roi_manipulation_app_test.py +268 -0
- datalab/tests/features/image/roigrid_unit_test.py +60 -0
- datalab/tests/features/image/side_by_side_app_test.py +52 -0
- datalab/tests/features/macro/__init__.py +1 -0
- datalab/tests/features/macro/macro_app_test.py +28 -0
- datalab/tests/features/macro/macroeditor_unit_test.py +102 -0
- datalab/tests/features/signal/__init__.py +1 -0
- datalab/tests/features/signal/baseline_dialog_test.py +53 -0
- datalab/tests/features/signal/deltax_dialog_unit_test.py +34 -0
- datalab/tests/features/signal/fft1d_app_test.py +26 -0
- datalab/tests/features/signal/filter_app_test.py +44 -0
- datalab/tests/features/signal/fitdialog_unit_test.py +50 -0
- datalab/tests/features/signal/interpolation_app_test.py +110 -0
- datalab/tests/features/signal/loadbigsignal_app_test.py +80 -0
- datalab/tests/features/signal/multiple_rois_unit_test.py +132 -0
- datalab/tests/features/signal/pulse_features_app_test.py +118 -0
- datalab/tests/features/signal/pulse_features_roi_app_test.py +55 -0
- datalab/tests/features/signal/roi_app_test.py +78 -0
- datalab/tests/features/signal/roi_manipulation_app_test.py +261 -0
- datalab/tests/features/signal/select_xy_cursor_unit_test.py +46 -0
- datalab/tests/features/signal/signalpeakdetection_dialog_test.py +33 -0
- datalab/tests/features/signal/signals_to_image_app_test.py +98 -0
- datalab/tests/features/signal/xarray_compat_app_test.py +128 -0
- datalab/tests/features/tour_unit_test.py +22 -0
- datalab/tests/features/utilities/__init__.py +1 -0
- datalab/tests/features/utilities/installconf_unit_test.py +21 -0
- datalab/tests/features/utilities/logview_app_test.py +21 -0
- datalab/tests/features/utilities/logview_error.py +24 -0
- datalab/tests/features/utilities/logview_unit_test.py +21 -0
- datalab/tests/features/utilities/memstatus_app_test.py +42 -0
- datalab/tests/features/utilities/settings_unit_test.py +88 -0
- datalab/tests/scenarios/__init__.py +1 -0
- datalab/tests/scenarios/beautiful_app.py +121 -0
- datalab/tests/scenarios/common.py +463 -0
- datalab/tests/scenarios/demo.py +212 -0
- datalab/tests/scenarios/example_app_test.py +47 -0
- datalab/tests/scenarios/scenario_h5_app_test.py +75 -0
- datalab/tests/scenarios/scenario_ima1_app_test.py +34 -0
- datalab/tests/scenarios/scenario_ima2_app_test.py +34 -0
- datalab/tests/scenarios/scenario_mac_app_test.py +58 -0
- datalab/tests/scenarios/scenario_sig1_app_test.py +36 -0
- datalab/tests/scenarios/scenario_sig2_app_test.py +35 -0
- datalab/utils/__init__.py +1 -0
- datalab/utils/conf.py +304 -0
- datalab/utils/dephash.py +105 -0
- datalab/utils/qthelpers.py +633 -0
- datalab/utils/strings.py +34 -0
- datalab/utils/tests.py +0 -0
- datalab/widgets/__init__.py +1 -0
- datalab/widgets/connection.py +138 -0
- datalab/widgets/filedialog.py +91 -0
- datalab/widgets/fileviewer.py +84 -0
- datalab/widgets/fitdialog.py +788 -0
- datalab/widgets/h5browser.py +1048 -0
- datalab/widgets/imagebackground.py +111 -0
- datalab/widgets/instconfviewer.py +175 -0
- datalab/widgets/logviewer.py +80 -0
- datalab/widgets/signalbaseline.py +90 -0
- datalab/widgets/signalcursor.py +208 -0
- datalab/widgets/signaldeltax.py +151 -0
- datalab/widgets/signalpeak.py +199 -0
- datalab/widgets/status.py +249 -0
- datalab/widgets/textimport.py +786 -0
- datalab/widgets/warningerror.py +223 -0
- datalab/widgets/wizard.py +286 -0
- datalab_platform-1.0.1.dist-info/METADATA +121 -0
- datalab_platform-1.0.1.dist-info/RECORD +494 -0
- datalab_platform-0.0.1.dev0.dist-info/METADATA +0 -67
- datalab_platform-0.0.1.dev0.dist-info/RECORD +0 -7
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/WHEEL +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/entry_points.txt +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/licenses/LICENSE +0 -0
- {datalab_platform-0.0.1.dev0.dist-info → datalab_platform-1.0.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Worker and WorkerStateMachine Unit Tests
|
|
5
|
+
========================================
|
|
6
|
+
|
|
7
|
+
This module contains comprehensive unit tests for the Worker class and
|
|
8
|
+
WorkerStateMachine class in DataLab's processor module.
|
|
9
|
+
|
|
10
|
+
Tests cover:
|
|
11
|
+
1. State machine functionality independently from Worker class
|
|
12
|
+
2. Worker class nominal operations
|
|
13
|
+
3. Exception handling in computations
|
|
14
|
+
4. Process pool restart mechanism for long-running/cancelled computations
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
# pylint: disable=protected-access
|
|
18
|
+
|
|
19
|
+
import time
|
|
20
|
+
from unittest.mock import Mock, patch
|
|
21
|
+
|
|
22
|
+
import pytest
|
|
23
|
+
from guidata.qthelpers import qt_app_context
|
|
24
|
+
from qtpy import QtWidgets as QW
|
|
25
|
+
|
|
26
|
+
import datalab.gui.processor.base as base_module
|
|
27
|
+
from datalab.gui.processor.base import Worker, WorkerState, WorkerStateMachine
|
|
28
|
+
from datalab.gui.processor.catcher import CompOut
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class TestWorkerStateMachine:
|
|
32
|
+
"""Test suite for WorkerStateMachine class - independent from Worker class."""
|
|
33
|
+
|
|
34
|
+
def test_initial_state(self):
|
|
35
|
+
"""Test that state machine starts in IDLE state."""
|
|
36
|
+
sm = WorkerStateMachine()
|
|
37
|
+
assert sm.current_state == WorkerState.IDLE
|
|
38
|
+
|
|
39
|
+
def test_valid_transitions(self):
|
|
40
|
+
"""Test all valid state transitions."""
|
|
41
|
+
sm = WorkerStateMachine()
|
|
42
|
+
|
|
43
|
+
# IDLE -> STARTING
|
|
44
|
+
sm.transition_to(WorkerState.STARTING)
|
|
45
|
+
assert sm.current_state == WorkerState.STARTING
|
|
46
|
+
|
|
47
|
+
# STARTING -> RUNNING
|
|
48
|
+
sm.transition_to(WorkerState.RUNNING)
|
|
49
|
+
assert sm.current_state == WorkerState.RUNNING
|
|
50
|
+
|
|
51
|
+
# RUNNING -> FINISHED
|
|
52
|
+
sm.transition_to(WorkerState.FINISHED)
|
|
53
|
+
assert sm.current_state == WorkerState.FINISHED
|
|
54
|
+
|
|
55
|
+
# FINISHED -> IDLE (complete cycle)
|
|
56
|
+
sm.transition_to(WorkerState.IDLE)
|
|
57
|
+
assert sm.current_state == WorkerState.IDLE
|
|
58
|
+
|
|
59
|
+
def test_same_state_transition_allowed(self):
|
|
60
|
+
"""Test that transitioning to the same state is a no-op."""
|
|
61
|
+
sm = WorkerStateMachine()
|
|
62
|
+
|
|
63
|
+
# Should not raise exception
|
|
64
|
+
sm.transition_to(WorkerState.IDLE)
|
|
65
|
+
assert sm.current_state == WorkerState.IDLE
|
|
66
|
+
|
|
67
|
+
# Same for other states
|
|
68
|
+
sm.transition_to(WorkerState.STARTING)
|
|
69
|
+
sm.transition_to(WorkerState.STARTING)
|
|
70
|
+
assert sm.current_state == WorkerState.STARTING
|
|
71
|
+
|
|
72
|
+
def test_invalid_transitions(self):
|
|
73
|
+
"""Test that invalid transitions raise ValueError."""
|
|
74
|
+
sm = WorkerStateMachine()
|
|
75
|
+
|
|
76
|
+
# IDLE can only go to STARTING
|
|
77
|
+
with pytest.raises(
|
|
78
|
+
ValueError,
|
|
79
|
+
match="Invalid transition from WorkerState.IDLE to WorkerState.RUNNING",
|
|
80
|
+
):
|
|
81
|
+
sm.transition_to(WorkerState.RUNNING)
|
|
82
|
+
|
|
83
|
+
with pytest.raises(
|
|
84
|
+
ValueError,
|
|
85
|
+
match="Invalid transition from WorkerState.IDLE to WorkerState.FINISHED",
|
|
86
|
+
):
|
|
87
|
+
sm.transition_to(WorkerState.FINISHED)
|
|
88
|
+
|
|
89
|
+
# STARTING can only go to RUNNING
|
|
90
|
+
sm.transition_to(WorkerState.STARTING)
|
|
91
|
+
with pytest.raises(
|
|
92
|
+
ValueError,
|
|
93
|
+
match="Invalid transition from WorkerState.STARTING to WorkerState.IDLE",
|
|
94
|
+
):
|
|
95
|
+
sm.transition_to(WorkerState.IDLE)
|
|
96
|
+
|
|
97
|
+
with pytest.raises(ValueError, match="Invalid transition.*STARTING.*FINISHED"):
|
|
98
|
+
sm.transition_to(WorkerState.FINISHED)
|
|
99
|
+
|
|
100
|
+
def test_reset_to_idle_from_any_state(self):
|
|
101
|
+
"""Test that reset_to_idle works from any state."""
|
|
102
|
+
sm = WorkerStateMachine()
|
|
103
|
+
|
|
104
|
+
# Test from each state
|
|
105
|
+
states_to_test = [
|
|
106
|
+
WorkerState.IDLE,
|
|
107
|
+
WorkerState.STARTING,
|
|
108
|
+
WorkerState.RUNNING,
|
|
109
|
+
WorkerState.FINISHED,
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
for state in states_to_test:
|
|
113
|
+
# Force state (bypassing transition validation for test)
|
|
114
|
+
sm._current_state = state
|
|
115
|
+
sm.reset_to_idle()
|
|
116
|
+
assert sm.current_state == WorkerState.IDLE
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# Module-level functions for pickle compatibility in multiprocessing
|
|
120
|
+
def dummy_successful_computation(x: int, y: int) -> int:
|
|
121
|
+
"""Simple computation that returns sum of two numbers."""
|
|
122
|
+
return x + y
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def dummy_failing_computation() -> None:
|
|
126
|
+
"""Computation that raises an exception."""
|
|
127
|
+
raise ValueError("Test exception from computation")
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def dummy_infinite_computation() -> None:
|
|
131
|
+
"""Computation that runs forever (until process is killed)."""
|
|
132
|
+
while True:
|
|
133
|
+
time.sleep(0.1) # Simulate work
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class TestWorker:
|
|
137
|
+
"""Test suite for Worker class functionality."""
|
|
138
|
+
|
|
139
|
+
def setup_method(self):
|
|
140
|
+
"""Setup for each test method - ensure clean pool state."""
|
|
141
|
+
# Clean up any existing pool
|
|
142
|
+
Worker.terminate_pool(wait=False)
|
|
143
|
+
Worker.create_pool()
|
|
144
|
+
|
|
145
|
+
def teardown_method(self):
|
|
146
|
+
"""Cleanup after each test method."""
|
|
147
|
+
# Clean up pool to avoid interference between tests
|
|
148
|
+
Worker.terminate_pool(wait=False)
|
|
149
|
+
|
|
150
|
+
def test_worker_initial_state(self):
|
|
151
|
+
"""Test worker starts in correct initial state."""
|
|
152
|
+
worker = Worker()
|
|
153
|
+
assert worker.state_machine.current_state == WorkerState.IDLE
|
|
154
|
+
assert worker.asyncresult is None
|
|
155
|
+
|
|
156
|
+
def test_worker_pool_management(self):
|
|
157
|
+
"""Test pool creation and termination."""
|
|
158
|
+
# Test static methods work
|
|
159
|
+
Worker.terminate_pool()
|
|
160
|
+
Worker.create_pool()
|
|
161
|
+
|
|
162
|
+
# Verify pool exists by checking global POOL variable
|
|
163
|
+
assert base_module.POOL is not None
|
|
164
|
+
|
|
165
|
+
# Test termination
|
|
166
|
+
Worker.terminate_pool()
|
|
167
|
+
# Note: POOL global variable is set to None in terminate_pool
|
|
168
|
+
|
|
169
|
+
def test_nominal_computation_case(self):
|
|
170
|
+
"""Test Case 2a: Nominal case - start computation, wait, get result."""
|
|
171
|
+
with qt_app_context():
|
|
172
|
+
worker = Worker()
|
|
173
|
+
|
|
174
|
+
# Start computation
|
|
175
|
+
worker.run(dummy_successful_computation, (10, 5))
|
|
176
|
+
assert worker.state_machine.current_state == WorkerState.RUNNING
|
|
177
|
+
|
|
178
|
+
# Wait for completion
|
|
179
|
+
while not worker.is_computation_finished():
|
|
180
|
+
QW.QApplication.processEvents()
|
|
181
|
+
time.sleep(0.001) # Small sleep to avoid busy waiting
|
|
182
|
+
|
|
183
|
+
# Should be finished
|
|
184
|
+
assert worker.state_machine.current_state == WorkerState.FINISHED
|
|
185
|
+
assert worker.has_result_available()
|
|
186
|
+
|
|
187
|
+
# Get result
|
|
188
|
+
result = worker.get_result()
|
|
189
|
+
assert isinstance(result, CompOut)
|
|
190
|
+
assert result.result == 15 # 10 + 5
|
|
191
|
+
assert result.error_msg is None
|
|
192
|
+
assert worker.state_machine.current_state == WorkerState.IDLE
|
|
193
|
+
|
|
194
|
+
def test_computation_exception_case(self):
|
|
195
|
+
"""Test Case 2b: Computation raises an exception."""
|
|
196
|
+
# Note: In unattended test mode, exceptions are re-raised by wng_err_func
|
|
197
|
+
# This test validates that the worker can handle exceptions that bubble up
|
|
198
|
+
with qt_app_context():
|
|
199
|
+
worker = Worker()
|
|
200
|
+
|
|
201
|
+
# Start computation that will fail
|
|
202
|
+
worker.run(dummy_failing_computation, ())
|
|
203
|
+
assert worker.state_machine.current_state == WorkerState.RUNNING
|
|
204
|
+
|
|
205
|
+
# In unattended mode, the exception will be raised when getting result
|
|
206
|
+
# Wait for computation to "complete" (which means ready to raise exception)
|
|
207
|
+
while not worker.is_computation_finished():
|
|
208
|
+
QW.QApplication.processEvents()
|
|
209
|
+
time.sleep(0.001)
|
|
210
|
+
|
|
211
|
+
# Should be marked as finished (even though it will raise on get_result)
|
|
212
|
+
assert worker.state_machine.current_state == WorkerState.FINISHED
|
|
213
|
+
assert worker.has_result_available()
|
|
214
|
+
|
|
215
|
+
# In unattended mode, get_result will raise the original exception
|
|
216
|
+
with pytest.raises(ValueError, match="Test exception from computation"):
|
|
217
|
+
worker.get_result()
|
|
218
|
+
|
|
219
|
+
# After exception, should still be back to IDLE (cleanup happened)
|
|
220
|
+
assert worker.state_machine.current_state == WorkerState.IDLE
|
|
221
|
+
|
|
222
|
+
def test_computation_cancellation_and_pool_restart(self):
|
|
223
|
+
"""Test Case 2c: Long computation with cancellation and pool restart."""
|
|
224
|
+
with qt_app_context():
|
|
225
|
+
worker = Worker()
|
|
226
|
+
|
|
227
|
+
# Start infinite computation
|
|
228
|
+
worker.run(dummy_infinite_computation, ())
|
|
229
|
+
assert worker.state_machine.current_state == WorkerState.RUNNING
|
|
230
|
+
|
|
231
|
+
# Let it run briefly to ensure it's actually started
|
|
232
|
+
start_time = time.time()
|
|
233
|
+
while time.time() - start_time < 0.1: # 100ms
|
|
234
|
+
QW.QApplication.processEvents()
|
|
235
|
+
time.sleep(0.001)
|
|
236
|
+
# Verify it's still running (not finished)
|
|
237
|
+
if worker.is_computation_finished():
|
|
238
|
+
pytest.fail("Infinite computation finished unexpectedly")
|
|
239
|
+
|
|
240
|
+
# Simulate user cancellation (like progress dialog cancel)
|
|
241
|
+
worker.restart()
|
|
242
|
+
assert worker.state_machine.current_state == WorkerState.IDLE
|
|
243
|
+
assert worker.asyncresult is None
|
|
244
|
+
|
|
245
|
+
# Verify pool was restarted by running a normal computation
|
|
246
|
+
worker.run(dummy_successful_computation, (20, 22))
|
|
247
|
+
assert worker.state_machine.current_state == WorkerState.RUNNING
|
|
248
|
+
|
|
249
|
+
# Wait for this computation to complete
|
|
250
|
+
while not worker.is_computation_finished():
|
|
251
|
+
QW.QApplication.processEvents()
|
|
252
|
+
time.sleep(0.001)
|
|
253
|
+
|
|
254
|
+
# Should complete successfully, proving pool restart worked
|
|
255
|
+
assert worker.state_machine.current_state == WorkerState.FINISHED
|
|
256
|
+
result = worker.get_result()
|
|
257
|
+
assert result.result == 42 # 20 + 22
|
|
258
|
+
assert result.error_msg is None
|
|
259
|
+
|
|
260
|
+
def test_worker_restart_from_various_states(self):
|
|
261
|
+
"""Test worker.restart() behavior from different states."""
|
|
262
|
+
with qt_app_context():
|
|
263
|
+
worker = Worker()
|
|
264
|
+
|
|
265
|
+
# Test restart from IDLE (should be no-op)
|
|
266
|
+
assert worker.state_machine.current_state == WorkerState.IDLE
|
|
267
|
+
worker.restart()
|
|
268
|
+
assert worker.state_machine.current_state == WorkerState.IDLE
|
|
269
|
+
|
|
270
|
+
# Test restart from STARTING state
|
|
271
|
+
with patch.object(worker.state_machine, "transition_to"):
|
|
272
|
+
# Force STARTING state
|
|
273
|
+
worker.state_machine._current_state = WorkerState.STARTING
|
|
274
|
+
worker.asyncresult = Mock() # Simulate asyncresult exists
|
|
275
|
+
|
|
276
|
+
worker.restart()
|
|
277
|
+
|
|
278
|
+
assert worker.asyncresult is None
|
|
279
|
+
assert worker.state_machine.current_state == WorkerState.IDLE
|
|
280
|
+
|
|
281
|
+
# Test restart from FINISHED state
|
|
282
|
+
worker.state_machine._current_state = WorkerState.FINISHED
|
|
283
|
+
worker.asyncresult = Mock()
|
|
284
|
+
|
|
285
|
+
worker.restart()
|
|
286
|
+
assert worker.asyncresult is None
|
|
287
|
+
assert worker.state_machine.current_state == WorkerState.IDLE
|
|
288
|
+
|
|
289
|
+
def test_worker_close(self):
|
|
290
|
+
"""Test worker.close() method."""
|
|
291
|
+
worker = Worker()
|
|
292
|
+
|
|
293
|
+
# Test close with no active computation
|
|
294
|
+
worker.close() # Should not raise
|
|
295
|
+
|
|
296
|
+
# Test close with active computation (simulate)
|
|
297
|
+
worker.asyncresult = Mock()
|
|
298
|
+
worker.close() # Should not raise
|
|
299
|
+
|
|
300
|
+
def test_error_conditions(self):
|
|
301
|
+
"""Test various error conditions."""
|
|
302
|
+
worker = Worker()
|
|
303
|
+
|
|
304
|
+
# Test starting computation when not in IDLE state
|
|
305
|
+
worker.state_machine._current_state = WorkerState.RUNNING
|
|
306
|
+
with pytest.raises(
|
|
307
|
+
ValueError, match="Cannot start computation from WorkerState.RUNNING state"
|
|
308
|
+
):
|
|
309
|
+
worker.run(dummy_successful_computation, (1, 2))
|
|
310
|
+
|
|
311
|
+
# Reset to proper state
|
|
312
|
+
worker.state_machine.reset_to_idle()
|
|
313
|
+
|
|
314
|
+
# Test getting result when not in FINISHED state
|
|
315
|
+
with pytest.raises(
|
|
316
|
+
ValueError, match="Cannot get result from WorkerState.IDLE state"
|
|
317
|
+
):
|
|
318
|
+
worker.get_result()
|
|
319
|
+
|
|
320
|
+
# Test has_result_available in various states
|
|
321
|
+
assert not worker.has_result_available() # IDLE
|
|
322
|
+
|
|
323
|
+
worker.state_machine._current_state = WorkerState.RUNNING
|
|
324
|
+
assert not worker.has_result_available() # RUNNING
|
|
325
|
+
|
|
326
|
+
worker.state_machine._current_state = WorkerState.FINISHED
|
|
327
|
+
assert worker.has_result_available() # FINISHED
|
|
328
|
+
|
|
329
|
+
def test_restart_pool_method_integration(self):
|
|
330
|
+
"""Test that restart_pool is properly integrated with restart method."""
|
|
331
|
+
with qt_app_context():
|
|
332
|
+
worker = Worker()
|
|
333
|
+
|
|
334
|
+
# Start an infinite computation
|
|
335
|
+
worker.run(dummy_infinite_computation, ())
|
|
336
|
+
|
|
337
|
+
# Let it run briefly
|
|
338
|
+
start_time = time.time()
|
|
339
|
+
while time.time() - start_time < 0.05: # 50ms
|
|
340
|
+
QW.QApplication.processEvents()
|
|
341
|
+
time.sleep(0.001)
|
|
342
|
+
|
|
343
|
+
# Force RUNNING state and call restart (which should use restart_pool)
|
|
344
|
+
assert worker.state_machine.current_state == WorkerState.RUNNING
|
|
345
|
+
worker.restart()
|
|
346
|
+
|
|
347
|
+
# Should be back to IDLE
|
|
348
|
+
assert worker.state_machine.current_state == WorkerState.IDLE
|
|
349
|
+
|
|
350
|
+
# Pool should be functional - test with a simple computation
|
|
351
|
+
worker.run(dummy_successful_computation, (100, 200))
|
|
352
|
+
while not worker.is_computation_finished():
|
|
353
|
+
QW.QApplication.processEvents()
|
|
354
|
+
time.sleep(0.001)
|
|
355
|
+
|
|
356
|
+
result = worker.get_result()
|
|
357
|
+
assert result.result == 300
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
# Module-level function for pickle compatibility
|
|
361
|
+
def simple_multiplication(a: int, b: int) -> int:
|
|
362
|
+
"""Simple computation that multiplies two numbers."""
|
|
363
|
+
return a * b
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def test_worker_and_state_machine_integration():
|
|
367
|
+
"""Integration test ensuring Worker and WorkerStateMachine work together."""
|
|
368
|
+
with qt_app_context():
|
|
369
|
+
# Ensure clean pool
|
|
370
|
+
Worker.terminate_pool(wait=False)
|
|
371
|
+
Worker.create_pool()
|
|
372
|
+
|
|
373
|
+
try:
|
|
374
|
+
worker = Worker()
|
|
375
|
+
|
|
376
|
+
# Test complete workflow
|
|
377
|
+
assert worker.state_machine.current_state == WorkerState.IDLE
|
|
378
|
+
|
|
379
|
+
# Start computation
|
|
380
|
+
worker.run(simple_multiplication, (6, 7))
|
|
381
|
+
assert worker.state_machine.current_state == WorkerState.RUNNING
|
|
382
|
+
|
|
383
|
+
# Wait and check states
|
|
384
|
+
while not worker.is_computation_finished():
|
|
385
|
+
QW.QApplication.processEvents()
|
|
386
|
+
time.sleep(0.001)
|
|
387
|
+
|
|
388
|
+
assert worker.state_machine.current_state == WorkerState.FINISHED
|
|
389
|
+
|
|
390
|
+
# Get result and verify state transition
|
|
391
|
+
result = worker.get_result()
|
|
392
|
+
assert result.result == 42 # 6 * 7
|
|
393
|
+
assert worker.state_machine.current_state == WorkerState.IDLE
|
|
394
|
+
|
|
395
|
+
finally:
|
|
396
|
+
# Cleanup
|
|
397
|
+
Worker.terminate_pool(wait=False)
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
if __name__ == "__main__":
|
|
401
|
+
# Run specific test for debugging
|
|
402
|
+
pytest.main([__file__, "-v"])
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
DataLab Remote client connection dialog example
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# guitest: show,skip
|
|
8
|
+
|
|
9
|
+
from guidata.qthelpers import qt_app_context
|
|
10
|
+
from qtpy import QtWidgets as QW
|
|
11
|
+
|
|
12
|
+
from datalab.control.proxy import RemoteProxy
|
|
13
|
+
from datalab.widgets.connection import ConnectionDialog
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_dialog():
|
|
17
|
+
"""Test connection dialog"""
|
|
18
|
+
proxy = RemoteProxy(autoconnect=False)
|
|
19
|
+
with qt_app_context():
|
|
20
|
+
dlg = ConnectionDialog(proxy.connect)
|
|
21
|
+
if dlg.exec():
|
|
22
|
+
QW.QMessageBox.information(None, "Connection", "Successfully connected")
|
|
23
|
+
else:
|
|
24
|
+
QW.QMessageBox.critical(None, "Connection", "Connection failed")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
if __name__ == "__main__":
|
|
28
|
+
test_dialog()
|