pymodaq 5.3.2__tar.gz → 5.3.4__tar.gz

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 (214) hide show
  1. {pymodaq-5.3.2 → pymodaq-5.3.4}/PKG-INFO +1 -1
  2. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/data_mixer/model.py +5 -5
  3. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/pid/utils.py +4 -6
  4. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/ramping/ramping.py +1 -2
  5. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/loader.py +1 -2
  6. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/sequencer.py +1 -2
  7. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/daq_utils.py +25 -0
  8. pymodaq-5.3.4/src/pymodaq/utils/plugin_testing/compliance_report.py +238 -0
  9. {pymodaq-5.3.2 → pymodaq-5.3.4}/.gitignore +0 -0
  10. {pymodaq-5.3.2 → pymodaq-5.3.4}/LICENSE +0 -0
  11. {pymodaq-5.3.2 → pymodaq-5.3.4}/README.rst +0 -0
  12. {pymodaq-5.3.2 → pymodaq-5.3.4}/pyproject.toml +0 -0
  13. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/__init__.py +0 -0
  14. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/__init__.py +0 -0
  15. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/control_module_selector.py +0 -0
  16. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/daq_move.py +0 -0
  17. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/daq_move_ui/__init__.py +0 -0
  18. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/daq_move_ui/factory.py +0 -0
  19. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/daq_move_ui/ui_base.py +0 -0
  20. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/daq_move_ui/uis/__init__.py +0 -0
  21. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/daq_move_ui/uis/binary.py +0 -0
  22. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/daq_move_ui/uis/relative.py +0 -0
  23. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/daq_move_ui/uis/simple.py +0 -0
  24. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/daq_move_ui/utils.py +0 -0
  25. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/daq_viewer.py +0 -0
  26. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/daq_viewer_ui/__init__.py +0 -0
  27. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/daq_viewer_ui/ui_base.py +0 -0
  28. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/daq_viewer_ui/viewer_selector.py +0 -0
  29. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/enums.py +0 -0
  30. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/instruments.py +0 -0
  31. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/mocks.py +0 -0
  32. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/move_utility_classes.py +0 -0
  33. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/plugin_base.py +0 -0
  34. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/thread_commands.py +0 -0
  35. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/ui_utils.py +0 -0
  36. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/units.py +0 -0
  37. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/utils.py +0 -0
  38. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/control_modules/viewer_utility_classes.py +0 -0
  39. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/daq_utils/__init__.py +0 -0
  40. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/daq_utils/daq_utils.py +0 -0
  41. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/dashboard.py +0 -0
  42. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/examples/__init__.py +0 -0
  43. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/examples/qt_less_standalone_module.py +0 -0
  44. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/examples/run_elts.py +0 -0
  45. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/__init__.py +0 -0
  46. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/adaptive_optim/__init__.py +0 -0
  47. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/adaptive_optim/adaptive_optimization.py +0 -0
  48. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/adaptive_optim/loss_function/_1d_loss_functions.py +0 -0
  49. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/adaptive_optim/loss_function/_2d_loss_functions.py +0 -0
  50. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/adaptive_optim/loss_function/__init__.py +0 -0
  51. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/adaptive_optim/loss_function/loss_factory.py +0 -0
  52. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/adaptive_optim/utils.py +0 -0
  53. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/bayesian/__init__.py +0 -0
  54. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/bayesian/acquisition/__init__.py +0 -0
  55. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/bayesian/acquisition/acquisition_function_factory.py +0 -0
  56. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/bayesian/acquisition/base_acquisition_function.py +0 -0
  57. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/bayesian/bayesian_optimization.py +0 -0
  58. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/bayesian/utils.py +0 -0
  59. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/console.py +0 -0
  60. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/custom_ext.py +0 -0
  61. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/daq_logger/__init__.py +0 -0
  62. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/daq_logger/abstract.py +0 -0
  63. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/daq_logger/daq_logger.py +0 -0
  64. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/daq_logger/daq_logger_legacy.py +0 -0
  65. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/daq_logger/db/__init__.py +0 -0
  66. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/daq_logger/db/db_logger.py +0 -0
  67. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/daq_logger/db/db_logger_models.py +0 -0
  68. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/daq_logger/h5logging.py +0 -0
  69. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/data_mixer/__init__.py +0 -0
  70. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/data_mixer/daq_0Dviewer_DataMixer.py +0 -0
  71. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/data_mixer/data_mixer.py +0 -0
  72. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/data_mixer/models/__init__.py +0 -0
  73. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/data_mixer/models/equation_model.py +0 -0
  74. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/data_mixer/models/gaussian_fit_model.py +0 -0
  75. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/data_mixer/parser.py +0 -0
  76. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/data_mixer/utils.py +0 -0
  77. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/h5browser.py +0 -0
  78. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/optimizers_base/__init__.py +0 -0
  79. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/optimizers_base/algorithm.py +0 -0
  80. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/optimizers_base/models.py +0 -0
  81. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/optimizers_base/optimizer.py +0 -0
  82. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/optimizers_base/thread_commands.py +0 -0
  83. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/optimizers_base/utils.py +0 -0
  84. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/pid/__init__.py +0 -0
  85. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/pid/actuator_controller.py +0 -0
  86. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/pid/daq_move_PID.py +0 -0
  87. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/pid/pid_controller.py +0 -0
  88. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/ramping/__init__.py +0 -0
  89. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/ramping/utilities/__init__.py +0 -0
  90. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/ramping/utilities/histograming.py +0 -0
  91. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/ramping/utilities/module_saver.py +0 -0
  92. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/ramping/utilities/ramp_generator.py +0 -0
  93. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/scan/__init__.py +0 -0
  94. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/scan/daq_scan.py +0 -0
  95. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/scan/help.md +0 -0
  96. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/scan/manager/__init__.py +0 -0
  97. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/scan/manager/scan_manager.py +0 -0
  98. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/scan/manager/subentries.py +0 -0
  99. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/__init__.py +0 -0
  100. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/models/__init__.py +0 -0
  101. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/models/false_choice_model.py +0 -0
  102. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/models/threshold_choice_model.py +0 -0
  103. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/models/true_choice_model.py +0 -0
  104. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/models/user_input_choice.py +0 -0
  105. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/__init__.py +0 -0
  106. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/choice_models/__init__.py +0 -0
  107. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/choice_models/factory.py +0 -0
  108. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/choice_models/model.py +0 -0
  109. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/element_factory.py +0 -0
  110. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/elements/__init__.py +0 -0
  111. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/elements/button.py +0 -0
  112. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/elements/choice.py +0 -0
  113. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/elements/grab.py +0 -0
  114. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/elements/move.py +0 -0
  115. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/elements/repeat.py +0 -0
  116. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/elements/root.py +0 -0
  117. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/elements/scanner.py +0 -0
  118. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/elements/sequence.py +0 -0
  119. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/elements/state.py +0 -0
  120. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/elements/wait.py +0 -0
  121. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/mocks.py +0 -0
  122. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/sequencer/__init__.py +0 -0
  123. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/sequencer/model_view.py +0 -0
  124. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/sequencer/sequence.py +0 -0
  125. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/states.py +0 -0
  126. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/utils.py +0 -0
  127. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/widget_with_toolbar.py +0 -0
  128. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/sequencer/utilities/yaml_utils.py +0 -0
  129. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/extensions/utils.py +0 -0
  130. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/icon.ico +0 -0
  131. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/launcher/__init__.py +0 -0
  132. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/launcher/launcher.py +0 -0
  133. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/post_treatment/__init__.py +0 -0
  134. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/post_treatment/load_and_plot.py +0 -0
  135. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/resources/__init__.py +0 -0
  136. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/resources/config_template.toml +0 -0
  137. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/resources/preset_default.xml +0 -0
  138. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/resources/setup_plugin.py +0 -0
  139. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/scripting/__init__.py +0 -0
  140. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/splash.png +0 -0
  141. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/__init__.py +0 -0
  142. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/array_manipulation.py +0 -0
  143. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/chrono_timer.py +0 -0
  144. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/compact_dock_manager.py +0 -0
  145. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/config.py +0 -0
  146. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/conftests.py +0 -0
  147. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/custom_ext.py +0 -0
  148. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/data.py +0 -0
  149. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/enums.py +0 -0
  150. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/exceptions.py +0 -0
  151. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/gui_utils/__init__.py +0 -0
  152. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/gui_utils/loader_utils.py +0 -0
  153. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/gui_utils/utils.py +0 -0
  154. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/gui_utils/widgets/lcd.py +0 -0
  155. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/gui_utils/widgets/window.py +0 -0
  156. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/h5modules/__init__.py +0 -0
  157. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/h5modules/module_saving.py +0 -0
  158. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/leco/__init__.py +0 -0
  159. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/leco/daq_move_LECODirector.py +0 -0
  160. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/leco/daq_xDviewer_LECODirector.py +0 -0
  161. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/leco/director_utils.py +0 -0
  162. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/leco/leco_director.py +0 -0
  163. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/leco/pymodaq_listener.py +0 -0
  164. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/leco/rpc_method_definitions.py +0 -0
  165. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/leco/utils.py +0 -0
  166. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/logger.py +0 -0
  167. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/__init__.py +0 -0
  168. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/batchscan_manager.py +0 -0
  169. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/experiment/__init__.py +0 -0
  170. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/experiment/experiment_manager.py +0 -0
  171. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/experiment/utils.py +0 -0
  172. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/extension/__init__.py +0 -0
  173. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/extension/extension_manager.py +0 -0
  174. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/modules/__init__.py +0 -0
  175. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/modules/loader.py +0 -0
  176. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/modules/module_creator.py +0 -0
  177. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/modules/module_settings_manager.py +0 -0
  178. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/modules/modules_manager.py +0 -0
  179. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/modules/utils.py +0 -0
  180. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/modules_manager.py +0 -0
  181. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/overshoot/__init__.py +0 -0
  182. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/overshoot/overshooter.py +0 -0
  183. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/overshoot/utils.py +0 -0
  184. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/remote_manager.py +0 -0
  185. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/roi_manager/__init__.py +0 -0
  186. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/roi_manager/roi_manager.py +0 -0
  187. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/roi_manager/utils.py +0 -0
  188. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/state/__init__.py +0 -0
  189. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/state/state_manager.py +0 -0
  190. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/state/subentries.py +0 -0
  191. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/managers/state/utils.py +0 -0
  192. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/math_utils.py +0 -0
  193. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/messenger.py +0 -0
  194. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/parameter/__init__.py +0 -0
  195. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/parameter/utils.py +0 -0
  196. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/plugin_testing/__init__.py +0 -0
  197. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/plugin_testing/harness.py +0 -0
  198. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/plugin_testing/package_checks.py +0 -0
  199. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/scanner/__init__.py +0 -0
  200. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/scanner/scan_config.py +0 -0
  201. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/scanner/scan_factory.py +0 -0
  202. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/scanner/scan_selector.py +0 -0
  203. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/scanner/scanner.py +0 -0
  204. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/scanner/scanners/_1d_scanners.py +0 -0
  205. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/scanner/scanners/_2d_scanners.py +0 -0
  206. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/scanner/scanners/__init__.py +0 -0
  207. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/scanner/scanners/sequential.py +0 -0
  208. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/scanner/scanners/tabular.py +0 -0
  209. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/scanner/utils.py +0 -0
  210. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/shared_ui.py +0 -0
  211. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/svg/__init__.py +0 -0
  212. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/svg/svg_renderer.py +0 -0
  213. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/svg/svg_view.py +0 -0
  214. {pymodaq-5.3.2 → pymodaq-5.3.4}/src/pymodaq/utils/svg/svg_viewer2D.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pymodaq
3
- Version: 5.3.2
3
+ Version: 5.3.4
4
4
  Summary: Modular Data Acquisition with Python
5
5
  Project-URL: Homepage, http://pymodaq.cnrs.fr
6
6
  Project-URL: Source, https://github.com/PyMoDAQ/PyMoDAQ
@@ -17,6 +17,8 @@ from pymodaq_data.data import DataToExport
17
17
  from pymodaq_gui.managers.parameter_manager import ParameterManager
18
18
  from pymodaq_gui.parameter import Parameter
19
19
 
20
+ from pymodaq.utils.daq_utils import find_model_class
21
+
20
22
 
21
23
  logger = set_logger(get_module_name(__file__))
22
24
 
@@ -90,11 +92,9 @@ def get_models(model_name=None) -> list[dict[(str, str), (str, type)]]:
90
92
  for mod in pkgutil.iter_modules([str(Path(module.__file__).parent.joinpath('models'))]):
91
93
  try:
92
94
  model_module = importlib.import_module(f'{module_name}.models.{mod.name}', module)
93
- classes = inspect.getmembers(model_module, inspect.isclass)
94
- for name, klass in classes:
95
- if klass.__base__ is DataMixerModel:
96
- models_import.append({'name': mod.name, 'module': model_module, 'class': klass})
97
- break
95
+ klass = find_model_class(model_module, DataMixerModel)
96
+ if klass is not None:
97
+ models_import.append({'name': mod.name, 'module': model_module, 'class': klass})
98
98
 
99
99
  except Exception as e: # pragma: no cover
100
100
  logger.warning(str(e))
@@ -13,7 +13,7 @@ from pymodaq_gui.utils.dock import DockArea
13
13
 
14
14
  from pymodaq_data.data import DataToExport
15
15
 
16
- from pymodaq.utils.daq_utils import get_plugins
16
+ from pymodaq.utils.daq_utils import get_plugins, find_model_class
17
17
  from pymodaq.utils.data import DataActuator, DataToActuators
18
18
 
19
19
 
@@ -165,11 +165,9 @@ def get_models(model_name=None):
165
165
  for mod in pkgutil.iter_modules([str(Path(module.__file__).parent.joinpath('models'))]):
166
166
  try:
167
167
  model_module = importlib.import_module(f'{module_name}.models.{mod.name}', module)
168
- classes = inspect.getmembers(model_module, inspect.isclass)
169
- for name, klass in classes:
170
- if klass.__base__ is PIDModelGeneric:
171
- models_import.append({'name': mod.name, 'module': model_module, 'class': klass})
172
- break
168
+ klass = find_model_class(model_module, PIDModelGeneric)
169
+ if klass is not None:
170
+ models_import.append({'name': mod.name, 'module': model_module, 'class': klass})
173
171
 
174
172
  except Exception as e: # pragma: no cover
175
173
  logger.warning(str(e))
@@ -685,8 +685,7 @@ def main():
685
685
  )
686
686
  win.mainwindow.setVisible(False)
687
687
 
688
- win_ext, ext = create_extension(dashboard, RampExtension)
689
- win_ext.show()
688
+ win_ext, ext = create_extension(dashboard, RampExtension, show_extension=True)
690
689
 
691
690
  sys.exit(app.exec())
692
691
 
@@ -14,8 +14,7 @@ def main():
14
14
  )
15
15
  win.mainwindow.setVisible(False)
16
16
 
17
- win_ext, ext = create_extension(dashboard, Sequencer)
18
- win_ext.show()
17
+ win_ext, ext = create_extension(dashboard, Sequencer, show_extension=True)
19
18
 
20
19
  sys.exit(app.exec())
21
20
 
@@ -359,8 +359,7 @@ def main():
359
359
  )
360
360
  win.mainwindow.setVisible(False)
361
361
 
362
- win_ext, ext = create_extension(dashboard, Sequencer)
363
- win_ext.show()
362
+ win_ext, ext = create_extension(dashboard, Sequencer, show_extension=True)
364
363
 
365
364
  sys.exit(app.exec())
366
365
 
@@ -1,5 +1,6 @@
1
1
 
2
2
  import importlib
3
+ import inspect
3
4
  from packaging import version as version_mod
4
5
  import pkgutil
5
6
  import platform
@@ -141,6 +142,30 @@ def get_instrument_plugins(): # pragma: no cover
141
142
  return plugins_import
142
143
 
143
144
 
145
+ def find_model_class(model_module, base: type):
146
+ """ Get the model class of a module of the ``models`` folder of a plugin
147
+
148
+ It is the class defined in the module (not imported in it) that derives from ``base`` and that is not itself the
149
+ base class of another one defined there. Deriving from an intermediate class of your own is therefore possible.
150
+
151
+ Parameters
152
+ ----------
153
+ model_module: module
154
+ a module of the ``models`` folder of a plugin package
155
+ base: type
156
+ the generic model class of the extension (``PIDModelGeneric``, ``DataMixerModel``...)
157
+
158
+ Returns
159
+ -------
160
+ type or None: the model class, None if the module defines none
161
+ """
162
+ candidates = [klass for _, klass in inspect.getmembers(model_module, inspect.isclass)
163
+ if issubclass(klass, base) and klass is not base and klass.__module__ == model_module.__name__]
164
+ leaves = [klass for klass in candidates if not any(other is not klass and issubclass(other, klass)
165
+ for other in candidates)]
166
+ return leaves[0] if leaves else None
167
+
168
+
144
169
  def get_plugins(plugin_type='daq_0Dviewer'): # pragma: no cover
145
170
  """
146
171
  Get plugins names as a list
@@ -0,0 +1,238 @@
1
+ """Report which plugin repositories still do not follow the plugin template.
2
+
3
+ Maintainer tool, run by hand (it only reads GitHub and PyPI, never writes)::
4
+
5
+ python -m pymodaq.utils.plugin_testing.compliance_report # every pymodaq_plugins_* repo of the org
6
+ python -m pymodaq.utils.plugin_testing.compliance_report basler thorlabs # these ones of the PyMoDAQ organization
7
+ python -m pymodaq.utils.plugin_testing.compliance_report someone/pymodaq_plugins_x # any repository
8
+ python -m pymodaq.utils.plugin_testing.compliance_report --pypi # + every plugin published on PyPI
9
+ python -m pymodaq.utils.plugin_testing.compliance_report --markdown # paste in an issue or a message
10
+
11
+ Archived repositories and forks of the organization are skipped. Set ``GH_TOKEN`` (or have the ``gh`` command logged
12
+ in) to raise the GitHub rate limit; public repositories do not need more.
13
+
14
+ Columns (each ``ok`` or what is wrong):
15
+
16
+ * ``host``: where the repository lives. A plugin published on PyPI should live in the PyMoDAQ organization (its
17
+ author stays the maintainer); anything else is shown as ``OUTSIDE owner``. ``-`` when the PyPI link and GitHub agree.
18
+ * ``agents``: ``AGENTS.md`` and ``CLAUDE.md`` at the root.
19
+ * ``tests``: ``tests/test_plugin_package_structure.py`` imports :mod:`pymodaq.utils.plugin_testing` (PyMoDAQ >= 5.3.2).
20
+ * ``workflows``: ``tests.yml``, ``compatibility.yml`` and ``python-publish.yml`` call the reusable workflows of
21
+ ``pymodaq_plugins_template`` and no legacy ``Test.yml``, ``Testbase.yml`` or ``updater.yml`` is left.
22
+ * ``floor``: the ``pymodaq>=X`` dependency of ``pyproject.toml`` is at least the one of the template.
23
+ * ``pr``: open pull request(s) about the plugin acceptance checks, to update instead of duplicating.
24
+
25
+ .. versionadded:: 5.3.3
26
+ """
27
+ import argparse
28
+ import json
29
+ import os
30
+ import re
31
+ import shutil
32
+ import subprocess
33
+ import sys
34
+ import urllib.error
35
+ import urllib.request
36
+ from typing import List, Optional, Tuple
37
+
38
+ ORG = 'PyMoDAQ'
39
+ TEMPLATE = f'{ORG}/pymodaq_plugins_template'
40
+ CALLERS = {'tests.yml': 'reusable-tests.yml', 'compatibility.yml': 'reusable-compatibility.yml',
41
+ 'python-publish.yml': 'reusable-publish.yml'}
42
+ LEGACY = ('Test.yml', 'Testbase.yml', 'updater.yml')
43
+ FLOOR = (5, 3, 2)
44
+ API = 'https://api.github.com'
45
+ COLUMNS = ['repo', 'host', 'agents', 'tests', 'workflows', 'floor', 'pr']
46
+
47
+
48
+ def _urlopen(url: str, use_token: bool) -> str:
49
+ headers = {'Accept': 'application/vnd.github+json', 'User-Agent': 'plugins-compliance-report'}
50
+ token = os.environ.get('GH_TOKEN') or os.environ.get('GITHUB_TOKEN')
51
+ if use_token and token:
52
+ headers['Authorization'] = f'Bearer {token}'
53
+ with urllib.request.urlopen(urllib.request.Request(url, headers=headers), timeout=30) as response:
54
+ return response.read().decode()
55
+
56
+
57
+ def request(url: str, raw: bool = False):
58
+ """GET an url; GitHub API urls go through the ``gh`` command when it is available (credentials, rate limit)"""
59
+ if url.startswith(API) and shutil.which('gh'):
60
+ done = subprocess.run(['gh', 'api', url[len(API):]], capture_output=True, text=True)
61
+ if done.returncode == 0:
62
+ return json.loads(done.stdout)
63
+ # an invalid token is refused (a raw file even answers 404) while public data needs none: try both ways
64
+ last_error = None
65
+ for use_token in ((True, False) if url.startswith(API) else (False, True)):
66
+ try:
67
+ body = _urlopen(url, use_token)
68
+ return body if raw else json.loads(body)
69
+ except urllib.error.HTTPError as error:
70
+ last_error = error
71
+ raise last_error
72
+
73
+
74
+ def fetch(full_name: str, branch: str, path: str) -> str:
75
+ try:
76
+ return request(f'https://raw.githubusercontent.com/{full_name}/{branch}/{path}', raw=True)
77
+ except urllib.error.HTTPError:
78
+ return ''
79
+
80
+
81
+ def parse_floor(pyproject: str) -> Optional[Tuple[int, ...]]:
82
+ match = re.search(r'["\']pymodaq\s*>=\s*(\d+)\.(\d+)(?:\.(\d+))?', pyproject)
83
+ return tuple(int(g or 0) for g in match.groups()) if match else None
84
+
85
+
86
+ def org_repos() -> List[str]:
87
+ """Names of the not archived, not forked ``pymodaq_plugins_*`` repositories of the organization"""
88
+ repos, page = [], 1
89
+ while True:
90
+ batch = request(f'{API}/orgs/{ORG}/repos?per_page=100&type=public&page={page}')
91
+ if not batch:
92
+ break
93
+ repos += batch
94
+ page += 1
95
+ return sorted(f"{ORG}/{r['name']}" for r in repos
96
+ if r['name'].startswith('pymodaq_plugins_') and not r['archived'] and not r['fork']
97
+ and r['full_name'] != TEMPLATE)
98
+
99
+
100
+ def pypi_plugins() -> dict:
101
+ """``{normalized pypi name: (version, github owner/repo or None)}`` of the plugins published on PyPI"""
102
+ with urllib.request.urlopen(urllib.request.Request(
103
+ 'https://pypi.org/simple/', headers={'Accept': 'application/vnd.pypi.simple.v1+json'}), timeout=120) as r:
104
+ index = json.load(r)
105
+ plugins = {}
106
+ for project in index['projects']:
107
+ name = project['name'].lower().replace('-', '_')
108
+ if not name.startswith('pymodaq_plugins_') or name == 'pymodaq_plugins_template':
109
+ continue
110
+ with urllib.request.urlopen(f"https://pypi.org/pypi/{project['name']}/json", timeout=30) as r:
111
+ info = json.load(r)['info']
112
+ urls = ' '.join([info.get('home_page') or ''] + list((info.get('project_urls') or {}).values()))
113
+ found = re.search(r'github\.com/([^/\s]+)/([^/\s#]+)', urls)
114
+ plugins[name] = (info['version'], f'{found.group(1)}/{found.group(2)}' if found else None)
115
+ return plugins
116
+
117
+
118
+ def check(full_name: str, pypi: Optional[dict] = None) -> dict:
119
+ """Compare one repository with what the template ships today"""
120
+ name = full_name.split('/')[-1]
121
+ info = request(f'{API}/repos/{full_name}')
122
+ branch = info['default_branch']
123
+ tree = {t['path'] for t in request(f'{API}/repos/{full_name}/git/trees/{branch}?recursive=1')['tree']}
124
+ result = {'repo': full_name if not full_name.startswith(ORG + '/') else name, 'branch': branch}
125
+
126
+ owner = info['owner']['login']
127
+ published = (pypi or {}).get(name.lower().replace('-', '_'))
128
+ if owner != ORG and published:
129
+ result['host'] = f'OUTSIDE {owner} (on PyPI {published[0]})'
130
+ elif owner != ORG:
131
+ result['host'] = f'outside {owner}, not on PyPI'
132
+ elif published and published[1] and not published[1].lower().startswith(ORG.lower() + '/'):
133
+ result['host'] = f'ok (PyPI links to {published[1].split("/")[0]})'
134
+ else:
135
+ result['host'] = 'ok'
136
+
137
+ missing = [f for f in ('AGENTS.md', 'CLAUDE.md') if f not in tree]
138
+ result['agents'] = ('MISSING ' + ', '.join(missing)) if missing else 'ok'
139
+
140
+ stub = 'tests/test_plugin_package_structure.py'
141
+ if stub not in tree:
142
+ result['tests'] = 'MISSING'
143
+ else:
144
+ text = fetch(full_name, branch, stub)
145
+ if 'pymodaq.utils.plugin_testing' in text:
146
+ result['tests'] = 'ok'
147
+ elif 'pymodaq_utils.plugin_testing' in text:
148
+ result['tests'] = 'OLD (pymodaq_utils.plugin_testing)'
149
+ else:
150
+ result['tests'] = 'OLD (generic copy of the template tests)'
151
+
152
+ problems = []
153
+ for workflow, reusable in CALLERS.items():
154
+ path = f'.github/workflows/{workflow}'
155
+ if path not in tree:
156
+ problems.append(f'no {workflow}')
157
+ elif f'{TEMPLATE}/.github/workflows/{reusable}' not in fetch(full_name, branch, path):
158
+ problems.append(f'{workflow} is not the template caller')
159
+ problems += [f'legacy {f}' for f in LEGACY if f'.github/workflows/{f}' in tree]
160
+ result['workflows'] = '; '.join(problems) or 'ok'
161
+
162
+ floor = parse_floor(fetch(full_name, branch, 'pyproject.toml'))
163
+ if floor is None:
164
+ result['floor'] = 'MISSING pymodaq>=X'
165
+ elif floor < FLOOR:
166
+ result['floor'] = 'OLD pymodaq>=' + '.'.join(map(str, floor))
167
+ else:
168
+ result['floor'] = 'ok'
169
+
170
+ pulls = request(f'{API}/repos/{full_name}/pulls?state=open&per_page=100')
171
+ mine = [f"#{p['number']}" for p in pulls
172
+ if re.search(r'plugin[ _]acceptance|plugin_testing|follow the plugin template', p['title'] + p['head']['ref'],
173
+ re.I)]
174
+ result['pr'] = ' '.join(mine) or '-'
175
+ result['compliant'] = (result['host'].startswith('ok') and
176
+ all(result[k] == 'ok' for k in ('agents', 'tests', 'workflows', 'floor')))
177
+ return result
178
+
179
+
180
+ def render(rows: List[dict], markdown: bool = False) -> str:
181
+ lines = []
182
+ if markdown:
183
+ lines.append('| ' + ' | '.join(COLUMNS) + ' |')
184
+ lines.append('|' + '---|' * len(COLUMNS))
185
+ lines += ['| ' + ' | '.join(str(r.get(c, '')) for c in COLUMNS) + ' |' for r in rows]
186
+ else:
187
+ widths = {c: max(len(c), *(len(str(r.get(c, ''))) for r in rows)) for c in COLUMNS}
188
+ lines.append(' '.join(c.ljust(widths[c]) for c in COLUMNS))
189
+ lines += [' '.join(str(r.get(c, '')).ljust(widths[c]) for c in COLUMNS) for r in rows]
190
+ counted = [r for r in rows if not r.get('gone')] # a repository that does not exist cannot follow the template
191
+ done = sum(1 for r in counted if r.get('compliant'))
192
+ lines += ['', f'{done}/{len(counted)} repositories follow the template']
193
+ return '\n'.join(lines)
194
+
195
+
196
+ def full_name_of(arg: str) -> str:
197
+ if '/' in arg:
198
+ return arg
199
+ return f"{ORG}/{arg if arg.startswith('pymodaq_plugins_') else 'pymodaq_plugins_' + arg}"
200
+
201
+
202
+ def main(argv: Optional[List[str]] = None) -> int:
203
+ parser = argparse.ArgumentParser(description=__doc__.split('\n')[0])
204
+ parser.add_argument('repos', nargs='*', help='short names of the organization (basler) or owner/repo; '
205
+ 'default: all the plugins of the organization')
206
+ parser.add_argument('--pypi', action='store_true',
207
+ help='also check the repositories linked by the plugins published on PyPI')
208
+ parser.add_argument('--markdown', action='store_true')
209
+ parser.add_argument('--json', action='store_true')
210
+ args = parser.parse_args(argv)
211
+
212
+ published = pypi_plugins() if args.pypi else {}
213
+ names = [full_name_of(r) for r in args.repos]
214
+ if not args.repos:
215
+ try:
216
+ names = org_repos()
217
+ except urllib.error.HTTPError as error:
218
+ print(f'Cannot list the organization ({error}): give the repositories on the command line',
219
+ file=sys.stderr)
220
+ return 2
221
+ for _, repo in published.values(): # the template is sometimes the only link an author gave on PyPI
222
+ if repo and repo not in names and repo != TEMPLATE:
223
+ names.append(repo)
224
+
225
+ rows = []
226
+ for name in names:
227
+ try:
228
+ rows.append(check(name, published))
229
+ except urllib.error.HTTPError as error:
230
+ gone = error.code == 404 # deleted, renamed or private: the link to it (PyPI, org list) is to be fixed
231
+ rows.append({'repo': name, 'host': 'gone (404)' if gone else f'error {error.code}', 'compliant': False,
232
+ 'gone': gone})
233
+ print(json.dumps(rows, indent=1) if args.json else render(rows, args.markdown))
234
+ return 0 if all(r.get('compliant') for r in rows if not r.get('gone')) else 1
235
+
236
+
237
+ if __name__ == '__main__':
238
+ sys.exit(main())
File without changes
File without changes
File without changes
File without changes
File without changes