psychopy 2024.1.2__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.

Files changed (34) hide show
  1. psychopy/__init__.py +2 -2
  2. psychopy/app/builder/localizedStrings.py +11 -9
  3. psychopy/app/locale/ja_JP/LC_MESSAGE/messages.mo +0 -0
  4. psychopy/app/locale/ja_JP/LC_MESSAGE/messages.po +359 -346
  5. psychopy/app/plugin_manager/plugins.py +7 -0
  6. psychopy/demos/builder/Feature Demos/progress/progressBar.psyexp +4 -4
  7. psychopy/experiment/components/buttonBox/__init__.py +21 -12
  8. psychopy/experiment/components/mouse/__init__.py +12 -0
  9. psychopy/experiment/components/progress/__init__.py +1 -1
  10. psychopy/experiment/routines/counterbalance/__init__.py +1 -1
  11. psychopy/experiment/routines/photodiodeValidator/__init__.py +1 -1
  12. psychopy/hardware/keyboard.py +1 -2
  13. psychopy/tests/test_experiment/test_components/__init__.py +1 -1
  14. psychopy/tests/test_experiment/test_components/{test_ButtonBox.py → test_ButtonBoxComponent.py} +9 -27
  15. psychopy/tests/test_experiment/test_components/{test_Code.py → test_CodeComponent.py} +8 -20
  16. psychopy/tests/test_experiment/test_components/test_GratingComponent.py +7 -0
  17. psychopy/tests/test_experiment/test_components/test_ImageComponent.py +8 -0
  18. psychopy/tests/test_experiment/test_components/{test_Mouse.py → test_MouseComponent.py} +44 -57
  19. psychopy/tests/test_experiment/test_components/{test_Polygon.py → test_PolygonComponent.py} +9 -25
  20. psychopy/tests/test_experiment/test_components/{test_ResourceManager.py → test_ResourceManagerComponent.py} +3 -13
  21. psychopy/tests/test_experiment/test_components/{test_Settings.py → test_SettingsComponent.py} +1 -3
  22. psychopy/tests/test_experiment/test_components/{test_Static.py → test_StaticComponent.py} +3 -12
  23. psychopy/tests/test_experiment/test_components/test_all_components.py +8 -66
  24. psychopy/tests/test_experiment/test_components/test_base_components.py +212 -125
  25. psychopy/tests/test_hardware/test_keyboard.py +153 -16
  26. psychopy/visual/progress.py +1 -1
  27. psychopy/web.py +5 -2
  28. {psychopy-2024.1.2.dist-info → psychopy-2024.1.4.dist-info}/METADATA +2 -2
  29. {psychopy-2024.1.2.dist-info → psychopy-2024.1.4.dist-info}/RECORD +33 -32
  30. {psychopy-2024.1.2.dist-info → psychopy-2024.1.4.dist-info}/WHEEL +1 -1
  31. psychopy/tests/test_experiment/test_components/test_Image.py +0 -24
  32. {psychopy-2024.1.2.dist-info → psychopy-2024.1.4.dist-info}/entry_points.txt +0 -0
  33. {psychopy-2024.1.2.dist-info → psychopy-2024.1.4.dist-info}/licenses/AUTHORS.md +0 -0
  34. {psychopy-2024.1.2.dist-info → psychopy-2024.1.4.dist-info}/licenses/LICENSE +0 -0
@@ -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
  """
@@ -364,10 +364,22 @@ class MouseComponent(BaseComponent):
364
364
  buff.writeIndentedLines(code % self.params)
365
365
  buff.setIndentLevel(1, relative=True)
366
366
  dedent += 1
367
+ # keep track of whether something's been written
368
+ hasContent = False
369
+ # write code to check clickable stim, if there are any
367
370
  if self.params['clickable'].val:
368
371
  self._writeClickableObjectsCode(buff)
372
+ hasContent = True
373
+ # write code to check correct stim, if there are any
369
374
  if self.params['storeCorrect']:
370
375
  self._writeCorrectAnsCode(buff)
376
+ hasContent = True
377
+ # if current if statement has no content, add a pass
378
+ if not hasContent:
379
+ buff.writeIndentedLines(
380
+ "pass"
381
+ )
382
+
371
383
  return buff, dedent
372
384
 
373
385
  # No mouse tracking, end routine on any or valid click
@@ -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
@@ -43,7 +43,7 @@ class CounterbalanceRoutine(BaseStandaloneRoutine):
43
43
  self.params['specMode'] = Param(
44
44
  specMode, valType="str", inputType="choice", categ="Basic",
45
45
  allowedVals=["uniform", "file"],
46
- allowedLabels=[_translate("Num. groups"), _translate("Conditions file")],
46
+ allowedLabels=[_translate("Num. groups"), _translate("Conditions file (local only)")],
47
47
  label=_translate("Groups from..."),
48
48
  hint=_translate(
49
49
  "Specify groups using an Excel file (for fine tuned control), specify as a variable name, or specify a "
@@ -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
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 +1 @@
1
- from .test_base_components import _TestBaseComponentsMixin, _TestDisabledMixin
1
+ from .test_base_components import BaseComponentTests
@@ -11,21 +11,14 @@ from psychopy.hardware.button import ButtonResponse
11
11
  from psychopy.experiment.routines import Routine
12
12
  from psychopy.experiment.components.buttonBox import ButtonBoxComponent
13
13
  from psychopy.experiment.components.code import CodeComponent
14
- from .test_base_components import _TestBaseComponentsMixin
14
+ from psychopy.tests.test_experiment.test_components.test_base_components import BaseComponentTests
15
+ from psychopy.hardware.button import ButtonBox
15
16
 
16
17
 
17
- class TestButtonBoxComponent(_TestBaseComponentsMixin):
18
- def setup_method(self):
19
- self.exp = Experiment()
20
- # make blank routine
21
- self.routine = Routine(name="testRoutine", exp=self.exp)
22
- self.exp.addRoutine("testRoutine", self.routine)
23
- self.exp.flow.addRoutine(self.routine, 0)
24
- # make component
25
- self.comp = ButtonBoxComponent(
26
- exp=self.exp, name="testPhotodiodeValidatorRoutine", parentName="testRoutine"
27
- )
28
-
18
+ class TestButtonBoxComponent(BaseComponentTests):
19
+ comp = ButtonBoxComponent
20
+ libraryClass = ButtonBox
21
+
29
22
  def test_values(self):
30
23
  """
31
24
  Test that a variety of different values work when run from Builder.
@@ -65,9 +58,8 @@ class TestButtonBoxComponent(_TestBaseComponentsMixin):
65
58
  thisCase[keys[i]] = val
66
59
  # add case
67
60
  cases.append(thisCase)
68
-
69
- # make an experiment
70
- exp = Experiment()
61
+ # make minimal experiment just for this test
62
+ comp, rt, exp = self.make_minimal_experiment()
71
63
  # configure experiment
72
64
  exp.requireImport("ButtonResponse", importFrom="psychopy.hardware.button")
73
65
  exp.settings.params['Full-screen window'].val = False
@@ -79,18 +71,8 @@ class TestButtonBoxComponent(_TestBaseComponentsMixin):
79
71
  resps = case.pop("resps")
80
72
  if not isinstance(resps, (list, tuple)):
81
73
  resps = [resps]
82
- # make a name
83
- name = f"rt{i}"
84
- # make a Routine
85
- rt = exp.addRoutine(name, Routine(name=name, exp=exp))
86
- exp.flow.addRoutine(rt, 0)
87
74
  # add timeout
88
75
  rt.settings.params['stopVal'].val = 0.2
89
- # make a Component
90
- comp = ButtonBoxComponent(
91
- exp, parentName=name, name=name + "_comp", **case
92
- )
93
- rt.addComponent(comp)
94
76
  # make a Code Component to send responses
95
77
  code = (
96
78
  "if frameN > 1:\n"
@@ -104,7 +86,7 @@ class TestButtonBoxComponent(_TestBaseComponentsMixin):
104
86
  name=comp.name, value=resp.value, channel=resp.channel
105
87
  )
106
88
  codeComp = CodeComponent(
107
- exp, parentName=name + "_code", eachFrame=code
89
+ exp, parentName=comp.name + "_code", eachFrame=code
108
90
  )
109
91
  rt.addComponent(codeComp)
110
92
  # save exp in temp directory
@@ -2,42 +2,30 @@ from pathlib import Path
2
2
  from tempfile import mkdtemp
3
3
 
4
4
  from psychopy import experiment
5
- from . import _TestDisabledMixin, _TestBaseComponentsMixin
5
+ from . import BaseComponentTests
6
6
  from psychopy.experiment.loops import TrialHandler
7
7
  from psychopy.experiment.routines import Routine
8
8
  from psychopy.experiment.components.code import CodeComponent
9
9
  from psychopy.tests.utils import TESTS_DATA_PATH
10
10
 
11
11
 
12
- class TestCodeComponent(_TestBaseComponentsMixin, _TestDisabledMixin):
12
+ class TestCodeComponent(BaseComponentTests):
13
13
  """
14
14
  Test that Code coponents have the correct params and write as expected.
15
15
  """
16
+ comp = CodeComponent
16
17
 
17
18
  @classmethod
18
19
  def setup_class(cls):
19
- cls.exp = experiment.Experiment() # create once, not every test
20
20
  try:
21
21
  cls.tempDir = mkdtemp(dir=Path(__file__).root, prefix='psychopy-tests-app')
22
22
  except (PermissionError, OSError):
23
23
  # can't write to root on Linux
24
24
  cls.tempDir = mkdtemp(prefix='psychopy-tests-app')
25
25
 
26
- def setup_method(self):
27
- # Make blank experiment
28
- self.exp = experiment.Experiment()
29
- # Make blank routine
30
- self.routine = Routine(name="testRoutine", exp=self.exp)
31
- self.exp.addRoutine("testRoutine", self.routine)
32
- self.exp.flow.addRoutine(self.routine, 0)
33
- # Add loop around routine
34
- self.loop = TrialHandler(exp=self.exp, name="testLoop")
35
- self.exp.flow.addLoop(self.loop, 0, -1)
36
- # Make Mouse component
37
- self.comp = CodeComponent(exp=self.exp, parentName="testRoutine", name="testCode")
38
- self.routine.addComponent(self.comp)
39
-
40
26
  def test_all_code_component_tabs(self):
27
+ # make minimal experiment just for this test
28
+ comp, rt, exp = self.make_minimal_experiment()
41
29
  # Names of each tab in a Code component
42
30
  tabs = {
43
31
  'Before Experiment': '___before_experiment___',
@@ -50,11 +38,11 @@ class TestCodeComponent(_TestBaseComponentsMixin, _TestDisabledMixin):
50
38
  # Add markers to component
51
39
  for paramName, marker in tabs.items():
52
40
  jsParamName = paramName.replace(" ", " JS ")
53
- self.comp.params[paramName].val = self.comp.params[jsParamName].val = marker
41
+ comp.params[paramName].val = comp.params[jsParamName].val = " = ".join([self.comp.__name__, comp.name, marker])
54
42
 
55
43
  # Write script
56
- pyScript = self.exp.writeScript(target="PsychoPy")
57
- jsScript = self.exp.writeScript(target="PsychoJS")
44
+ pyScript = exp.writeScript(target="PsychoPy")
45
+ jsScript = exp.writeScript(target="PsychoJS")
58
46
 
59
47
  # Check that code from each tab exists in compiled script
60
48
  for lang, script in {"Python": pyScript, "JS": jsScript}.items():
@@ -0,0 +1,7 @@
1
+ from psychopy.tests.test_experiment.test_components.test_base_components import BaseComponentTests, _TestLibraryClassMixin
2
+ from psychopy.experiment.components.grating import GratingComponent
3
+ from psychopy.visual import GratingStim
4
+
5
+ class TestGratingComponent(BaseComponentTests, _TestLibraryClassMixin):
6
+ comp = GratingComponent
7
+ libraryClass = GratingStim
@@ -0,0 +1,8 @@
1
+ from psychopy.experiment.components.image import ImageComponent
2
+ from psychopy.tests.test_experiment.test_components.test_base_components import BaseComponentTests, _TestDepthMixin, _TestLibraryClassMixin
3
+ from psychopy.visual.image import ImageStim
4
+
5
+
6
+ class TestImage(BaseComponentTests, _TestLibraryClassMixin):
7
+ comp = ImageComponent
8
+ libraryClass = ImageStim
@@ -1,65 +1,52 @@
1
1
  from pathlib import Path
2
2
 
3
- from . import _TestDisabledMixin, _TestBaseComponentsMixin
4
- from psychopy.experiment import Experiment
3
+ from . import BaseComponentTests
5
4
  from psychopy.experiment.loops import TrialHandler
6
- from psychopy.experiment.routines import Routine
7
5
  from psychopy.experiment.components.mouse import MouseComponent
8
6
  from psychopy.experiment.components.polygon import PolygonComponent
9
7
  from psychopy.tests.utils import TESTS_DATA_PATH
10
8
  from psychopy.hardware.mouse import Mouse
11
9
 
12
10
 
13
- class TestMouseComponent(_TestBaseComponentsMixin, _TestDisabledMixin):
11
+ class TestMouseComponent(BaseComponentTests):
14
12
  """
15
13
  Test that Mouse coponents have the correct params and write as expected.
16
14
  """
15
+ comp = MouseComponent
17
16
  libraryClass = Mouse
18
17
 
19
- def setup_method(self):
20
- # Make blank experiment
21
- self.exp = Experiment()
22
- # Make blank routine
23
- self.routine = Routine(name="testRoutine", exp=self.exp)
24
- self.exp.addRoutine("testRoutine", self.routine)
25
- self.exp.flow.addRoutine(self.routine, 0)
26
- # Add loop around routine
27
- self.loop = TrialHandler(exp=self.exp, name="testLoop")
28
- self.exp.flow.addLoop(self.loop, 0, -1)
29
- # Make Mouse component
30
- self.comp = MouseComponent(exp=self.exp, parentName="testRoutine", name="testMouse")
31
- self.routine.addComponent(self.comp)
32
- # Make a rect for when we need something to click on
33
- self.target = PolygonComponent(exp=self.exp, parentName="testRoutine", name="testPolygon")
34
- self.routine.addComponent(self.target)
35
-
36
18
  def test_click_save_end_clickable_cases(self):
37
19
  """
38
20
  Test all combinations of options for what to save, what can be clicked on & what kind of clicks to end the
39
21
  routine on.
40
22
  """
23
+ # make minimal experiment just for this test
24
+ comp, rt, exp = self.make_minimal_experiment()
25
+ # make a rect for when we need something to click on
26
+ target = PolygonComponent(exp=exp, parentName=rt.name, name="testPolygon")
27
+
41
28
  saveMouseStateCases = [
42
29
  {'val': "final",
43
- 'want': ["thisExp.addData('testMouse.x', x)"], # should contain code for adding final value of x
44
- 'avoid': ["testMouse.x.append(x)"]}, # should not contain code to update testMouse.x in frame loop
30
+ 'want': [f"thisExp.addData('{comp.name}.x', x)"], # should contain code for adding final value of x
31
+ 'avoid': [f"{comp.name}.x.append(x)"]}, # should not contain code to update testMouse.x in frame loop
45
32
  {'val': "on click",
46
- 'want': ["thisExp.addData('testMouse.x', testMouse.x)", # should add testMouse.x at the end
47
- "testMouse.x.append(x)"], # should contain code to update testMouse.x in frame loop
48
- 'avoid': ["thisExp.addData('testMouse.x', x)"]}, # should not add final value of x
33
+ 'want': [f"thisExp.addData('{comp.name}.x', {comp.name}.x)", # should add testMouse.x at the end
34
+ f"{comp.name}.x.append(x)"], # should contain code to update testMouse.x in frame loop
35
+ 'avoid': [f"thisExp.addData('{comp.name}.x', x)"]}, # should not add final value of x
49
36
  {'val': "on valid click",
50
- 'want': ["thisExp.addData('testMouse.x', testMouse.x)", # should add testMouse.x at the end
51
- "testMouse.x.append(x)", # should contain code to update testMouse.x in frame loop
37
+ 'want': [f"thisExp.addData('{comp.name}.x', {comp.name}.x)", # should add testMouse.x at the end
38
+ f"{comp.name}.x.append(x)", # should contain code to update testMouse.x in frame loop
52
39
  "if gotValidClick:"], # should check for valid clicks
53
- 'avoid': ["thisExp.addData('testMouse.x', x)"]}, # should not add final value of x
40
+ 'avoid': [f"thisExp.addData('{comp.name}.x', x)"]}, # should not add final value of x
54
41
  {'val': "every frame",
55
- 'want': ["thisExp.addData('testMouse.x', testMouse.x)", # should add testMouse.x at the end
56
- "testMouse.x.append(x)"], # should contain code to update testMouse.x in frame loop
57
- 'avoid': ["thisExp.addData('testMouse.x', x)"]}, # should not add final value of x
42
+ 'want': [f"thisExp.addData('{comp.name}.x', {comp.name}.x)", # should add testMouse.x at the end
43
+ f"{comp.name}.x.append(x)"], # should contain code to update testMouse.x in frame loop
44
+ 'avoid': [f"thisExp.addData('{comp.name}.x', x)"]}, # should not add final value of x
58
45
  {'val': "never",
59
46
  'want': [],
60
- 'avoid': ["thisExp.addData('testMouse.x', testMouse.x)", # should not add testMouse.x at the end
61
- "testMouse.x.append(x)", # should not contain code to update testMouse.x in frame loop
62
- "thisExp.addData('testMouse.x', x)"]}, # should not add final value of x]},
47
+ 'avoid': [f"thisExp.addData('{comp.name}.x', {comp.name}.x)", # should not add testMouse.x at the end
48
+ f"{comp.name}.x.append(x)", # should not contain code to update testMouse.x in frame loop
49
+ f"thisExp.addData('{comp.name}.x', x)"]}, # should not add final value of x]},
63
50
  ]
64
51
  forceEndRoutineOnPressCases = [
65
52
  {'val': "never",
@@ -85,54 +72,54 @@ class TestMouseComponent(_TestBaseComponentsMixin, _TestDisabledMixin):
85
72
  # Iterate through saveMouseState cases
86
73
  for SMScase in saveMouseStateCases:
87
74
  # Set saveMouseState
88
- self.comp.params['saveMouseState'].val = SMScase['val']
75
+ comp.params['saveMouseState'].val = SMScase['val']
89
76
  for FEROPcase in forceEndRoutineOnPressCases:
90
77
  # Set forceEndRoutineOnPress
91
- self.comp.params['forceEndRoutineOnPress'].val = FEROPcase['val']
78
+ comp.params['forceEndRoutineOnPress'].val = FEROPcase['val']
92
79
  for Ccase in clickableCases:
93
80
  # Set clickable
94
- self.comp.params['clickable'].val = Ccase['val']
81
+ comp.params['clickable'].val = Ccase['val']
95
82
 
96
83
  # Compile script
97
- script = self.exp.writeScript(target="PsychoPy")
84
+ script = exp.writeScript(target="PsychoPy")
98
85
  try:
99
86
  # Look for wanted phrases
100
87
  for phrase in SMScase['want']:
101
88
  assert phrase in script, (
102
- f"{phrase} not found in script when saveMouseState={self.comp.params['saveMouseState']}, "
103
- f"forceEndRoutineOnPress={self.comp.params['forceEndRoutineOnPress']} and "
104
- f"clickable={self.comp.params['clickable']}"
89
+ f"{phrase} not found in script when saveMouseState={comp.params['saveMouseState']}, "
90
+ f"forceEndRoutineOnPress={comp.params['forceEndRoutineOnPress']} and "
91
+ f"clickable={comp.params['clickable']}"
105
92
  )
106
93
  for phrase in FEROPcase['want']:
107
94
  assert phrase in script, (
108
- f"{phrase} not found in script when saveMouseState={self.comp.params['saveMouseState']}, "
109
- f"forceEndRoutineOnPress={self.comp.params['forceEndRoutineOnPress']} and "
110
- f"clickable={self.comp.params['clickable']}"
95
+ f"{phrase} not found in script when saveMouseState={comp.params['saveMouseState']}, "
96
+ f"forceEndRoutineOnPress={comp.params['forceEndRoutineOnPress']} and "
97
+ f"clickable={comp.params['clickable']}"
111
98
  )
112
99
  for phrase in Ccase['want']:
113
100
  assert phrase in script, (
114
- f"{phrase} not found in script when saveMouseState={self.comp.params['saveMouseState']}, "
115
- f"forceEndRoutineOnPress={self.comp.params['forceEndRoutineOnPress']} and "
116
- f"clickable={self.comp.params['clickable']}"
101
+ f"{phrase} not found in script when saveMouseState={comp.params['saveMouseState']}, "
102
+ f"forceEndRoutineOnPress={comp.params['forceEndRoutineOnPress']} and "
103
+ f"clickable={comp.params['clickable']}"
117
104
  )
118
105
  # Check there's no avoid phrases
119
106
  for phrase in SMScase['avoid']:
120
107
  assert phrase not in script, (
121
- f"{phrase} found in script when saveMouseState={self.comp.params['saveMouseState']}, "
122
- f"forceEndRoutineOnPress={self.comp.params['forceEndRoutineOnPress']} and "
123
- f"clickable={self.comp.params['clickable']}"
108
+ f"{phrase} found in script when saveMouseState={comp.params['saveMouseState']}, "
109
+ f"forceEndRoutineOnPress={comp.params['forceEndRoutineOnPress']} and "
110
+ f"clickable={comp.params['clickable']}"
124
111
  )
125
112
  for phrase in FEROPcase['avoid']:
126
113
  assert phrase not in script, (
127
- f"{phrase} found in script when saveMouseState={self.comp.params['saveMouseState']}, "
128
- f"forceEndRoutineOnPress={self.comp.params['forceEndRoutineOnPress']} and "
129
- f"clickable={self.comp.params['clickable']}"
114
+ f"{phrase} found in script when saveMouseState={comp.params['saveMouseState']}, "
115
+ f"forceEndRoutineOnPress={comp.params['forceEndRoutineOnPress']} and "
116
+ f"clickable={comp.params['clickable']}"
130
117
  )
131
118
  for phrase in Ccase['avoid']:
132
119
  assert phrase not in script, (
133
- f"{phrase} found in script when saveMouseState={self.comp.params['saveMouseState']}, "
134
- f"forceEndRoutineOnPress={self.comp.params['forceEndRoutineOnPress']} and "
135
- f"clickable={self.comp.params['clickable']}"
120
+ f"{phrase} found in script when saveMouseState={comp.params['saveMouseState']}, "
121
+ f"forceEndRoutineOnPress={comp.params['forceEndRoutineOnPress']} and "
122
+ f"clickable={comp.params['clickable']}"
136
123
  )
137
124
  except AssertionError as err:
138
125
  # If any assertion fails, save script to view
@@ -1,37 +1,21 @@
1
- from pathlib import Path
2
-
3
- from . import _TestDisabledMixin, _TestBaseComponentsMixin
4
- from psychopy.experiment import Experiment
5
- from psychopy.experiment.loops import TrialHandler
6
- from psychopy.experiment.routines import Routine
1
+ from psychopy.tests.test_experiment.test_components.test_base_components import BaseComponentTests, _TestLibraryClassMixin
7
2
  from psychopy.experiment.components.polygon import PolygonComponent
8
3
  from psychopy.visual.polygon import Polygon
9
4
 
10
5
 
11
- class TestPolygonComponent(_TestBaseComponentsMixin, _TestDisabledMixin):
6
+ class TestPolygonComponent(BaseComponentTests, _TestLibraryClassMixin):
12
7
  """
13
8
  Test that Polygon coponents have the correct params and write as expected.
14
9
  """
10
+ comp = PolygonComponent
15
11
  libraryClass = Polygon
16
12
 
17
- def setup_method(self):
18
- # Make blank experiment
19
- self.exp = Experiment()
20
- # Make blank routine
21
- self.routine = Routine(name="testRoutine", exp=self.exp)
22
- self.exp.addRoutine("testRoutine", self.routine)
23
- self.exp.flow.addRoutine(self.routine, 0)
24
- # Add loop around routine
25
- self.loop = TrialHandler(exp=self.exp, name="testLoop")
26
- self.exp.flow.addLoop(self.loop, 0, -1)
27
- # Make a rect for when we need something to click on
28
- self.comp = PolygonComponent(exp=self.exp, parentName="testRoutine", name="testPolygon")
29
- self.routine.addComponent(self.comp)
30
-
31
13
  def test_vertices_usage(self):
32
14
  """
33
15
  Test that vertices values are used only under the correct conditions
34
16
  """
17
+ # make minimal experiment just for this test
18
+ comp, rt, exp = self.make_minimal_experiment()
35
19
  # Define values to look for and avoid in code according to value of shape
36
20
  cases = [
37
21
  # Shape is a line
@@ -61,14 +45,14 @@ class TestPolygonComponent(_TestBaseComponentsMixin, _TestDisabledMixin):
61
45
  'avoid': ["___nVertices___"]},
62
46
  ]
63
47
  # Setup component with markers for nVertices and vertices
64
- self.comp.params['nVertices'].val = "___nVertices___"
65
- self.comp.params['vertices'].val = "___vertices___"
48
+ comp.params['nVertices'].val = "___nVertices___"
49
+ comp.params['vertices'].val = "___vertices___"
66
50
  # Test each case
67
51
  for case in cases:
68
52
  # Set shape
69
- self.comp.params['shape'].val = case['val']
53
+ comp.params['shape'].val = case['val']
70
54
  # Write experiment
71
- pyScript = self.exp.writeScript(target="PsychoPy")
55
+ pyScript = exp.writeScript(target="PsychoPy")
72
56
  # Look for sought values in experiment script
73
57
  for seekVal in case['seek']:
74
58
  assert seekVal in pyScript, (
@@ -1,23 +1,13 @@
1
1
  from pathlib import Path
2
2
 
3
- from . import _TestBaseComponentsMixin, _TestDisabledMixin
4
- from .test_base_components import _find_global_resource_in_js_experiment
3
+ from psychopy.tests.test_experiment.test_components.test_base_components import BaseComponentTests, _find_global_resource_in_js_experiment
5
4
  from psychopy.experiment.components.resourceManager import ResourceManagerComponent
6
5
  from psychopy import experiment
7
6
  from ...utils import TESTS_DATA_PATH
8
7
 
9
8
 
10
- class TestResourceManagerComponent(_TestBaseComponentsMixin, _TestDisabledMixin):
11
- def setup_method(self):
12
- # Make blank experiment
13
- self.exp = experiment.Experiment()
14
- # Make blank routine
15
- self.routine = experiment.routines.Routine(name="testRoutine", exp=self.exp)
16
- self.exp.addRoutine("testRoutine", self.routine)
17
- self.exp.flow.addRoutine(self.routine, 0)
18
- # Make Resource Manager component
19
- self.comp = ResourceManagerComponent(exp=self.exp, parentName="testRoutine", name="testResourceManager")
20
- self.routine.addComponent(self.comp)
9
+ class TestResourceManagerComponent(BaseComponentTests):
10
+ comp = ResourceManagerComponent
21
11
 
22
12
  def test_handled_resources_removed(self):
23
13
  """
@@ -1,13 +1,11 @@
1
1
  from pathlib import Path
2
2
 
3
- from . import _TestBaseComponentsMixin, _TestDisabledMixin
4
3
  from .test_base_components import _find_global_resource_in_js_experiment
5
- from psychopy.experiment.components.settings import SettingsComponent
6
4
  from psychopy import experiment
7
5
  from ...utils import TESTS_DATA_PATH
8
6
 
9
7
 
10
- class TestSettingsComponent(_TestBaseComponentsMixin):
8
+ class TestSettingsComponent:
11
9
  def test_unhandled_resources_js(self):
12
10
  """
13
11
  Check that resources not otherwise handled are present at the start of the experiment