psychopy 2024.1.3__py3-none-any.whl → 2024.1.4__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.

@@ -1222,6 +1222,13 @@ def getAllPluginDetails():
1222
1222
  return None
1223
1223
  # otherwise get as a string
1224
1224
  value = resp.text
1225
+
1226
+ if value is None or value == "":
1227
+ return None
1228
+
1229
+ # make sure we are using UTF-8 encoding
1230
+ value = value.encode('utf-8', 'ignore').decode('utf-8')
1231
+
1225
1232
  # attempt to parse JSON
1226
1233
  try:
1227
1234
  database = json.loads(value)
@@ -125,7 +125,7 @@
125
125
  <Param val="from exp settings" valType="str" updates="None" name="units" />
126
126
  </TextboxComponent>
127
127
  <ProgressComponent name="timer10" plugin="None">
128
- <Param val="center left" valType="str" updates="constant" name="anchor" />
128
+ <Param val="center-left" valType="str" updates="constant" name="anchor" />
129
129
  <Param val="grey" valType="color" updates="constant" name="borderColor" />
130
130
  <Param val="grey" valType="color" updates="constant" name="color" />
131
131
  <Param val="rgb" valType="str" updates="constant" name="colorSpace" />
@@ -190,7 +190,7 @@
190
190
  <Param val="from exp settings" valType="str" updates="None" name="units" />
191
191
  </TextboxComponent>
192
192
  <ProgressComponent name="timer5" plugin="None">
193
- <Param val="center left" valType="str" updates="constant" name="anchor" />
193
+ <Param val="center-left" valType="str" updates="constant" name="anchor" />
194
194
  <Param val="darkgrey" valType="color" updates="constant" name="borderColor" />
195
195
  <Param val="darkgrey" valType="color" updates="constant" name="color" />
196
196
  <Param val="rgb" valType="str" updates="constant" name="colorSpace" />
@@ -255,7 +255,7 @@
255
255
  <Param val="from exp settings" valType="str" updates="None" name="units" />
256
256
  </TextboxComponent>
257
257
  <ProgressComponent name="timer1" plugin="None">
258
- <Param val="center left" valType="str" updates="constant" name="anchor" />
258
+ <Param val="center-left" valType="str" updates="constant" name="anchor" />
259
259
  <Param val="lightgrey" valType="color" updates="constant" name="borderColor" />
260
260
  <Param val="lightgrey" valType="color" updates="constant" name="color" />
261
261
  <Param val="rgb" valType="str" updates="constant" name="colorSpace" />
@@ -320,7 +320,7 @@
320
320
  <Param val="from exp settings" valType="str" updates="None" name="units" />
321
321
  </TextboxComponent>
322
322
  <ProgressComponent name="trialCtr" plugin="None">
323
- <Param val="center left" valType="str" updates="constant" name="anchor" />
323
+ <Param val="center-left" valType="str" updates="constant" name="anchor" />
324
324
  <Param val="dodgerblue" valType="color" updates="constant" name="borderColor" />
325
325
  <Param val="dodgerblue" valType="color" updates="constant" name="color" />
326
326
  <Param val="rgb" valType="str" updates="constant" name="colorSpace" />
@@ -161,6 +161,14 @@ class ButtonBoxComponent(BaseDeviceComponent, PluginDevicesMixin):
161
161
  f"%(name)s.resetTimer({clockStr})\n"
162
162
  )
163
163
  buff.writeIndentedLines(code % self.params)
164
+ # clear keys
165
+ code = (
166
+ "# clear %(name)s button presses\n"
167
+ "%(name)s.buttons = []\n"
168
+ "%(name)s.times = []\n"
169
+ "%(name)s.corr = []\n"
170
+ )
171
+ buff.writeIndentedLines(code % self.params)
164
172
 
165
173
  def writeFrameCode(self, buff):
166
174
  params = self.params
@@ -201,7 +209,10 @@ class ButtonBoxComponent(BaseDeviceComponent, PluginDevicesMixin):
201
209
  # include code to get correct
202
210
  if self.params['storeCorrect']:
203
211
  code += (
204
- " %(name)s.corr.append(_thisResp.channel in %(correctAns)s)\n"
212
+ " if _thisResp.channel in %(correctAns)s or _thisResp.channel == %(correctAns)s:\n"
213
+ " %(name)s.corr.append(1)\n"
214
+ " else:\n"
215
+ " %(name)s.corr.append(0)\n"
205
216
  )
206
217
  elif self.params['store'] == "last":
207
218
  # if storing last, replace
@@ -212,7 +223,10 @@ class ButtonBoxComponent(BaseDeviceComponent, PluginDevicesMixin):
212
223
  # include code to get correct
213
224
  if self.params['storeCorrect']:
214
225
  code += (
215
- " %(name)s.corr = _thisResp.channel in %(correctAns)s\n"
226
+ " if _thisResp.channel in %(correctAns)s or _thisResp.channel == %(correctAns)s:\n"
227
+ " %(name)s.corr = 1\n"
228
+ " else:\n"
229
+ " %(name)s.corr = 0\n"
216
230
  )
217
231
  elif self.params['store'] == "first":
218
232
  # if storing first, replace but only if empty
@@ -224,7 +238,10 @@ class ButtonBoxComponent(BaseDeviceComponent, PluginDevicesMixin):
224
238
  # include code to get correct
225
239
  if self.params['storeCorrect']:
226
240
  code += (
227
- " %(name)s.corr = _thisResp.channel in %(correctAns)s\n"
241
+ " if _thisResp.channel in %(correctAns)s or _thisResp.channel == %(correctAns)s:\n"
242
+ " %(name)s.corr = 1\n"
243
+ " else:\n"
244
+ " %(name)s.corr = 0\n"
228
245
  )
229
246
  else:
230
247
  code = "pass\n"
@@ -260,15 +277,7 @@ class ButtonBoxComponent(BaseDeviceComponent, PluginDevicesMixin):
260
277
  "thisExp.addData('%(name)s.corr', %(name)s.corr)\n"
261
278
  )
262
279
  buff.writeIndentedLines(code % params)
263
- # clear keys
264
- code = (
265
- "# clear %(name)s button presses\n"
266
- "%(name)s.buttons = []\n"
267
- "%(name)s.times = []\n"
268
- "%(name)s.corr = []\n"
269
- )
270
- buff.writeIndentedLines(code % params)
271
-
280
+
272
281
 
273
282
  class KeyboardButtonBoxBackend(DeviceBackend):
274
283
  """
@@ -24,7 +24,7 @@ class ProgressComponent(BaseVisualComponent):
24
24
  progress=0,
25
25
  color="white", fillColor="None", borderColor="white", colorSpace="rgb",
26
26
  opacity=1, lineWidth=4,
27
- pos=(0, 0), size=(0.5, 0.5), anchor="center left", ori=0, units="height",
27
+ pos=(0, 0), size=(0.5, 0.5), anchor="center-left", ori=0, units="height",
28
28
  disabled=False):
29
29
 
30
30
  self.exp = exp # so we can access the experiment if necess
@@ -17,7 +17,7 @@ class PhotodiodeValidatorRoutine(BaseValidatorRoutine, PluginDevicesMixin):
17
17
 
18
18
  categories = ['Validation']
19
19
  iconFile = Path(__file__).parent / 'photodiode_validator.png'
20
- tooltip = _translate('')
20
+ tooltip = _translate('Photodiode validator')
21
21
  deviceClasses = []
22
22
  version = "2024.2.0"
23
23
 
@@ -521,7 +521,6 @@ class KeyboardDevice(BaseResponseDevice, aliases=["keyboard"]):
521
521
  elif KeyboardDevice._backend == 'iohub':
522
522
  # get events from backend (need to reverse order)
523
523
  key_events = KeyboardDevice._iohubKeyboard.getKeys(clear=True)
524
- key_events.reverse()
525
524
  # parse and receive each event
526
525
  for k in key_events:
527
526
  kpress = self.parseMessage(k)
@@ -573,7 +572,7 @@ class KeyboardDevice(BaseResponseDevice, aliases=["keyboard"]):
573
572
  if message.type == "KEYBOARD_PRESS":
574
573
  # if message is from a key down event, make a new response
575
574
  response = KeyPress(code=message.char, tDown=message.time, name=message.key)
576
- response.rt = response.tDown - self.clock.getLastResetTime()
575
+ response.rt = response.tDown - (self.clock.getLastResetTime() - self._iohubKeyboard.clock.getLastResetTime())
577
576
  self._keysStillDown.append(response)
578
577
  else:
579
578
  # if message is from a key up event, alter existing response
@@ -1,11 +1,19 @@
1
1
  import sys
2
2
  from psychopy.hardware import keyboard
3
- from pytest import skip
3
+ import pytest
4
4
  import time
5
+ from psychopy import logging
5
6
 
6
7
 
7
- class _TestKeyboard:
8
- def testMakeAndReceiveMessage(self):
8
+ class _TestBaseKeyboard:
9
+ """
10
+ Tests for the general functionality which should exist across Keyboard backends.
11
+ """
12
+ def testReceiveGeneratedKeypress(self):
13
+ """
14
+ Test that `KeyboardDevice.receiveMessage` can receive and interpret a KeyPress object
15
+ correctly, even when that object isn't linked to a physical keypress.
16
+ """
9
17
  # list of events to fake, time to fake them and state of getKeys outputs afterwards
10
18
  cases = [
11
19
  {'val': "a", 't': 0.1, 'len': 1},
@@ -24,10 +32,7 @@ class _TestKeyboard:
24
32
  """
25
33
  # skip this test on Linux (as MOP *is* slower due to having to use subprocess)
26
34
  if sys.platform == "linux":
27
- skip()
28
- # delete test kb
29
- backend = self.kb._backend
30
- del self.kb
35
+ pytest.skip()
31
36
 
32
37
  # array to store times
33
38
  times = {}
@@ -36,38 +41,170 @@ class _TestKeyboard:
36
41
 
37
42
  for mop in (True, False):
38
43
  # make new keyboard with muteOutsidePsychopy set as desired
39
- kb = keyboard.KeyboardDevice(muteOutsidePsychopy=mop)
44
+ self.kb.muteOutsidePsychopy = mop
40
45
  # start timer
41
46
  start = time.time()
42
47
  # make 10000 responses
43
48
  for n in range(nResps):
44
- kb.makeResponse(
49
+ self.kb.makeResponse(
45
50
  code="a", tDown=0
46
51
  )
47
52
  # get time
48
53
  times[mop] = time.time() - start
49
- # delete keyboard
50
- del kb
51
54
 
52
55
  # work out average difference per-response
53
56
  avg = (times[True] - times[False]) / nResps
54
57
  # make sure average difference will still be less than a frame on high performance monitors
55
58
  assert avg < 1/240
56
59
 
57
- # recreate test kb
58
- self.kb = keyboard.KeyboardDevice
60
+ def teardown_method(self):
61
+ # clear any keypresses
62
+ self.kb.getKeys(clear=True)
63
+ # set mute outside psychopy back to False
64
+ self.kb.muteOutsidePsychopy = False
65
+
66
+
67
+ class _MillikeyMixin:
68
+ """
69
+ Mixin to add tests which use a Millikey device to generate keypresses. If no such device is
70
+ connected, these tests will all skip.
71
+ """
72
+ # this attribute should be overwritten when setup_class is called
73
+ millikey = None
74
+
75
+ def setup_class(self):
76
+ """
77
+ Create a serial object to interface with a Millikey device,
78
+ """
79
+ from psychopy.hardware.serialdevice import SerialDevice
80
+ from psychopy.tools import systemtools as st
81
+
82
+ # systemtools only works on Windows so skip millikey-dependent tests on other OS's
83
+ if sys.platform != "win32":
84
+ return
59
85
 
86
+ # use systemtools to find millikey port
87
+ for profile in st.systemProfilerWindowsOS(classname="Ports", connected=True):
88
+ # identify by driver name
89
+ if "usbser.inf" not in profile['Driver Name']:
90
+ continue
91
+ # find "COM" in profile description
92
+ desc = profile['Device Description']
93
+ start = desc.find("COM") + 3
94
+ end = desc.find(")", start)
95
+ # if there's no reference to a COM port, skip
96
+ if -1 in (start, end):
97
+ continue
98
+ # get COM port number
99
+ num = desc[start:end]
100
+ # if we've got this far, create device
101
+ self.millikey = SerialDevice(f"COM{num}", baudrate=128000)
102
+ # stop looking once we've got one
103
+ break
60
104
 
61
- class TestIohubKeyboard(_TestKeyboard):
105
+ def teardown_class(self):
106
+ """
107
+ Close Millikey before finishing tests.
108
+ """
109
+ if self.millikey is not None:
110
+ self.millikey.close()
111
+
112
+ def assertMillikey(self):
113
+ """
114
+ Make sure a Millikey device is connected (and skip the current test if not)
115
+ """
116
+ # if we didn't find a device, skip current test
117
+ if self.millikey is None:
118
+ pytest.skip()
119
+
120
+ def makeMillikeyKeypress(self, key, duration, delay=0):
121
+ """
122
+ Send a trigger to the Millikey device telling to to press a particular key.
123
+
124
+ Parameters
125
+ ----------
126
+ key : str
127
+ Key to press
128
+ duration : int
129
+ Duration (ms) of the keypress
130
+ delay : int
131
+ Delay (ms) before making the keypress
132
+ """
133
+ # make sure we have a millikey device
134
+ self.assertMillikey()
135
+ # construct command (see https://blog.labhackers.com/?p=285)
136
+ cmd = "KGEN {} {} {}".format(key, duration, delay)
137
+ # send
138
+ self.millikey.sendMessage(cmd)
139
+ # read any resp1
140
+ return self.millikey.getResponse()
141
+
142
+ def testReceivePhysicalKeypress(self):
143
+ """
144
+ Test that physical keypresses are detected.
145
+
146
+ Requires a Millikey device to run.
147
+ """
148
+ self.makeMillikeyKeypress(key="a", duration=10, delay=10)
149
+ # get last message
150
+ resp = self.kb.getKeys()[-1]
151
+ # check whether the created press was received
152
+ assert resp.name == "a"
153
+
154
+ def testPhysicalKeypressTiming(self):
155
+ """
156
+ Test that timing (tDown, rt, etc.) on KeyPress objects received via a physical key press
157
+ are correct.
158
+
159
+ Requires a Millikey device to run.
160
+ """
161
+ # define tolerance (ms) for this test
162
+ tolerance = 4
163
+ # try a few times to make sure times aren't cumulative
164
+ for ans, dur, rt in [
165
+ ("a", 123, 456),
166
+ ("b", 456, 123),
167
+ ("c", 123, 123),
168
+ ("d", 456, 456),
169
+ ]:
170
+ # reset keyboard clock
171
+ self.kb.clock.reset()
172
+ # wait for rt
173
+ time.sleep(rt / 1000)
174
+ # store start time
175
+ start = logging.defaultClock.getTime()
176
+ # make a keypress
177
+ self.makeMillikeyKeypress(key=ans, duration=dur)
178
+ # wait for press to finish
179
+ time.sleep(dur / 500)
180
+ # get last message
181
+ resp = self.kb.getKeys()[-1]
182
+ # check correct key
183
+ assert resp.name == ans
184
+ # check correct rt
185
+ assert abs(resp.rt - rt / 1000) <= tolerance / 1000
186
+ # check correct duration
187
+ assert abs(resp.duration - dur / 1000) <= tolerance / 1000
188
+ # check correct start time
189
+ assert abs(resp.tDown - start) <= tolerance / 1000
190
+
191
+
192
+ class TestIohubKeyboard(_TestBaseKeyboard, _MillikeyMixin):
62
193
  def setup_method(self):
63
194
  self.kb = keyboard.KeyboardDevice(backend="iohub", muteOutsidePsychopy=False)
64
195
 
65
196
 
66
- class TestPtbKeyboard(_TestKeyboard):
197
+ class TestPtbKeyboard(_TestBaseKeyboard, _MillikeyMixin):
67
198
  def setup_method(self):
68
199
  self.kb = keyboard.KeyboardDevice(backend="ptb", muteOutsidePsychopy=False)
69
200
 
201
+ def teardown_method(self):
202
+ self.kb.getKeys(clear=True)
203
+
70
204
 
71
- class TestEventKeyboard(_TestKeyboard):
205
+ class TestEventKeyboard(_TestBaseKeyboard, _MillikeyMixin):
72
206
  def setup_method(self):
73
207
  self.kb = keyboard.KeyboardDevice(backend="event", muteOutsidePsychopy=False)
208
+
209
+ def teardown_method(self):
210
+ self.kb.getKeys(clear=True)
@@ -83,7 +83,7 @@ class Progress(shape.ShapeStim):
83
83
  def __init__(
84
84
  self, win, name="pb",
85
85
  progress=0, direction="horizontal",
86
- pos=(-.5, 0), size=(1, 0.1), anchor="center left", units=None,
86
+ pos=(-.5, 0), size=(1, 0.1), anchor="center-left", units=None,
87
87
  barColor=False, backColor=False, borderColor=False, colorSpace=None,
88
88
  lineWidth=1.5, opacity=1.0, ori=0.0,
89
89
  depth=0, autoLog=None, autoDraw=False,
psychopy/web.py CHANGED
@@ -7,6 +7,7 @@
7
7
  # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2024 Open Science Tools Ltd.
8
8
  # Distributed under the terms of the GNU General Public License (GPL).
9
9
 
10
+ import pathlib
10
11
  import sys
11
12
  import socket
12
13
  import re
@@ -115,8 +116,10 @@ def getPacFiles():
115
116
  pacFiles.append(subkeys['AutoConfigURL'])
116
117
  elif sys.platform == 'darwin':
117
118
  import plistlib
118
- sysPrefs = plistlib.readPlist('/Library/Preferences/System'
119
- 'Configuration/preferences.plist')
119
+ prefs_loc = pathlib.Path('/Library/Preferences/SystemConfiguration/preferences.plist')
120
+ if prefs_loc.exists():
121
+ with open(prefs_loc, 'rb') as fp :
122
+ sysPrefs = plistlib.loads(fp.read())
120
123
  networks = sysPrefs['NetworkServices']
121
124
  # loop through each possible network (e.g. Ethernet, Airport...)
122
125
  for network in list(networks.items()):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: psychopy
3
- Version: 2024.1.3
3
+ Version: 2024.1.4
4
4
  Summary: PsychoPy provides easy, precise, flexible experiments in behavioural sciences
5
5
  Author-Email: Open Science Tools Ltd <support@opensciencetools.org>
6
6
  Maintainer-Email: Open Science Tools Ltd <support@opensciencetools.org>
@@ -1,12 +1,12 @@
1
- psychopy-2024.1.3.dist-info/METADATA,sha256=Dgf2hQgHlVrGjHGkRlF_xx0N_lUO9X6FETfx-vdWyic,6993
2
- psychopy-2024.1.3.dist-info/WHEEL,sha256=7sv5iXvIiTVJSnAxCz2tGBm9DHsb2vPSzeYeT7pvGUY,90
3
- psychopy-2024.1.3.dist-info/entry_points.txt,sha256=1LXVqRMSILrbEagrzpJDtmXyEPHX3GnpBJ85TEnxuoI,56
4
- psychopy-2024.1.3.dist-info/licenses/AUTHORS.md,sha256=MmZf-GmSBscBa_z7ePoqYxbaGe6XOJnld_s6JIQGfS4,2395
5
- psychopy-2024.1.3.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
1
+ psychopy-2024.1.4.dist-info/METADATA,sha256=fDCS681nI8qyi-KWW8r5C0-9COz7XzsvfWVXnTU_dsY,6993
2
+ psychopy-2024.1.4.dist-info/WHEEL,sha256=vnE8JVcI2Wz7GRKorsPArnBdnW2SWKWGow5gu5tHlRU,90
3
+ psychopy-2024.1.4.dist-info/entry_points.txt,sha256=1LXVqRMSILrbEagrzpJDtmXyEPHX3GnpBJ85TEnxuoI,56
4
+ psychopy-2024.1.4.dist-info/licenses/AUTHORS.md,sha256=MmZf-GmSBscBa_z7ePoqYxbaGe6XOJnld_s6JIQGfS4,2395
5
+ psychopy-2024.1.4.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
6
6
  psychopy/CHANGELOG.txt,sha256=bRyB9AEemUO4KBYhtBOIWOaXFmX9X3pHgMMF9QyeITA,203527
7
7
  psychopy/LICENSE.txt,sha256=d2HeFOYbuXc2LZobE1EkFq3lYV5ge3YSaTL3y1r7KQc,746
8
8
  psychopy/LICENSES.txt,sha256=T59KljDkUEEtd40IHWS-S0OTSjzqueGD6oNmgqpRIf0,3145
9
- psychopy/__init__.py,sha256=TaSpE94UGKdQ0J3pbhPIO_aH4HsJ3AlNIdFspPjwik0,2757
9
+ psychopy/__init__.py,sha256=Ui1G3d_Pxm-Ywc1gHe96JBFCD82M4IacVgxhkLGyHqU,2757
10
10
  psychopy/alerts/__init__.py,sha256=buvC7HFn71FhIp1D4XGXkZLeNLk22uO9TSQsxLlYZqU,2178
11
11
  psychopy/alerts/_alerts.py,sha256=IMHMXY1mzTCmlOYhHW0_Upb9oAcYzzTWe44BUNXj-ec,6120
12
12
  psychopy/alerts/_errorHandler.py,sha256=JNkdx3OJv0PeAeARG09Rgne7dH-aGgUdxdoriDd4KW4,1501
@@ -919,7 +919,7 @@ psychopy/app/builder/dialogs/dlgsCode.py,sha256=e6L80eZjVidfL3UwCLsGpha1uBJkfi3g
919
919
  psychopy/app/builder/dialogs/dlgsConditions.py,sha256=Q0yQaZCuWAMXKYboe4wiOrfFJxhr6rrhzvV00ZU16F8,29203
920
920
  psychopy/app/builder/dialogs/findDlg.py,sha256=XNixASyu0cUDRNuwxeixwA0U7-05QVmqJw2GfnexLwk,6839
921
921
  psychopy/app/builder/dialogs/paramCtrls.py,sha256=wWv2OB_ho1fLNTuOBvzh_oiI7CCbgLPd63QfSCTbMrY,47654
922
- psychopy/app/builder/localizedStrings.py,sha256=WRKzpvfRjJXoGRUrLhlbYDtyMXulLGUeyRZB5KvkU04,8973
922
+ psychopy/app/builder/localizedStrings.py,sha256=nmXSLbpYhKWjGxPXKvwWmkY3foAIWVt0p1m0jM2wRUw,9043
923
923
  psychopy/app/builder/validators.py,sha256=9UNzKWZbza_8E9zptgZ9RiXEEpKQLyL8OnHkZMdQH74,21342
924
924
  psychopy/app/coder/__init__.py,sha256=hF476K91n-eIQmcyIKtOTM5Wwu5TOAni2mjg7dATlqA,164
925
925
  psychopy/app/coder/codeEditorBase.py,sha256=-y5ZtDeEV6KKCFzOFo4O3KlrHVUJ3UEiIQFHvp6aj64,18016
@@ -979,8 +979,8 @@ psychopy/app/locale/hu_HU/LC_MESSAGE/messages.mo,sha256=YL0OkWylqScel5-55e0UOTbr
979
979
  psychopy/app/locale/hu_HU/LC_MESSAGE/messages.po,sha256=lUwWIx2w6yCg1oSFolOAGoWTYq6gilECmOe8MzmSU1c,750
980
980
  psychopy/app/locale/it_IT/LC_MESSAGE/messages.mo,sha256=ZKMzzkn-3x5ctpBDJv25-S-4Q9dlaVD8MDgCBhJDbpg,625
981
981
  psychopy/app/locale/it_IT/LC_MESSAGE/messages.po,sha256=Hn2PHcXpyupdKp1vWZLV0T5Th1hSyaY59d7f0mVNE0c,247774
982
- psychopy/app/locale/ja_JP/LC_MESSAGE/messages.mo,sha256=bds8RYcMc7mbDAhhxlsTbp4QA4FWrGYRaur-fC_84bI,217288
983
- psychopy/app/locale/ja_JP/LC_MESSAGE/messages.po,sha256=hsCH_HHmVCePxYYJdY5BLn3RDB8H9OfPTKARZhyqD4g,326294
982
+ psychopy/app/locale/ja_JP/LC_MESSAGE/messages.mo,sha256=aH5GhAQmHkaHqj3KpiL9dsAgWvcAGU6DYCqTr1L2aPw,217528
983
+ psychopy/app/locale/ja_JP/LC_MESSAGE/messages.po,sha256=ZjOPBBkeyTZd_z1yHv_1X92T_7QonM1dMT7iPhpgiOM,326647
984
984
  psychopy/app/locale/ko_KR/LC_MESSAGE/messages.mo,sha256=aH0Bw3Wg0KaxWPYu9pNfA8zLizw2fCg6YP191aL63Us,561
985
985
  psychopy/app/locale/ko_KR/LC_MESSAGE/messages.po,sha256=Og8xPQ0fmSCKOMp-rFBiPDAACi56C8LdjH7mFuVTwoA,719
986
986
  psychopy/app/locale/ms_MY/LC_MESSAGE/messages.mo,sha256=IbykycFb3cwbl7OOa9-iJemo7ep92PiV5pEtPse4SrA,2213
@@ -1017,7 +1017,7 @@ psychopy/app/plugin_manager/__init__.py,sha256=bSD1HYo2TXCFMith4-erfzv_PHP6p-qhB
1017
1017
  psychopy/app/plugin_manager/dialog.py,sha256=YW5OfmQ79cPOZ40Vx1yctKy5gDth4Q4qQw1VOw4Dm_I,15102
1018
1018
  psychopy/app/plugin_manager/output.py,sha256=BUfmvr7EGkDJlj97wku-GKI_vhzx2mNGCAepUHlzyRc,4045
1019
1019
  psychopy/app/plugin_manager/packages.py,sha256=gykd4LcQJVU5jexhYsoQDeplXBpFo1GQOOS_Yzmz56Q,20072
1020
- psychopy/app/plugin_manager/plugins.py,sha256=ode_ST9o-VcW3sTRQ7NM4ElE3oVJQKnmwY1sthzgF-M,47525
1020
+ psychopy/app/plugin_manager/plugins.py,sha256=1ULbiIG89uVE9qvuBgI00-XwZWvD-J5k7V_2PilKj3s,47705
1021
1021
  psychopy/app/plugin_manager/utils.py,sha256=2xEcau7amzOXs9P2QZbLeuvN_437ttyCWYCKC-lCGG4,4267
1022
1022
  psychopy/app/preferencesDlg.py,sha256=Y476Y_GRp2FUOtZL8o3u2ktVoNPNx3B6fpsxnfJ70Es,32028
1023
1023
  psychopy/app/psychopyApp.py,sha256=71Hn-zIRzukQmFhN4H6UMCTf6DQFE5eQ8JdFIMaeh0o,3369
@@ -1169,7 +1169,7 @@ psychopy/demos/builder/Feature Demos/noise/noise.psyexp,sha256=awd_ocUQyLKDrcX8o
1169
1169
  psychopy/demos/builder/Feature Demos/noise/readme.md,sha256=380VfNp6kH-rwYvf2-MafaFPEV98xi9B0XuRQQUwgs0,121
1170
1170
  psychopy/demos/builder/Feature Demos/panorama/panImg.jpg,sha256=oOlPPTaGBVsiMZ3iBHFO7k1JDZRRMRGsok9CGEtOULE,14084972
1171
1171
  psychopy/demos/builder/Feature Demos/panorama/panorama.psyexp,sha256=P-3WLaKPXEsSMkgiGvv6rEWmmTh6RXhv1z_eCfLMyyo,10578
1172
- psychopy/demos/builder/Feature Demos/progress/progressBar.psyexp,sha256=W-jOKd6EOy-zVgn16O0khGov2qP2yUhBDoCAMQ7woDE,31782
1172
+ psychopy/demos/builder/Feature Demos/progress/progressBar.psyexp,sha256=m5jQrfb61APm32KvzdpXvHZnn2HpsZRxo0XAbeJoRKs,31782
1173
1173
  psychopy/demos/builder/Feature Demos/progress/readme.md,sha256=eMIuawrNMyfOzV9-BNvmfYHWAD9hjsjaNWqf_BMuxQE,264
1174
1174
  psychopy/demos/builder/Feature Demos/sliders/README.md,sha256=DESTwlzvnTKU7Pmtx26E5L3McMLjeJv4z_TfjrzX9tU,394
1175
1175
  psychopy/demos/builder/Feature Demos/sliders/fruitConditions.xlsx,sha256=XVronDakp0VkWNB_dMDwLBR8CmIUa44CYZcyajeOq80,11587
@@ -1357,7 +1357,7 @@ psychopy/experiment/components/button/dark/button.png,sha256=SBAbSgqTPCYaAZTZUzL
1357
1357
  psychopy/experiment/components/button/dark/button@2x.png,sha256=rOaQQiDzIod3CJOS-9QB03FG3ftNTc0qYxwn2hAgnVU,2189
1358
1358
  psychopy/experiment/components/button/light/button.png,sha256=96qG9x_4BgTmLhlrEJgG5NnxYIKFsowgOMSX_FBg4WM,1124
1359
1359
  psychopy/experiment/components/button/light/button@2x.png,sha256=UaoRfEq-FAfsPW7DQ7TqXH9XEMOfKfrI2BnKTaLHx0M,2179
1360
- psychopy/experiment/components/buttonBox/__init__.py,sha256=wezkhrhV7pESyDpz9eq4at_HJZwpIQ8wYxw0wJRfTqE,11900
1360
+ psychopy/experiment/components/buttonBox/__init__.py,sha256=-jrtsdw3FYFs-ROHLia94GQ2bDuAjFYgj4DBnfSWym4,12382
1361
1361
  psychopy/experiment/components/buttonBox/classic/buttonBox.png,sha256=mPWJ3fiZ9lbHMxDuC5NOOH4oXuKdApEThXfXcRro4Y4,2672
1362
1362
  psychopy/experiment/components/buttonBox/classic/buttonBox@2x.png,sha256=G64Vfyg4Cie1MRf_1wNN8Xr23VolKsNLLQTGXoWRn8k,6094
1363
1363
  psychopy/experiment/components/buttonBox/dark/buttonBox.png,sha256=G3JfdQ3zLSRTSTz0t6GfKkt7ihEhhw2AJs0u_FGTwSs,1259
@@ -1487,7 +1487,7 @@ psychopy/experiment/components/polygon/dark/polygon.png,sha256=6ZCyor1NM4i7kLpXy
1487
1487
  psychopy/experiment/components/polygon/dark/polygon@2x.png,sha256=GVoiBNpjoSPRFIKoqc542SyWssn53exU3qyPqtRYD2w,1608
1488
1488
  psychopy/experiment/components/polygon/light/polygon.png,sha256=D2UXeVnUpQIEL4vizve-T93NckPTHu8_jDeRZPPAvLU,890
1489
1489
  psychopy/experiment/components/polygon/light/polygon@2x.png,sha256=NAmC9ZRAEgG1CZIdfjEEEMP0EZuPzp6i927enCtF8QM,1610
1490
- psychopy/experiment/components/progress/__init__.py,sha256=c4-FPLGOymVwUjX7N3yzYk44dqOkzp1OUy1WONX4q7g,5516
1490
+ psychopy/experiment/components/progress/__init__.py,sha256=Xxyk3m-wbYor_kF4eR2YHyj-m1cJue4xu8rDZ65uv9g,5516
1491
1491
  psychopy/experiment/components/progress/classic/progress.png,sha256=Gp4am-n_1PAv8fk8W0lrHZzaIe4FkjAUMVNFjJ242Mc,1224
1492
1492
  psychopy/experiment/components/progress/classic/progress@2x.png,sha256=bv1QzZVgbvRXn0Hcppyk3znleGJi2mCVQVWnlXXm_RI,2394
1493
1493
  psychopy/experiment/components/progress/dark/progress.png,sha256=mHkbscXItnKvZY5AL8lzjjRvTDWcxr1hKJe3ibmsz-0,852
@@ -1636,7 +1636,7 @@ psychopy/experiment/routines/pavlovia_survey/dark/survey.png,sha256=YHJAx4LHLurS
1636
1636
  psychopy/experiment/routines/pavlovia_survey/dark/survey@2x.png,sha256=avsdFSmD-qy_Mnj-NMacvECqw4BEqeC9aRFSxf9sRYU,3947
1637
1637
  psychopy/experiment/routines/pavlovia_survey/light/survey.png,sha256=ojzaoqGK6qIehsj2ElkHEq1J526YZBcGtqlDgQD0LqI,2141
1638
1638
  psychopy/experiment/routines/pavlovia_survey/light/survey@2x.png,sha256=0S0VB_qSJjiBJNtNVb9oQChCFb9HCwvb8j1K76ERf4E,3969
1639
- psychopy/experiment/routines/photodiodeValidator/__init__.py,sha256=DE3OHRrzVGQZTnXy_88BC-8HKy65cbfzMOsTBoIjQwI,15899
1639
+ psychopy/experiment/routines/photodiodeValidator/__init__.py,sha256=tOf6TXE6mnHQPYTfWJK-TT4AqsEhreXOWkRE59S6rFg,15919
1640
1640
  psychopy/experiment/routines/photodiodeValidator/classic/photodiode_validator.png,sha256=P9XtMKUVN-xKXqf7OgTvfjzJfTq0WgYEJu3vLR1_DT0,4837
1641
1641
  psychopy/experiment/routines/photodiodeValidator/classic/photodiode_validator@2x.png,sha256=pLoUU7IzKlZ_uOHA_0xA0ZXRa7Np7ocXMS8c8EGW4U8,13416
1642
1642
  psychopy/experiment/routines/photodiodeValidator/dark/photodiode_validator.png,sha256=yg85iyoPTMm34XBvPeak3ZKK0aXoqQkWnkFGK5xdDhc,1690
@@ -1683,7 +1683,7 @@ psychopy/hardware/forp.py,sha256=P19o4cmrZD4kHhJwNT0kj5LR-F4kdwXSu5GpYyiis4U,135
1683
1683
  psychopy/hardware/gammasci.py,sha256=odRzQ1kKduDqrQshp582YtKnXnSFPXWc8qic9jjPZMc,1000
1684
1684
  psychopy/hardware/iolab.py,sha256=8fqy-xGe15naHLgYfxELpes5ooNDTUytLTTz9_NhTi0,1067
1685
1685
  psychopy/hardware/joystick/__init__.py,sha256=wBhX_21kRPAlKM2UyEZBYBKhDCfiLHIp-K7r_2bDorI,19109
1686
- psychopy/hardware/keyboard.py,sha256=enf7nluy1w3_SYA2B2mCrVY0Cx3ytM5BjtXdkIjiLqk,34192
1686
+ psychopy/hardware/keyboard.py,sha256=jjsTdovR7m0--XkkCFeM74J1fODua4Issmx71DJXPUI,34208
1687
1687
  psychopy/hardware/knownDevices.json,sha256=rGsTu0MaBdUTUA6bwCKU9D-J03i0oFPDWOw28Eu4Ik0,1791
1688
1688
  psychopy/hardware/labhackers.py,sha256=_fRtMUtSd5f2DXRVgVsXQdF3x9ZDFypXcuxaD0J1C0E,864
1689
1689
  psychopy/hardware/labjacks.py,sha256=CQfxgty2uGdG2bzkcbfw-pKBzxHlnSSVfcPHKlsOC8E,980
@@ -2774,7 +2774,7 @@ psychopy/tests/test_hardware/test_CRS_bitsShaders.py,sha256=zjzFyA6K889xdIzExY0-
2774
2774
  psychopy/tests/test_hardware/test_device_manager.py,sha256=iLbRKaiR_fVaPob6Pj2p7pSGRJkHU2OTdUyfRIQD4jo,1240
2775
2775
  psychopy/tests/test_hardware/test_emulator.py,sha256=3JlvxVM6SlqWRQYITI2XkjOjd_wMtaWvajkFMerichE,4227
2776
2776
  psychopy/tests/test_hardware/test_gammasci.py,sha256=bwoesGbNHzcwz6x3wNqXPu4Ahk0PzSzpXsK-KK2c2xw,1140
2777
- psychopy/tests/test_hardware/test_keyboard.py,sha256=JEdlSFd0B67p-kTnKqSvJPF5hxw-uCYHBbgsjuP85us,2421
2777
+ psychopy/tests/test_hardware/test_keyboard.py,sha256=iL_3m1zQ1XfmAoujvM4ZRJ6yHLexpd_6HbqSyGJ1nKU,7244
2778
2778
  psychopy/tests/test_hardware/test_keyboard_events.py,sha256=z_-ERHgMMtMs_AaCLWllOz8dm1IGg-_qjJyJuiLYkeo,10995
2779
2779
  psychopy/tests/test_hardware/test_ports.py,sha256=jvwP1tboaxySZUmGyKFb7SdDPXziVI_ky3_rw0BHvm8,4934
2780
2780
  psychopy/tests/test_iohub/__init__.py,sha256=XWwudbQJpOsGyIVAq5MW_kkSE6pvoG4D6ztzdVIvL-I,19
@@ -2916,7 +2916,7 @@ psychopy/visual/panorama.py,sha256=8B96YTS5lxMoFO1feUaCLEXD7oERR3J0Pr4Kgi2UJdM,1
2916
2916
  psychopy/visual/patch.py,sha256=UMD6JG1WuM1PK7Lam679tbyUltXxWbvd1IdIqwGbreQ,1007
2917
2917
  psychopy/visual/pie.py,sha256=oIgisD1x1TmKHxLautG89cnbleaGUqSZVejuYDFl6VQ,9732
2918
2918
  psychopy/visual/polygon.py,sha256=ldp7bcj3vobHZwoVt2WfVsXEL078x-Y339IEJD84-zI,9444
2919
- psychopy/visual/progress.py,sha256=zWEW1A21znqgmljTXBSt-kpLCWtjTRBxUQp1KsIOppo,10661
2919
+ psychopy/visual/progress.py,sha256=VH6W9pcZG5PXKrga7YTV6ugeiGM8kNXNc5Bmio4mciY,10661
2920
2920
  psychopy/visual/radial.py,sha256=kraRjPnrkhhJ9V5w3qJUVZQwIWgwpXXBqBpmZn8NMU8,1288
2921
2921
  psychopy/visual/ratingscale.py,sha256=6BGdR0neA-HI4b32qwVaFUM-2RNSib-9KSpjtokqVaY,65386
2922
2922
  psychopy/visual/rect.py,sha256=PNjf2CJsAAR1hdwdCA6swG5QokzHAG6sL9AITgihEDM,8555
@@ -2947,5 +2947,5 @@ psychopy/voicekey/labjack_vks.py,sha256=PPTpdAON8I7zdPevls8SIMH9_ZfJ14gSL01A5UVD
2947
2947
  psychopy/voicekey/parallel_vks.py,sha256=I6a07GvN0Q2k9xidl9YbEUDORG2v9l2H_5Owbpw_xzY,1464
2948
2948
  psychopy/voicekey/signal.py,sha256=Mk363qVsvJampVDfsOTdGq7lPESlKmogmNFqasdghJE,1013
2949
2949
  psychopy/voicekey/vk_tools.py,sha256=pFvOvF9b9CfS-JkZ_fv38LxI59hJXQqiz9ymcrJiAFc,8483
2950
- psychopy/web.py,sha256=ohiFb7lW1-0pH_62cR-z8ufZ5Nta2jRIjGS4_zosX_U,10228
2951
- psychopy-2024.1.3.dist-info/RECORD,,
2950
+ psychopy/web.py,sha256=TaN6joXx_NmyMUP6NqLYk66yMMUV2nlSEPGByPqvzFM,10328
2951
+ psychopy-2024.1.4.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: pdm-backend (2.2.1)
2
+ Generator: pdm-backend (2.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any