psychopy 2024.1.4__py3-none-any.whl → 2024.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of psychopy might be problematic. Click here for more details.

Files changed (325) hide show
  1. psychopy/.DS_Store +0 -0
  2. psychopy/CHANGELOG.txt +206 -0
  3. psychopy/GIT_SHA +1 -0
  4. psychopy/VERSION +1 -0
  5. psychopy/__init__.py +77 -15
  6. psychopy/app/Resources/classic/plugin16.png +0 -0
  7. psychopy/app/Resources/classic/plugin16@2x.png +0 -0
  8. psychopy/app/Resources/dark/plugin16.png +0 -0
  9. psychopy/app/Resources/dark/plugin16@2x.png +0 -0
  10. psychopy/app/Resources/light/plugin16.png +0 -0
  11. psychopy/app/Resources/light/plugin16@2x.png +0 -0
  12. psychopy/app/__init__.py +76 -2
  13. psychopy/app/_psychopyApp.py +126 -101
  14. psychopy/app/builder/builder.py +14 -10
  15. psychopy/app/builder/dialogs/__init__.py +8 -8
  16. psychopy/app/builder/dialogs/dlgsConditions.py +12 -13
  17. psychopy/app/builder/dialogs/paramCtrls.py +24 -57
  18. psychopy/app/builder/validators.py +2 -2
  19. psychopy/app/coder/codeEditorBase.py +8 -8
  20. psychopy/app/coder/coder.py +4 -4
  21. psychopy/app/connections/sendusage.py +2 -2
  22. psychopy/app/connections/updates.py +9 -9
  23. psychopy/app/dialogs.py +34 -2
  24. psychopy/app/idle.py +31 -0
  25. psychopy/app/jobs.py +21 -3
  26. psychopy/app/linuxconfig/__init__.py +9 -0
  27. psychopy/app/locale/ar_001/LC_MESSAGE/messages.mo +0 -0
  28. psychopy/app/locale/ar_001/LC_MESSAGE/messages.po +4602 -2540
  29. psychopy/app/locale/es_CO/LC_MESSAGE/messages.mo +0 -0
  30. psychopy/app/locale/es_CO/LC_MESSAGE/messages.po +56 -54
  31. psychopy/app/locale/es_ES/LC_MESSAGE/messages.po +53 -43
  32. psychopy/app/locale/es_US/LC_MESSAGE/messages.mo +0 -0
  33. psychopy/app/locale/es_US/LC_MESSAGE/messages.po +56 -54
  34. psychopy/app/locale/ja_JP/LC_MESSAGE/messages.mo +0 -0
  35. psychopy/app/locale/ja_JP/LC_MESSAGE/messages.po +1011 -942
  36. psychopy/app/locale/pt_PT/LC_MESSAGE/messages.po +9415 -5
  37. psychopy/app/pavlovia_ui/_base.py +33 -3
  38. psychopy/app/pavlovia_ui/search.py +0 -1
  39. psychopy/app/plugin_manager/dialog.py +104 -51
  40. psychopy/app/plugin_manager/packages.py +5 -0
  41. psychopy/app/plugin_manager/plugins.py +145 -67
  42. psychopy/app/preferencesDlg.py +8 -8
  43. psychopy/app/psychopyApp.py +11 -5
  44. psychopy/app/ribbon.py +124 -14
  45. psychopy/app/runner/runner.py +6 -1
  46. psychopy/app/stdout/stdOutRich.py +27 -11
  47. psychopy/app/themes/icons.py +52 -2
  48. psychopy/assets/__init__.py +0 -0
  49. psychopy/assets/click.png +0 -0
  50. psychopy/assets/clicknext.png +0 -0
  51. psychopy/assets/next.png +0 -0
  52. psychopy/assets/psychopy.ico +0 -0
  53. psychopy/assets/psychopy.png +0 -0
  54. psychopy/assets/templates/__init__.py +0 -0
  55. psychopy/assets/touch.png +0 -0
  56. psychopy/assets/touchnext.png +0 -0
  57. psychopy/assets/window.ico +0 -0
  58. psychopy/changes/2023.1.0.md +9 -0
  59. psychopy/changes/2024.1.0.md +16 -0
  60. psychopy/changes/__init__.py +0 -0
  61. psychopy/clock.py +2 -2
  62. psychopy/colors.py +2 -1
  63. psychopy/compatibility.py +53 -1
  64. psychopy/contrib/.DS_Store +0 -0
  65. psychopy/contrib/configobj/__init__.py +10 -8
  66. psychopy/data/__init__.py +3 -2
  67. psychopy/data/base.py +5 -5
  68. psychopy/data/experiment.py +130 -4
  69. psychopy/data/routine.py +56 -0
  70. psychopy/data/staircase.py +2 -2
  71. psychopy/data/trial.py +559 -97
  72. psychopy/data/utils.py +56 -21
  73. psychopy/demos/.DS_Store +0 -0
  74. psychopy/demos/builder/.DS_Store +0 -0
  75. psychopy/demos/builder/Design Templates/.DS_Store +0 -0
  76. psychopy/demos/builder/Experiments/.DS_Store +0 -0
  77. psychopy/demos/builder/Feature Demos/.DS_Store +0 -0
  78. psychopy/demos/builder/Feature Demos/buttonBox/buttonBoxDemo.psyexp +375 -0
  79. psychopy/demos/builder/Feature Demos/buttonBox/readme.md +5 -0
  80. psychopy/demos/builder/Feature Demos/pilotMode/pilotMode.psyexp +433 -0
  81. psychopy/demos/builder/Feature Demos/pilotMode/readme.md +7 -0
  82. psychopy/demos/builder/Hardware/.DS_Store +0 -0
  83. psychopy/demos/builder/Helper Tools/.DS_Store +0 -0
  84. psychopy/demos/coder/.DS_Store +0 -0
  85. psychopy/demos/coder/hardware/testSoundLatency.py +2 -2
  86. psychopy/demos/coder/iohub/.DS_Store +0 -0
  87. psychopy/demos/coder/misc/hdf5_2_csv +33 -0
  88. psychopy/event.py +30 -29
  89. psychopy/experiment/.DS_Store +0 -0
  90. psychopy/experiment/_experiment.py +6 -6
  91. psychopy/experiment/components/.DS_Store +0 -0
  92. psychopy/experiment/components/__init__.py +6 -3
  93. psychopy/experiment/components/_base.py +286 -131
  94. psychopy/experiment/components/aperture/.DS_Store +0 -0
  95. psychopy/experiment/components/brush/.DS_Store +0 -0
  96. psychopy/experiment/components/button/.DS_Store +0 -0
  97. psychopy/experiment/components/button/__init__.py +5 -1
  98. psychopy/experiment/components/buttonBox/.DS_Store +0 -0
  99. psychopy/experiment/components/camera/.DS_Store +0 -0
  100. psychopy/experiment/components/code/.DS_Store +0 -0
  101. psychopy/experiment/components/dots/.DS_Store +0 -0
  102. psychopy/experiment/components/eyetracker_record/.DS_Store +0 -0
  103. psychopy/experiment/components/eyetracker_record/__init__.py +92 -30
  104. psychopy/experiment/components/form/.DS_Store +0 -0
  105. psychopy/experiment/components/form/__init__.py +6 -2
  106. psychopy/experiment/components/grating/.DS_Store +0 -0
  107. psychopy/experiment/components/grating/__init__.py +14 -3
  108. psychopy/experiment/components/image/.DS_Store +0 -0
  109. psychopy/experiment/components/image/__init__.py +14 -3
  110. psychopy/experiment/components/joyButtons/.DS_Store +0 -0
  111. psychopy/experiment/components/joystick/.DS_Store +0 -0
  112. psychopy/experiment/components/keyboard/.DS_Store +0 -0
  113. psychopy/experiment/components/keyboard/__init__.py +22 -10
  114. psychopy/experiment/components/microphone/.DS_Store +0 -0
  115. psychopy/experiment/components/microphone/__init__.py +59 -39
  116. psychopy/experiment/components/mouse/.DS_Store +0 -0
  117. psychopy/experiment/components/mouse/__init__.py +44 -29
  118. psychopy/experiment/components/movie/.DS_Store +0 -0
  119. psychopy/experiment/components/movie/__init__.py +1 -1
  120. psychopy/experiment/components/panorama/.DS_Store +0 -0
  121. psychopy/experiment/components/parallelOut/.DS_Store +0 -0
  122. psychopy/experiment/components/patch/.DS_Store +0 -0
  123. psychopy/experiment/components/polygon/.DS_Store +0 -0
  124. psychopy/experiment/components/polygon/__init__.py +26 -6
  125. psychopy/experiment/components/progress/.DS_Store +0 -0
  126. psychopy/experiment/components/ratingScale/.DS_Store +0 -0
  127. psychopy/experiment/components/resourceManager/.DS_Store +0 -0
  128. psychopy/experiment/components/roi/.DS_Store +0 -0
  129. psychopy/experiment/components/roi/__init__.py +5 -0
  130. psychopy/experiment/components/routineSettings/.DS_Store +0 -0
  131. psychopy/experiment/components/routineSettings/__init__.py +57 -10
  132. psychopy/experiment/components/serialOut/.DS_Store +0 -0
  133. psychopy/experiment/components/settings/.DS_Store +0 -0
  134. psychopy/experiment/components/settings/__init__.py +117 -42
  135. psychopy/experiment/components/slider/.DS_Store +0 -0
  136. psychopy/experiment/components/sound/.DS_Store +0 -0
  137. psychopy/experiment/components/sound/__init__.py +54 -19
  138. psychopy/experiment/components/static/.DS_Store +0 -0
  139. psychopy/experiment/components/static/__init__.py +1 -1
  140. psychopy/experiment/components/text/.DS_Store +0 -0
  141. psychopy/experiment/components/text/__init__.py +28 -3
  142. psychopy/experiment/components/textbox/.DS_Store +0 -0
  143. psychopy/experiment/components/textbox/__init__.py +12 -2
  144. psychopy/experiment/components/unknown/.DS_Store +0 -0
  145. psychopy/experiment/components/unknown/__init__.py +1 -2
  146. psychopy/experiment/components/unknownPlugin/.DS_Store +0 -0
  147. psychopy/experiment/components/unknownPlugin/__init__.py +2 -2
  148. psychopy/experiment/components/variable/.DS_Store +0 -0
  149. psychopy/experiment/flow.py +11 -4
  150. psychopy/experiment/loops.py +85 -37
  151. psychopy/experiment/params.py +74 -32
  152. psychopy/experiment/py2js_transpiler.py +8 -1
  153. psychopy/experiment/routines/.DS_Store +0 -0
  154. psychopy/experiment/routines/_base.py +102 -22
  155. psychopy/experiment/routines/counterbalance/.DS_Store +0 -0
  156. psychopy/experiment/routines/counterbalance/__init__.py +5 -1
  157. psychopy/experiment/routines/eyetracker_calibrate/.DS_Store +0 -0
  158. psychopy/experiment/routines/eyetracker_validate/.DS_Store +0 -0
  159. psychopy/experiment/routines/pavlovia_survey/.DS_Store +0 -0
  160. psychopy/experiment/routines/photodiodeValidator/.DS_Store +0 -0
  161. psychopy/experiment/routines/photodiodeValidator/__init__.py +6 -5
  162. psychopy/experiment/routines/unknown/.DS_Store +0 -0
  163. psychopy/gui/wxgui.py +4 -4
  164. psychopy/hardware/.DS_Store +0 -0
  165. psychopy/hardware/__init__.py +1 -1
  166. psychopy/hardware/base.py +12 -0
  167. psychopy/hardware/camera/__init__.py +1 -15
  168. psychopy/hardware/cedrus.py +10 -11
  169. psychopy/hardware/crs/colorcal.py +13 -22
  170. psychopy/hardware/crs/optical.py +10 -20
  171. psychopy/hardware/emulator.py +17 -14
  172. psychopy/hardware/eyetracker.py +42 -118
  173. psychopy/hardware/gammasci.py +4 -15
  174. psychopy/hardware/keyboard.py +102 -10
  175. psychopy/hardware/listener.py +3 -0
  176. psychopy/hardware/microphone.py +148 -18
  177. psychopy/hardware/minolta.py +8 -15
  178. psychopy/hardware/photodiode.py +191 -16
  179. psychopy/hardware/photometer/__init__.py +11 -19
  180. psychopy/hardware/pr.py +8 -15
  181. psychopy/hardware/speaker.py +39 -4
  182. psychopy/info.py +0 -71
  183. psychopy/iohub/.DS_Store +0 -0
  184. psychopy/iohub/__init__.py +1 -1
  185. psychopy/iohub/client/__init__.py +30 -20
  186. psychopy/iohub/client/keyboard.py +24 -24
  187. psychopy/iohub/datastore/__init__.py +2 -2
  188. psychopy/iohub/datastore/util.py +2 -2
  189. psychopy/iohub/default_config.yaml +1 -1
  190. psychopy/iohub/devices/.DS_Store +0 -0
  191. psychopy/iohub/devices/__init__.py +112 -25
  192. psychopy/iohub/devices/deviceConfigValidation.py +2 -1
  193. psychopy/iohub/devices/experiment/default_experiment.yaml +12 -1
  194. psychopy/iohub/devices/experiment/supported_config_settings.yaml +5 -1
  195. psychopy/iohub/devices/eyetracker/.DS_Store +0 -0
  196. psychopy/iohub/devices/eyetracker/__init__.py +46 -0
  197. psychopy/iohub/devices/eyetracker/calibration/procedure.py +2 -2
  198. psychopy/iohub/devices/eyetracker/hw/gazepoint/__init__.py +14 -2
  199. psychopy/iohub/devices/eyetracker/hw/mouse/eyetracker.py +3 -4
  200. psychopy/iohub/server.py +2 -2
  201. psychopy/iohub/start_iohub_process.py +3 -0
  202. psychopy/iohub/util/__init__.py +62 -70
  203. psychopy/layout.py +5 -5
  204. psychopy/logging.py +8 -1
  205. psychopy/microphone.py +10 -37
  206. psychopy/platform_specific/__init__.py +0 -2
  207. psychopy/platform_specific/darwin.py +1 -3
  208. psychopy/platform_specific/linux.py +31 -33
  209. psychopy/platform_specific/win32.py +38 -13
  210. psychopy/plugins/__init__.py +148 -116
  211. psychopy/plugins/util.py +39 -0
  212. psychopy/preferences/Darwin.spec +4 -2
  213. psychopy/preferences/FreeBSD.spec +4 -2
  214. psychopy/preferences/Linux.spec +4 -2
  215. psychopy/preferences/Windows.spec +4 -2
  216. psychopy/preferences/baseNoArch.spec +4 -2
  217. psychopy/preferences/preferences.py +47 -24
  218. psychopy/projects/pavlovia.py +47 -4
  219. psychopy/scripts/psyexpCompile.py +0 -4
  220. psychopy/session.py +153 -21
  221. psychopy/sound/__init__.py +31 -21
  222. psychopy/sound/_base.py +20 -3
  223. psychopy/sound/audioclip.py +320 -33
  224. psychopy/sound/backend_ptb.py +47 -58
  225. psychopy/sound/backend_pygame.py +1 -1
  226. psychopy/sound/backend_pysound.py +6 -15
  227. psychopy/sound/transcribe.py +53 -0
  228. psychopy/tests/.DS_Store +0 -0
  229. psychopy/tests/data/.DS_Store +0 -0
  230. psychopy/tests/data/TestUnknownPluginComponent_load_resave.psyexp +135 -0
  231. psychopy/tests/data/Test_textbox/test_ori_0_bottom right.png +0 -0
  232. psychopy/tests/data/Test_textbox/test_ori_0_center.png +0 -0
  233. psychopy/tests/data/Test_textbox/test_ori_0_top left.png +0 -0
  234. psychopy/tests/data/Test_textbox/test_ori_120_bottom right.png +0 -0
  235. psychopy/tests/data/Test_textbox/test_ori_120_center.png +0 -0
  236. psychopy/tests/data/Test_textbox/test_ori_120_top left.png +0 -0
  237. psychopy/tests/data/Test_textbox/test_ori_180_bottom right.png +0 -0
  238. psychopy/tests/data/Test_textbox/test_ori_180_center.png +0 -0
  239. psychopy/tests/data/Test_textbox/test_ori_180_top left.png +0 -0
  240. psychopy/tests/data/Test_textbox/test_ori_240_bottom right.png +0 -0
  241. psychopy/tests/data/Test_textbox/test_ori_240_center.png +0 -0
  242. psychopy/tests/data/Test_textbox/test_ori_240_top left.png +0 -0
  243. psychopy/tests/data/correctScript/.DS_Store +0 -0
  244. psychopy/tests/data/test_components/testClearKeyboard/testClearKeyboard.psyexp +200 -0
  245. psychopy/tests/data/test_session/.DS_Store +0 -0
  246. psychopy/tests/data/test_session/root/testFutureTrials/testFutureTrials.psyexp +155 -0
  247. psychopy/tests/data/test_session/root/testTrialNav/trialNav.psyexp +158 -0
  248. psychopy/tests/test_app/.DS_Store +0 -0
  249. psychopy/tests/test_app/conftest.py +2 -2
  250. psychopy/tests/test_app/test_speed.py +4 -1
  251. psychopy/tests/test_data/test_TrialHandler2.py +146 -1
  252. psychopy/tests/test_experiment/.DS_Store +0 -0
  253. psychopy/tests/test_experiment/needs_wx/genComponsTemplate.py +3 -3
  254. psychopy/tests/test_experiment/needs_wx/test_components.py +2 -2
  255. psychopy/tests/test_experiment/test_components/test_KeyboardComponent.py +28 -0
  256. psychopy/tests/test_experiment/test_components/test_UnknownPluginComponent.py +27 -0
  257. psychopy/tests/test_experiment/test_components/test_base_components.py +58 -0
  258. psychopy/tests/test_experiment/test_py2js.py +1 -1
  259. psychopy/tests/test_hardware/test_keyboard.py +31 -0
  260. psychopy/tests/test_hardware/test_ports.py +1 -11
  261. psychopy/tests/test_liaison/test_Liaison.py +47 -0
  262. psychopy/tests/test_misc/test_core.py +5 -0
  263. psychopy/tests/test_session/test_Session.py +5 -1
  264. psychopy/tests/test_tools/test_versionchooser.py +39 -8
  265. psychopy/tests/test_visual/test_all_stimuli.py +0 -97
  266. psychopy/tests/test_visual/test_image.py +6 -5
  267. psychopy/tests/test_visual/test_textbox.py +36 -0
  268. psychopy/tests/utils.py +4 -0
  269. psychopy/tools/filetools.py +1 -1
  270. psychopy/tools/pkgtools.py +160 -137
  271. psychopy/tools/versionchooser.py +10 -10
  272. psychopy/tools/wizard.py +3 -3
  273. psychopy/visual/.DS_Store +0 -0
  274. psychopy/visual/backends/pygletbackend.py +24 -13
  275. psychopy/visual/basevisual.py +5 -11
  276. psychopy/visual/button.py +2 -14
  277. psychopy/visual/helpers.py +5 -5
  278. psychopy/visual/line.py +1 -2
  279. psychopy/visual/movie2.py +7 -816
  280. psychopy/visual/movie3.py +7 -589
  281. psychopy/visual/movies/__init__.py +8 -11
  282. psychopy/visual/movies/frame.py +5 -2
  283. psychopy/visual/movies/players/ffpyplayer_player.py +5 -2
  284. psychopy/visual/noise.py +8 -7
  285. psychopy/visual/patch.py +7 -16
  286. psychopy/visual/radial.py +9 -7
  287. psychopy/visual/ratingscale.py +8 -1415
  288. psychopy/visual/secondorder.py +10 -9
  289. psychopy/visual/shape.py +7 -2
  290. psychopy/visual/text.py +1 -1
  291. psychopy/visual/textbox2/textbox2.py +28 -5
  292. {psychopy-2024.1.4.dist-info → psychopy-2024.2.0.dist-info}/METADATA +8 -13
  293. {psychopy-2024.1.4.dist-info → psychopy-2024.2.0.dist-info}/RECORD +307 -213
  294. {psychopy-2024.1.4.dist-info → psychopy-2024.2.0.dist-info}/WHEEL +1 -1
  295. psychopy/app/Resources/click.png +0 -0
  296. psychopy/app/Resources/next.png +0 -0
  297. psychopy/experiment/components/patch/__init__.py +0 -121
  298. psychopy/experiment/components/patch/classic/patch.png +0 -0
  299. psychopy/experiment/components/patch/dark/patch.png +0 -0
  300. psychopy/experiment/components/patch/dark/patch@2x.png +0 -0
  301. psychopy/experiment/components/patch/light/patch.png +0 -0
  302. psychopy/experiment/components/patch/light/patch@2x.png +0 -0
  303. psychopy/experiment/components/ratingScale/__init__.py +0 -337
  304. psychopy/experiment/components/ratingScale/classic/ratingscale.png +0 -0
  305. psychopy/experiment/components/ratingScale/classic/ratingscale@2x.png +0 -0
  306. psychopy/experiment/components/ratingScale/dark/ratingScale@2x.png +0 -0
  307. psychopy/experiment/components/ratingScale/dark/ratingscale.png +0 -0
  308. psychopy/experiment/components/ratingScale/light/ratingScale@2x.png +0 -0
  309. psychopy/experiment/components/ratingScale/light/ratingscale.png +0 -0
  310. psychopy/platform_specific/posix.py +0 -16
  311. psychopy/tests/test_sound/test_microphone.py +0 -217
  312. psychopy/tests/test_visual/test_ratingScale.py +0 -299
  313. /psychopy/{app/Resources → assets}/Psychopy Window Favicon@16w.png +0 -0
  314. /psychopy/{app/Resources → assets}/Psychopy Window Favicon@32w.png +0 -0
  315. /psychopy/{app/Resources → assets}/USB-C.png +0 -0
  316. /psychopy/{app/Resources → assets}/USB.png +0 -0
  317. /psychopy/{app/Resources → assets}/creditCard.png +0 -0
  318. /psychopy/{app/Resources → assets}/default.mp3 +0 -0
  319. /psychopy/{app/Resources → assets}/default.mp4 +0 -0
  320. /psychopy/{app/Resources → assets}/default.png +0 -0
  321. /psychopy/{app/Resources → assets/templates}/instruct1.png +0 -0
  322. /psychopy/{app/Resources → assets/templates}/instruct2.png +0 -0
  323. {psychopy-2024.1.4.dist-info → psychopy-2024.2.0.dist-info}/entry_points.txt +0 -0
  324. {psychopy-2024.1.4.dist-info → psychopy-2024.2.0.dist-info}/licenses/AUTHORS.md +0 -0
  325. {psychopy-2024.1.4.dist-info → psychopy-2024.2.0.dist-info}/licenses/LICENSE +0 -0
@@ -7,6 +7,7 @@ import socket
7
7
  import os
8
8
  import numbers # numbers.Integral is like (int, long) but supports Py3
9
9
  from psychopy import colors
10
+ from psychopy.iohub.devices import importDeviceModule
10
11
  from psychopy.tools import arraytools
11
12
  from ..util import yload, yLoader, module_directory, getSupportedConfigSettings
12
13
  from ..errors import print2err
@@ -488,7 +489,7 @@ def validateDeviceConfiguration(
488
489
  current_device_config):
489
490
  """Validate the device configuration settings provided.
490
491
  """
491
- validation_module = importlib.import_module(relative_module_path)
492
+ validation_module = importDeviceModule(relative_module_path)
492
493
  validation_file_path = getSupportedConfigSettings(validation_module)
493
494
 
494
495
  # use a default config if we can't get the YAML file
@@ -6,13 +6,24 @@
6
6
  # indicated here.
7
7
  #
8
8
  Experiment:
9
- # name: The unique name to assign to the evice instance created.
9
+ # name: The unique name to assign to the device instance created.
10
10
  # The device is accessed from within the PsychoPy script
11
11
  # using the name's value; therefore it must be a valid Python
12
12
  # variable name as well.
13
13
  #
14
14
  name: experiment
15
15
 
16
+ # filename: The name of files saved by an attached PsychoPy experiment.
17
+ # This is usually provided as PsychoPy ExperimentHandler.dataFileName.
18
+ # It gives ioHub server awareness of filenames used by PsychoPy when a
19
+ # DataStore file is not being saved by the ioHub. This handle is useful
20
+ # when the ioHub is being used to monitor the PsychoPy experiment, but
21
+ # all data is being saved by the PsychoPy ExperimentHandler, while there
22
+ # are external data files transferred through the ioHub server that need
23
+ # to be saved in the same naming convention as the PsychoPy data files.
24
+ # Default value is Python None type. Valid value is any string.
25
+ filename:
26
+
16
27
  # monitor_event_types: Specify which of the device's supported event
17
28
  # types you would like the ioHub to monitor for.
18
29
  #
@@ -4,7 +4,11 @@ Experiment:
4
4
  IOHUB_STRING:
5
5
  min_length: 1
6
6
  max_length: 32
7
- first_char_alpha: True
7
+ first_char_alpha: True
8
+ filename:
9
+ IOHUB_STRING:
10
+ min_length: 0
11
+ first_char_alpha: False
8
12
  save_events: IOHUB_BOOL
9
13
  stream_events: True
10
14
  auto_report_events: True
@@ -250,6 +250,52 @@ class EyeTrackerDevice(Device):
250
250
  None
251
251
  """
252
252
  return EyeTrackerConstants.EYETRACKER_INTERFACE_METHOD_NOT_SUPPORTED
253
+
254
+ @staticmethod
255
+ def getCalibrationDict(calib):
256
+ """
257
+ Create a dict describing the given Calibration object, respecting this
258
+ eyetracker's specific limitations. If not overloaded by a subclass, this
259
+ will use the same fields and values as MouseGaze.
260
+
261
+ Parameters
262
+ ----------
263
+ calib : psychopy.hardware.eyetracker.EyetrackerCalibration
264
+ Object to create a dict from
265
+
266
+ Returns
267
+ -------
268
+ dict
269
+ Dict describing the given Calibration object
270
+ """
271
+ return {
272
+ 'target_attributes': {
273
+ # target outer circle
274
+ 'outer_diameter': calib.target.radius * 2,
275
+ 'outer_stroke_width': calib.target.outer.lineWidth,
276
+ 'outer_fill_color': getattr(calib.target.outer._fillColor, calib.colorSpace) if calib.target.outer._fillColor else getattr(calib.target.win._color, calib.colorSpace),
277
+ 'outer_line_color': getattr(calib.target.outer._borderColor, calib.colorSpace) if calib.target.outer._borderColor else getattr(calib.target.win._color, calib.colorSpace),
278
+ # target inner circle
279
+ 'inner_diameter': calib.target.innerRadius * 2,
280
+ 'inner_stroke_width': calib.target.inner.lineWidth,
281
+ 'inner_fill_color': getattr(calib.target.inner._borderColor, calib.colorSpace) if calib.target.inner._borderColor else getattr(calib.target.win._color, calib.colorSpace),
282
+ 'inner_line_color': getattr(calib.target.inner._borderColor, calib.colorSpace) if calib.target.inner._borderColor else getattr(calib.target.win._color, calib.colorSpace),
283
+ # target animation
284
+ 'animate':{
285
+ 'enable': calib.movementAnimation,
286
+ 'expansion_ratio': calib.expandScale,
287
+ 'contract_only': calib.expandScale == 1,
288
+ },
289
+ },
290
+ 'type': calib.targetLayout,
291
+ 'randomize': calib.randomisePos,
292
+ 'auto_pace': calib.progressMode == "time",
293
+ 'pacing_speed': calib.targetDelay,
294
+ 'unit_type': calib.units,
295
+ 'color_type': calib.colorSpace,
296
+ 'text_color': calib.textColor if str(calib.textColor).lower() != "auto" else None,
297
+ 'screen_background_color': getattr(calib.win._color, calib.colorSpace),
298
+ }
253
299
 
254
300
  def setRecordingState(self, recording):
255
301
  """The setRecordingState method is used to start or stop the recording
@@ -157,10 +157,10 @@ class BaseCalibrationProcedure:
157
157
  def setDefaultCalibrationTarget():
158
158
  # convert sizes to stimulus units
159
159
  radiusPix = self.getCalibSetting(['target_attributes', 'outer_diameter']) / 2
160
- radiusObj = layout.Size(radiusPix, units="pix", win=self.window)
160
+ radiusObj = layout.Size(radiusPix, units=unit_type, win=self.window)
161
161
  radius = getattr(radiusObj, unit_type)[1]
162
162
  innerRadiusPix = self.getCalibSetting(['target_attributes', 'inner_diameter']) / 2
163
- innerRadiusObj = layout.Size(innerRadiusPix, units="pix", win=self.window)
163
+ innerRadiusObj = layout.Size(innerRadiusPix, units=unit_type, win=self.window)
164
164
  innerRadius = getattr(innerRadiusObj, unit_type)[1]
165
165
  # make target
166
166
  self.targetStim = visual.TargetStim(
@@ -6,7 +6,19 @@
6
6
  import psychopy.logging as logging
7
7
 
8
8
  try:
9
- from psychopy_eyetracker_gazepoint.gazepoint import gp3
9
+ from psychopy_eyetracker_gazepoint.gazepoint.gp3 import (
10
+ __file__,
11
+ EyeTracker,
12
+ MonocularEyeSampleEvent,
13
+ BinocularEyeSampleEvent,
14
+ FixationStartEvent,
15
+ FixationEndEvent,
16
+ SaccadeStartEvent,
17
+ SaccadeEndEvent,
18
+ BlinkStartEvent,
19
+ BlinkEndEvent,
20
+ GazepointSampleEvent
21
+ )
10
22
  except (ModuleNotFoundError, ImportError, NameError):
11
23
  logging.error(
12
24
  "The Gazepoint eyetracker requires package "
@@ -14,4 +26,4 @@ except (ModuleNotFoundError, ImportError, NameError):
14
26
  "package and restart the session to enable support.")
15
27
 
16
28
  if __name__ == "__main__":
17
- pass
29
+ pass
@@ -408,11 +408,10 @@ class EyeTracker(EyeTrackerDevice):
408
408
  cal_run = calibration.runCalibration()
409
409
  calibration.window.close()
410
410
 
411
- # NOTE - The following line has been commented out to prevent ioHub from
412
- # losing keyboard input after the window is closed. The new keyboard
413
- # input system does not require this call anymore.
414
- # calibration._unregisterEventMonitors()
411
+ calibration._unregisterEventMonitors()
415
412
  calibration.clearAllEventBuffers()
413
+ del calibration.window
414
+ del calibration
416
415
 
417
416
  if cal_run:
418
417
  return {"RESULT": "CALIBRATION_OK"}
psychopy/iohub/server.py CHANGED
@@ -28,7 +28,7 @@ from .net import MAX_PACKET_SIZE
28
28
  from .util import convertCamelToSnake, win32MessagePump
29
29
  from .util import yload, yLoader
30
30
  from .constants import DeviceConstants, EventConstants
31
- from .devices import DeviceEvent, import_device
31
+ from .devices import DeviceEvent, import_device, importDeviceModule
32
32
  from .devices import Computer
33
33
  from .devices.deviceConfigValidation import validateDeviceConfiguration
34
34
  getTime = Computer.getTime
@@ -846,7 +846,7 @@ class ioServer():
846
846
  else:
847
847
  dev_mod_pth += dev_cls_name.lower()
848
848
  # convert subdirectory to path
849
- dev_mod = importlib.import_module(dev_mod_pth)
849
+ dev_mod = importDeviceModule(dev_mod_pth)
850
850
  dev_file_pth = os.path.dirname(dev_mod.__file__)
851
851
  # get config from path
852
852
  dev_conf_pth = os.path.join(dev_file_pth,
@@ -79,6 +79,9 @@ def run(rootScriptPathDir, configFilePath):
79
79
  else:
80
80
  gevent.joinall(glets)
81
81
 
82
+ # Wait for the server to be ready to shutdown
83
+ gevent.wait()
84
+
82
85
  lrtime = Computer.global_clock.getLastResetTime()
83
86
  s.log('Server END Time Offset: {0}'.format(lrtime), 'DEBUG')
84
87
  return True
@@ -16,6 +16,10 @@ import collections.abc
16
16
  import pathlib
17
17
  import psychopy.logging as logging
18
18
  import psychopy.plugins as plugins
19
+ from psychopy.plugins.util import getEntryPoints
20
+ from importlib.metadata import entry_points
21
+ from pathlib import Path
22
+ from psychopy.preferences import prefs
19
23
 
20
24
  ########################
21
25
  #
@@ -33,8 +37,6 @@ try:
33
37
  except ImportError:
34
38
  from collections import Iterable
35
39
 
36
- from psychopy.preferences import prefs
37
-
38
40
 
39
41
  def saveConfig(config, dst_path):
40
42
  '''
@@ -141,7 +143,7 @@ def module_directory(local_function):
141
143
  def getSupportedConfigSettings(moduleName, deviceClassName=None):
142
144
  """Get the supported configuration settings for a device.
143
145
 
144
- These are usually stored as YAML files within the module directory that
146
+ These are usually stored as YAML files within the module directory that
145
147
  defines the device class.
146
148
 
147
149
  Parameters
@@ -150,10 +152,10 @@ def getSupportedConfigSettings(moduleName, deviceClassName=None):
150
152
  The name of the module to get the path for. Must be a package that defines
151
153
  `__init__.py`.
152
154
  deviceClassName : str, optional
153
- The name of the specific device class to get the path for. If not provided,
154
- the default configuration file will be searched for in the module
155
+ The name of the specific device class to get the path for. If not provided,
156
+ the default configuration file will be searched for in the module
155
157
  directory.
156
-
158
+
157
159
  Returns
158
160
  -------
159
161
  str
@@ -174,13 +176,13 @@ def getSupportedConfigSettings(moduleName, deviceClassName=None):
174
176
  "Found ioHub device configuration file: {0}".format(yamlFile))
175
177
 
176
178
  return str(yamlFile)
177
-
179
+
178
180
  # file name for yaml file name convention for single file
179
181
  yamlFile = yamlRoot / pathlib.Path('supported_config_settings.yaml')
180
182
  if not yamlFile.exists(): # nothing is found
181
183
  raise FileNotFoundError(
182
184
  "No config file found in module dir {0}".format(moduleName))
183
-
185
+
184
186
  logging.debug(
185
187
  "Found ioHub device configuration file: {0}".format(yamlFile))
186
188
 
@@ -231,9 +233,17 @@ def getDevicePaths(device_name=""):
231
233
 
232
234
  """
233
235
  yaml_paths = []
234
- # try to walk both the internal iohub_device_path and user-level packages folder
235
- for route in (os.walk(iohub_device_path), os.walk(prefs.paths['packages'])):
236
- for root, _, files in route:
236
+
237
+ if '.zip' in iohub_device_path:
238
+ # if the entry point is in a zip file, it is likely loading from a precompiled
239
+ # library instead of a user installed plugin module. Raise warning.
240
+ logging.error(
241
+ f"Bad entry point loaded: {ep}\n"
242
+ f"It is pointing into a zip file: {iohub_device_path}"
243
+ )
244
+ else:
245
+ # search the provided iohub_device_path for device config files
246
+ for root, _, files in os.walk(iohub_device_path):
237
247
  # check each file in the route to see if it's a config yaml
238
248
  device_folder = None
239
249
  for file in files:
@@ -253,65 +263,40 @@ def getDevicePaths(device_name=""):
253
263
  scs_yaml_paths = [] # stores the paths to the device config files
254
264
  plugins.refreshBundlePaths() # make sure eyetracker external plugins are reachable
255
265
 
256
- # get device paths for extant extensions
257
- try: # tobii eyetrackers
258
- logging.debug("Looking for Tobii device configuration file...")
259
- import psychopy_eyetracker_tobii.tobii as tobii
260
- deviceConfig = _getDevicePaths(os.path.dirname(tobii.__file__))
261
- if deviceConfig:
262
- logging.debug("Found Tobii device configuration file.")
263
- scs_yaml_paths.extend(deviceConfig)
264
- except ImportError:
265
- logging.debug("No Tobii device configuration file found.")
266
-
267
- try: # for SR Research EyeLink
268
- logging.debug("Looking for SR Research EyeLink device configuration file...")
269
- import psychopy_eyetracker_sr_research.sr_research.eyelink as eyelink
270
- deviceConfig = _getDevicePaths(os.path.dirname(eyelink.__file__))
271
- if deviceConfig:
272
- logging.debug("Found SR Research EyeLink device configuration file.")
273
- scs_yaml_paths.extend(deviceConfig)
274
- except ImportError:
275
- logging.debug("No SR Research EyeLink device configuration file found.")
276
-
277
- try: # for Gazepoint eye trackers
278
- logging.debug("Looking for Gazepoint device configuration file...")
279
- import psychopy_eyetracker_gazepoint.gazepoint.gp3 as gp3
280
- deviceConfig = _getDevicePaths(os.path.dirname(gp3.__file__))
281
- if deviceConfig:
282
- logging.debug("Found Gazepoint device configuration file.")
283
- scs_yaml_paths.extend(deviceConfig)
284
- except ImportError:
285
- logging.debug("No Gazepoint device configuration file found.")
286
-
287
- try: # for PupilLabs eye trackers
288
- logging.debug("Looking for PupilLabs device configuration file...")
289
- import psychopy_eyetracker_pupil_labs.pupil_labs.pupil_core as pupil_core
290
- deviceConfig = _getDevicePaths(os.path.dirname(pupil_core.__file__))
291
- if deviceConfig:
292
- logging.debug("Found PupilLabs device configuration file.")
293
- scs_yaml_paths.extend(deviceConfig)
294
-
295
- import psychopy_eyetracker_pupil_labs.pupil_labs.neon as neon
296
- deviceConfig = _getDevicePaths(os.path.dirname(neon.__file__))
297
- if deviceConfig:
298
- logging.debug("Found PupilLabs Neon device configuration file.")
299
- scs_yaml_paths.extend(deviceConfig)
300
-
301
- except ImportError:
302
- logging.debug("No PupilLabs device configuration file found.")
303
-
304
- # use this method for built-in devices
266
+ # NOTE: The “selectable” entry points were introduced in importlib_metadata 3.6 and Python 3.10.
267
+ # Prior to those changes, entry_points accepted no parameters and always returned a dictionary
268
+ # of entry points, keyed by group. With importlib_metadata 5.0 and Python 3.12, entry_points
269
+ # always returns an EntryPoints object.
270
+
271
+ if 'eyetracker' in device_name.lower():
272
+ # Find entry points targeting psychopy.iohub.devices.eyetracker
273
+ for ep in getEntryPoints('psychopy.iohub.devices.eyetracker', submodules=False, flatten=True):
274
+ # load the target the entry point points to, it could be a class or a module
275
+ try:
276
+ ep_target = ep.load()
277
+ except: # noqa: E722
278
+ logging.error(f"Failed to load entry point: {ep}")
279
+ continue
280
+
281
+ if hasattr(ep_target, "configFile"):
282
+ # if entry point target binds to a yaml file, use it
283
+ scs_yaml_paths.append(
284
+ (ep_target.configFile.parent, ep_target.configFile.name)
285
+ )
286
+ else: # otherwise, check the local folder of the target module or class
287
+ deviceConfig = _getDevicePaths(os.path.dirname(inspect.getfile(ep_target)))
288
+ scs_yaml_paths.extend(deviceConfig)
289
+
290
+ # Use import_device() method for built-in devices
305
291
  iohub_device_path = module_directory(import_device)
306
292
  if device_name:
307
293
  iohub_device_path = os.path.join(
308
294
  iohub_device_path, device_name.replace('.', os.path.sep))
309
-
310
295
  deviceConfigs = _getDevicePaths(iohub_device_path)
311
- if deviceConfigs:
312
- scs_yaml_paths.extend(deviceConfigs)
296
+ scs_yaml_paths.extend(deviceConfigs)
313
297
 
314
- return scs_yaml_paths
298
+ # Return a unique list of device config paths
299
+ return list(set(scs_yaml_paths))
315
300
 
316
301
 
317
302
  def getDeviceDefaultConfig(device_name, builder_hides=True):
@@ -381,10 +366,10 @@ def getDeviceNames(device_name="eyetracker.hw", get_paths=True):
381
366
  print(eyetrackers)
382
367
 
383
368
  Output:
384
- [('GazePoint', 'eyetracker.hw.gazepoint.gp3.EyeTracker'),
369
+ [('GazePoint', 'eyetracker.gazepoint.EyeTracker'),
385
370
  ('MouseGaze', 'eyetracker.hw.mouse.EyeTracker'),
386
- ('SR Research Ltd', 'eyetracker.hw.sr_research.eyelink.EyeTracker'),
387
- ('Tobii Technology', 'eyetracker.hw.tobii.EyeTracker')]
371
+ ('SR Research Ltd', 'eyetracker.eyelink.EyeTracker'),
372
+ ('Tobii Technology', 'eyetracker.tobii.EyeTracker')]
388
373
  """
389
374
  names = []
390
375
  dconfigs = getDeviceDefaultConfig(device_name)
@@ -397,6 +382,7 @@ def getDeviceNames(device_name="eyetracker.hw", get_paths=True):
397
382
  names.append((d_config.get('manufacturer_name'), d_path))
398
383
  return names
399
384
 
385
+
400
386
  def getDeviceFile(device_name, file_name):
401
387
  """
402
388
  Returns the contents of file_name for the specified device. If file_name does not exist, None is returned.
@@ -408,6 +394,7 @@ def getDeviceFile(device_name, file_name):
408
394
  if device_name.endswith(".EyeTracker"):
409
395
  device_name = device_name[:-11]
410
396
  device_paths = getDevicePaths(device_name)
397
+
411
398
  device_sconfigs = []
412
399
  for dpath, _ in device_paths:
413
400
  device_sconfigs.append(readConfig(os.path.join(dpath, file_name)))
@@ -416,6 +403,7 @@ def getDeviceFile(device_name, file_name):
416
403
  return list(device_sconfigs[0].values())[0]
417
404
  return device_sconfigs
418
405
 
406
+
419
407
  def getDeviceSupportedConfig(device_name):
420
408
  """
421
409
  Returns the contents of the supported_config_settings.yaml for the specified device.
@@ -425,6 +413,7 @@ def getDeviceSupportedConfig(device_name):
425
413
  """
426
414
  return getDeviceFile(device_name, 'supported_config_settings.yaml')
427
415
 
416
+
428
417
  if sys.platform == 'win32':
429
418
  import pythoncom
430
419
 
@@ -446,6 +435,7 @@ else:
446
435
  def win32MessagePump():
447
436
  pass
448
437
 
438
+
449
439
  # PsychoPy Window Hide / Show functions.
450
440
  # Windows 10 and macOS have different code that needs to be called
451
441
  # to show a second full screen window on top of an existing one, like
@@ -468,6 +458,7 @@ def hideWindow(win, force=False):
468
458
  else:
469
459
  print("Warning: Unhandled sys.platform: ", sys.platform)
470
460
 
461
+
471
462
  def showWindow(win, force=False):
472
463
  """
473
464
  If needed, hide / minimize the in.
@@ -486,6 +477,7 @@ def showWindow(win, force=False):
486
477
  else:
487
478
  print("Warning: Unhandled sys.platform: ", sys.platform)
488
479
 
480
+
489
481
  def createCustomCalibrationStim(win, cal_settings):
490
482
  """
491
483
  Create a custom calibration target using the CUSTOM eyetracker calibration settings. Returns an instance of
@@ -549,12 +541,12 @@ def updateDict(add_to, add_from):
549
541
 
550
542
  def updateSettings(d, u):
551
543
  for k, v in u.items():
552
- if type(k) == bytes:
544
+ if isinstance(k, bytes):
553
545
  k = k.decode('UTF-8')
554
546
  if isinstance(v, collections.abc.Mapping):
555
547
  d[k] = updateSettings(d.get(k, {}), v)
556
548
  else:
557
- if type(v) == bytes:
549
+ if isinstance(v, bytes):
558
550
  v = v.decode('UTF-8')
559
551
  d[k] = v
560
552
  return d
@@ -575,7 +567,7 @@ def convertCamelToSnake(name, lower_snake=True):
575
567
  # A couple date / time related utility functions
576
568
 
577
569
  getCurrentDateTime = datetime.datetime.now
578
- getCurrentDateTimeString = lambda: getCurrentDateTime().strftime("%Y-%m-%d %H:%M")
570
+ getCurrentDateTimeString = lambda: getCurrentDateTime().strftime("%Y-%m-%d %H:%M") # noqa: E731
579
571
 
580
572
 
581
573
  # rgb255 color utils
psychopy/layout.py CHANGED
@@ -171,16 +171,16 @@ class Vector:
171
171
  self.valid = False
172
172
 
173
173
  # Replace None with the matching window dimension
174
- if (value == None).any() or np.isnan(value).any():
174
+ if (value == None).any() or np.isnan(value).any(): # noqa: E711
175
175
  win = Vector((1, 1), units="norm", win=self.win)
176
176
  if len(value.shape) == 1:
177
- value[value == None] = getattr(win, units)[value == None]
177
+ value[value == None] = getattr(win, units)[value == None] # noqa: E711
178
178
  value[np.isnan(value)] = getattr(win, units)[np.isnan(value)]
179
179
  else:
180
180
  value[np.isnan(value[:, 0]), 0] = getattr(win, units)[0]
181
181
  value[np.isnan(value[:, 1]), 1] = getattr(win, units)[1]
182
- value[value[:, 0] == None, 0] = getattr(win, units)[0]
183
- value[value[:, 1] == None, 1] = getattr(win, units)[1]
182
+ value[value[:, 0] == None, 0] = getattr(win, units)[0] # noqa: E711
183
+ value[value[:, 1] == None, 1] = getattr(win, units)[1] # noqa: E711
184
184
 
185
185
  assert self.valid, (f"Array of position/size values must be either "
186
186
  f"Nx1, Nx2 or Nx3, not {value.shape}")
@@ -913,4 +913,4 @@ class Vertices:
913
913
 
914
914
 
915
915
  if __name__ == "__main__":
916
- pass
916
+ pass
psychopy/logging.py CHANGED
@@ -76,6 +76,9 @@ _levelNames = {
76
76
  'DEBUG': DEBUG,
77
77
  'NOTSET': NOTSET}
78
78
 
79
+ # string to search for level names in a log message
80
+ _levelNamesRe = "|".join(key for key in _levelNames if isinstance(key, str))
81
+
79
82
  _prefEncoding = locale.getpreferredencoding()
80
83
 
81
84
  def getLevel(level):
@@ -188,6 +191,10 @@ class LogFile():
188
191
  def setLevel(self, level):
189
192
  """Set a new minimal level for the log file/stream
190
193
  """
194
+ # if given a name, get corresponding integer value
195
+ if isinstance(level, str):
196
+ level = getLevel(level)
197
+ # make sure we (now) have an integer
191
198
  if type(level) is not int:
192
199
  raise TypeError("LogFile.setLevel() should be given an int, which"
193
200
  "is usually one of logging.INFO (not logging.info)")
@@ -305,7 +312,7 @@ class _Logger():
305
312
  self.toFlush = [] # a new empty list
306
313
 
307
314
  root = _Logger()
308
- console = LogFile()
315
+ console = LogFile(level=WARNING)
309
316
 
310
317
 
311
318
  def flush(logger=root):
psychopy/microphone.py CHANGED
@@ -12,43 +12,16 @@ These are optional components that can be obtained by installing the
12
12
 
13
13
  """
14
14
 
15
- import psychopy.logging as logging
16
-
17
- try:
18
- from psychopy_legacy_mic import (
19
- haveMic,
20
- FLAC_PATH,
21
- AudioCapture,
22
- AdvAudioCapture,
23
- getMarkerOnset,
24
- readWavFile,
25
- getDftBins,
26
- getDft,
27
- getRMSBins,
28
- getRMS,
29
- SoundFormatNotSupported,
30
- SoundFileError,
31
- MicrophoneError,
32
- Speech2Text,
33
- BatchSpeech2Text,
34
- flac2wav,
35
- wav2flac,
36
- switchOn,
37
- switchOff,
38
- _getFlacPath)
39
- except (ModuleNotFoundError, ImportError, NameError):
40
- logging.error(
41
- "Support for `psychopy.microphone` hardware is not available this "
42
- "session. Please install `psychopy-legacy-mic` and restart the session "
43
- "to enable support.")
44
- else:
45
- # if we successfully load the package, warn the user to use the newer stuff
46
- logging.warning(
47
- "Attempting to import `psychopy.microphone`. Note that this library is "
48
- "deprecated for the purpose of audio capture, but may still provide "
49
- "other useful functionality. Use `psychopy.sound.microphone` for audio "
50
- "capture instead."
51
- )
15
+
16
+ from psychopy.tools.pkgtools import PluginStub
17
+
18
+
19
+ class AudioCapture(
20
+ PluginStub,
21
+ plugin="psychopy-legacy-mic"
22
+ ):
23
+ pass
24
+
52
25
 
53
26
  if __name__ == "__main__":
54
27
  pass
@@ -44,5 +44,3 @@ elif sys.platform == 'darwin':
44
44
  from .darwin import * # pylint: disable=W0401
45
45
  elif sys.platform.startswith('linux'): # normally 'linux2'
46
46
  from .linux import * # pylint: disable=W0401
47
- elif sys.platform == 'posix': # ever?!
48
- from .posix import * # pylint: disable=W0401
@@ -105,8 +105,6 @@ def getBusFreq():
105
105
  def rush(value=True, realtime=False):
106
106
  """Raise the priority of the current thread / process.
107
107
 
108
- Win32 and macOS only so far - on linux use os.nice(niceIncrement)
109
-
110
108
  Set with rush(True) or rush(False).
111
109
 
112
110
  realtime arg is not used by osx implementation.
@@ -149,7 +147,7 @@ def rush(value=True, realtime=False):
149
147
  # send the address of the struct
150
148
  ctypes.byref(extendedPolicy),
151
149
  THREAD_STANDARD_POLICY_COUNT)
152
- return True
150
+ return err == KERN_SUCCESS
153
151
 
154
152
 
155
153
  def getThreadPolicy(getDefault, flavour):