示例#1
0
 def setup_class(cls):
     cls.exp = experiment.Experiment() # create once, not every test
     try:
         cls.tempDir = mkdtemp(dir=Path(__file__).root, prefix='psychopy-tests-app')
     except (PermissionError, OSError):
         # can't write to root on Linux
         cls.tempDir = mkdtemp(prefix='psychopy-tests-app')
示例#2
0
    def loadExperiment(self):
        """
        Load the experiment object for the current psyexp file.

        Returns
        -------
        PsychoPy Experiment object
        """
        fileName = str(self.currentFile)
        if not os.path.exists(fileName):
            raise FileNotFoundError("File not found: {}".format(fileName))

        # If not a Builder file, return
        if not fileName.endswith('.psyexp'):
            return None

        # Load experiment file
        exp = experiment.Experiment(prefs=self.app.prefs)
        try:
            exp.loadFromXML(fileName)
        except Exception:
            print(u"Failed to load {}. Please send the following to"
                  u" the PsychoPy user list".format(fileName))
            traceback.print_exc()

        return exp
示例#3
0
    def test_get_info(self):
        # List of values for expInfo fields, with expected compiled values for python and js
        cases = [
            # Function call with multiple inputs
            {
                'val': 'randint(0, 999)',
                'py': "randint(0, 999)",
                'js': "util.randint(0, 999)"
            }
        ]

        # Construct exp with one big expInfo string from cases
        exp = experiment.Experiment()
        exp.settings.params['Experiment info'].val = "{"
        i = 0
        for case in cases:
            exp.settings.params[
                'Experiment info'].val += f"'{i}': '{case['val']}',"
            i += 1
        exp.settings.params['Experiment info'].val += "}"

        # Compile to py
        pyScript = exp.writeScript(target="PsychoPy")
        # Check py
        expInfoStr = pyScript.split("expInfo = {")[1]
        expInfoStr = expInfoStr.split("}")[0]
        i = 0
        for case in cases:
            wanted = f"'{i}': {case['py']},"
            assert wanted in expInfoStr, (f"Could not find `{wanted}` in ```\n"
                                          f"{expInfoStr}\n"
                                          f"```")
            i += 1
示例#4
0
    def test_handled_resources_removed(self):
        """
        Check that resources handled by a static component are removed from the start of the experiment
        """
        cases = [
            # Resource handled by static component, no loop present
            {
                'exp':
                "handledbystatic_noloop",
                'seek': [],
                'avoid': [
                    'blue.png', 'white.png', 'yellow.png', 'groups.csv',
                    'groupA.csv', 'groupB.csv'
                ]
            },
            # Resource handled by static component, loop defined by string
            {
                'exp':
                "handledbystatic_strloop",
                'seek': ['groupA.csv'],
                'avoid': [
                    'blue.png', 'white.png', 'yellow.png', 'groupB.csv',
                    'groups.csv'
                ]
            },
            # Resource handled by static component, loop defined by constructed string
            {
                'exp': "handledbystatic_constrloop",
                'seek': ['groupA.csv', 'groupB.csv', 'groups.csv'],
                'avoid': ['blue.png', 'white.png', 'yellow.png']
            },
            # Resource handled by static component, loop defined by constructed string from loop
            {
                'exp': "handledbystatic_recurloop",
                'seek': ['groupA.csv', 'groupB.csv', 'groups.csv'],
                'avoid': ['blue.png', 'white.png', 'yellow.png']
            },
        ]

        exp = experiment.Experiment()
        for case in cases:
            # Load experiment
            exp.loadFromXML(
                Path(TESTS_DATA_PATH) / "test_get_resources" /
                (case['exp'] + ".psyexp"))
            # Write to JS
            script = exp.writeScript(target="PsychoJS")
            # Check that all "seek" phrases are included
            for phrase in case['seek']:
                assert _find_global_resource_in_js_experiment(
                    script, phrase
                ), (f"'{phrase}' was not found in resources for {case['exp']}.psyexp"
                    )
            # Check that all "avoid" phrases are excluded
            for phrase in case['avoid']:
                assert not _find_global_resource_in_js_experiment(
                    script, phrase
                ), (f"'{phrase}' was found in resources for {case['exp']}.psyexp"
                    )
示例#5
0
 def test_stroop(self):
     #load experiment
     exp = experiment.Experiment()
     exp.loadFromXML(join(demosDir, 'builder', 'stroop', 'stroop.psyexp'))
     # try once packaging up the js libs
     exp.settings.params['JS libs'].val = 'remote'
     outFolder = join(self.temp_dir, 'stroopJS_remote/html')
     os.makedirs(outFolder)
     self.writeScript(exp, outFolder)
示例#6
0
 def test_blocked(self):
     # load experiment
     exp = experiment.Experiment()
     exp.loadFromXML(demosDir/'builder/understandingPsychopy/images_blocks/blockedTrials.psyexp')
     # try once packaging up the js libs
     exp.settings.params['JS libs'].val = 'packaged'
     outFolder = self.temp_dir/'blocked_packaged/html'
     os.makedirs(outFolder)
     self.writeScript(exp, outFolder)
     print("files in {}".format(outFolder))
示例#7
0
 def test_blocked(self):
     # load experiment
     exp = experiment.Experiment()
     exp.loadFromXML(demosDir/'builder'/'Design Templates'/'randomisedBlocks'/'randomisedBlocks.psyexp')
     # try once packaging up the js libs
     exp.settings.params['JS libs'].val = 'packaged'
     outFolder = self.temp_dir/'blocked_packaged/html'
     os.makedirs(outFolder)
     self.writeScript(exp, outFolder)
     print("files in {}".format(outFolder))
示例#8
0
 def test_blocked(self):
     # load experiment
     exp = experiment.Experiment()
     exp.loadFromXML(join(demosDir, 'builder', 'images_blocks',
                          'blockedTrials.psyexp'))
     # try once packaging up the js libs
     exp.settings.params['JS libs'].val = 'packaged'
     outFolder = join(self.temp_dir, 'blocked_packaged')
     self.writeScript(exp, outFolder)
     print("files in {}".format(outFolder))
示例#9
0
    def setup_class(cls):
        """
        Load and run various experiments just once and use the objects / output in later tests
        """
        # Setup temporary dir
        try:
            cls.tempDir = mkdtemp(dir=Path(__file__).root,
                                  prefix='psychopy-tests-loops')
        except (PermissionError, OSError):
            # can't write to root on Linux
            cls.tempDir = mkdtemp(prefix='psychopy-tests-loops')
        # List of filenames for experiments to run
        filenames = [
            'testLoopsBlocks', 'testStaircase', 'test_current_loop_attr'
        ]
        # Run each experiment to get data
        cls.cases = {}
        for filename in filenames:
            # Copy file to temp dir so it's in the same folder as we want data to output to
            ogExpFile = Path(
                TESTS_DATA_PATH) / "test_loops" / f"{filename}.psyexp"
            expFile = Path(cls.tempDir) / f"{filename}.psyexp"
            shutil.copy(ogExpFile, expFile)
            # Load experiment from file
            exp = experiment.Experiment()
            exp.loadFromXML(expFile)
            # Change data file output to temp dir
            datafile = (Path(cls.tempDir) / "data" / f"{filename}.csv")
            exp.settings.params[
                'Data filename'].val = f"'data' + os.sep + '{filename}'"
            # Write scripts
            pyScript = exp.writeScript(target="PsychoPy")
            # jsScript = exp.writeScript(target="PsychoJS")  # disabled until all loops work in JS
            # Save Python script to temp dir
            pyScriptFile = Path(cls.tempDir) / f"{filename}.py"
            with codecs.open(str(pyScriptFile), 'w', 'utf-8-sig') as f:
                f.write(pyScript)

            # Run Python script to generate data file
            stdout, stderr = core.shellCall(
                [sys.executable, str(pyScriptFile)], stderr=True)
            # Load data file
            with open(datafile, "rb") as f:
                data = np.recfromcsv(f, case_sensitive=True)

            # Store
            cls.cases[filename] = {
                'exp': exp,
                'pyScript': pyScript,
                # 'jsScript': jsScript,  # disabled until all loops work in JS
                'data': data,
                'stdout': stdout,
                'stderr': stderr,
            }
示例#10
0
    def setup_class(cls):
        cls.expPy = experiment.Experiment()  # create once, not every test
        cls.expJS = experiment.Experiment()
        cls.here = Path(__file__).parent
        cls.baselineProfile = cls.here / profile

        # should not need a wx.App with fetchIcons=False
        try:
            cls.allComp = getAllComponents(fetchIcons=False)
        except Exception:
            import wx
            if parse_version(wx.__version__) < parse_version('2.9'):
                tmpApp = wx.PySimpleApp()
            else:
                tmpApp = wx.App(False)
            try:
                from psychopy.app import localization
            except Exception:
                pass  # not needed if can't import it
            cls.allComp = getAllComponents(fetchIcons=False)
 def test_onlineExtraResources(self):
     """Open an experiment with resources in the format of 2020.5
     (i.e. broken with \\ and with .. at start)"""
     expFile = (testsDataDir /
                'broken2020_2_5_resources/broken_resources.psyexp')
     exp = experiment.Experiment()
     exp.loadFromXML(expFile)
     resList = exp.settings.params['Resources'].val
     print(resList)
     assert type(resList) == list
     assert (not resList[0].startswith('..'))
示例#12
0
 def setup(self):
     # Make blank experiment
     self.exp = experiment.Experiment()
     # Make blank routine
     self.routine = experiment.routines.Routine(name="testRoutine",
                                                exp=self.exp)
     self.exp.addRoutine("testRoutine", self.routine)
     self.exp.flow.addRoutine(self.routine, 0)
     # Make Resource Manager component
     self.comp = ResourceManagerComponent(exp=self.exp,
                                          parentName="testRoutine",
                                          name="testResourceManager")
     self.routine.addComponent(self.comp)
示例#13
0
 def setup(self):
     # Make blank experiment
     self.exp = experiment.Experiment()
     # Make blank routine
     self.routine = experiment.routines.Routine(name="testRoutine",
                                                exp=self.exp)
     self.exp.addRoutine("testRoutine", self.routine)
     self.exp.flow.addRoutine(self.routine, 0)
     # Make Static component
     self.comp = StaticComponent(exp=self.exp,
                                 parentName="testRoutine",
                                 name="testStatic")
     self.routine.addComponent(self.comp)
示例#14
0
 def test_stroop(self):
     #load experiment
     exp = experiment.Experiment()
     exp.loadFromXML(join(demosDir, 'builder','stroop','stroop.psyexp'))
     # try once packaging up the js libs
     exp.settings.params['JS libs'].val = 'packaged'
     outFolder = join(self.temp_dir, 'stroopJS_packaged')
     self.writeScript(exp, outFolder)
     # try once packaging up the js libs
     exp.settings.params['JS libs'].val = 'remote'
     outFolder = join(self.temp_dir, 'stroopJS_remote')
     self.writeScript(exp, outFolder)
     print("files in {}".format(outFolder))
示例#15
0
 def setup(self):
     # Make blank experiment
     self.exp = experiment.Experiment()
     # Make blank routine
     self.routine = Routine(name="testRoutine", exp=self.exp)
     self.exp.addRoutine("testRoutine", self.routine)
     self.exp.flow.addRoutine(self.routine, 0)
     # Add loop around routine
     self.loop = TrialHandler(exp=self.exp, name="testLoop")
     self.exp.flow.addLoop(self.loop, 0, -1)
     # Make Mouse component
     self.comp = CodeComponent(exp=self.exp, parentName="testRoutine", name="testCode")
     self.routine.addComponent(self.comp)
示例#16
0
 def test_JS_script_output(self):
     # Load experiment
     exp = experiment.Experiment()
     exp.loadFromXML(join(demosDir, 'builder', 'stroop', 'stroop.psyexp'))
     outFolder = join(self.temp_dir, 'stroopJS_output/html')
     outFile = os.path.join(outFolder, 'stroop.js')
     os.makedirs(outFolder)
     # Compile scripts
     assert(self.compileScript(infile=exp, version=None, outfile=outFile))
     # Test whether files are written
     assert(os.path.isfile(os.path.join(outFolder, 'stroop.js')))
     assert(os.path.isfile(os.path.join(outFolder, 'stroop-legacy-browsers.js')))
     assert(os.path.isfile(os.path.join(outFolder, 'index.html')))
     assert(os.path.isdir(os.path.join(outFolder, 'resources')))
示例#17
0
    def test_writing(self):
        # Create simple experiment with a Polygon
        exp = experiment.Experiment()
        rt = experiment.routines.Routine(name="testRoutine", exp=exp)
        exp.addRoutine("testRoutine", rt)
        exp.flow.addRoutine(rt, 0)
        comp = polygon.PolygonComponent(exp=exp, parentName="testRoutine")
        rt.addComponent(comp)
        # Set use version
        exp.settings.params['Use version'].val = "2021.1.4"
        # Save experiment
        exp.saveToXML(str(self.temp / "versionText.psyexp"))

        # --- Python ---
        # Write script
        scriptFile = str(self.temp / "versionText.py")
        generateScript(
            experimentPath=scriptFile,
            exp=exp,
            target="PsychoPy"
        )
        # Read script
        with open(scriptFile, "r") as f:
            script = f.read()
        # Get args passed to comp
        args = script.split(f"{comp.name} = visual.ShapeStim(")[1]
        args = args.split(")")[0]
        # If using 2021.1.4, there shouldn't be any "anchor" arg in ShapeStim, as it wasn't implemented yet
        assert "anchor" not in args, (
            "When compiling Py with useversion 2021.1.4, found 'anchor' argument in ShapeStim; this was not "
            "implemented in requested version."
        )

        # --- JS ---
        # Write script
        scriptFile = str(self.temp / "versionText.js")
        generateScript(
            experimentPath=scriptFile,
            exp=exp,
            target="PsychoJS"
        )
        # Read script
        with open(scriptFile, "r") as f:
            script = f.read()
        # Check for correct version import statement
        assert "import { PsychoJS } from './lib/core-2021.1.4.js'" in script, (
            "When compiling JS with useversion 2021.1.4, could not find version-specific import statement."
        )
示例#18
0
def _make_minimal_experiment(obj):
    """
    Make a minimal experiment with just one routine, the same class as the current standalone routine but with all
    default params.
    """
    # Skip whole test if required attributes aren't present
    if not hasattr(obj, "rt"):
        pytest.skip()
    # Make blank experiment
    exp = experiment.Experiment()
    # Create instance of this component with all default params
    rtClass = type(obj.rt)
    rt = rtClass(exp=exp, name=f"test{rtClass.__name__}")
    exp.addStandaloneRoutine(rt.name, rt)
    exp.flow.addRoutine(rt, 0)
    # Return experiment, routine and component
    return rt, exp
示例#19
0
 def setup(self):
     # Make a basic experiment with one routine
     self.exp = experiment.Experiment()
     self.rt = self.exp.addRoutine("testRoutine")
     self.exp.flow.addRoutine(self.rt, 0)
     # Add one of every component to that routine (default params)
     for compName, compClass in experiment.getAllComponents().items():
         if compClass != SettingsComponent:
             comp = compClass(exp=self.exp,
                              parentName=self.rt.name,
                              name=f"test{compName}")
             self.rt.append(comp)
     # Add one of every standalone routine
     for rtName, rtClass in experiment.getAllStandaloneRoutines().items():
         rt = rtClass(exp=self.exp, name=f"test{rtName}")
         self.exp.addStandaloneRoutine(rt.name, rt)
     # Add all routines to the flow
     for rt in self.exp.routines.values():
         self.exp.flow.addRoutine(rt, 0)
示例#20
0
def _make_minimal_experiment(obj):
    """
    Make a minimal experiment with just one routine containing just one component, of the same class as the current
    component but with all default params.
    """
    # Skip whole test if required attributes aren't present
    if not hasattr(obj, "comp"):
        pytest.skip()
    # Make blank experiment
    exp = experiment.Experiment()
    rt = exp.addRoutine(routineName='TestRoutine')
    exp.flow.addRoutine(rt, 0)
    # Create instance of this component with all default params
    compClass = type(obj.comp)
    comp = compClass(exp=exp,
                     parentName='TestRoutine',
                     name=f"test{compClass.__name__}")
    rt.append(comp)
    # Return experiment, routine and component
    return comp, rt, exp
示例#21
0
    def setup_class(cls):
        cls.exp = experiment.Experiment()  # create once, not every test
        cls.here = os.path.abspath(os.path.dirname(__file__))
        cls.baselineProfile = os.path.join(cls.here, profile)

        # should not need a wx.App with fetchIcons=False
        try:
            cls.allComp = getAllComponents(fetchIcons=False)
        except Exception:
            import wx
            if parse_version(wx.__version__) < parse_version('2.9'):
                tmpApp = wx.PySimpleApp()
            else:
                tmpApp = wx.App(False)
            try:
                from psychopy.app import localization
            except Exception:
                pass  # not needed if can't import it
            cls.allComp = getAllComponents(fetchIcons=False)

        cls.origProjectCatalog = projects.projectCatalog
        projects.projectCatalog = {}
示例#22
0
 def test_xml(self):
     isTime = re.compile(r"\d+:\d+(:\d+)?( [AP]M)?")
     # Get all psyexp files in demos folder
     demosFolder = Path(self.exp.prefsPaths['demos']) / 'builder'
     for file in demosFolder.glob("**/*.psyexp"):
         # Create experiment and load from psyexp
         exp = experiment.Experiment()
         exp.loadFromXML(file)
         # Compile to get what script should look like
         target = exp.writeScript()
         # Save as XML
         temp = str(Path(self.tempDir) / "testXML.psyexp")
         exp.saveToXML(temp)
         # Load again
         exp.loadFromXML(temp)
         # Compile again
         test = exp.writeScript()
         # Remove any timestamps from script (these can cause false errors if compile takes longer than a second)
         test = re.sub(isTime, "", test)
         target = re.sub(isTime, "", target)
         # Compare two scripts to make sure saving and loading hasn't changed anything
         diff = difflib.unified_diff(target.splitlines(), test.splitlines())
         assert list(diff) == []
示例#23
0
 def __init__(self, compClass):
     self.exp = experiment.Experiment()
     self.rt = experiment.routines.Routine(exp=self.exp, name="testRoutine")
     self.comp = compClass(exp=self.exp,
                           parentName="testRoutine",
                           name=f"test{compClass.__name__}")
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# this script replaces hashtags with a sphinx URL string (to the github issues or pull request)
# written by Jon with regex code by Jeremy

from __future__ import absolute_import, print_function
import os
from psychopy import experiment, __version__
from pathlib import Path

thisFolder = Path(__file__).parent

nFiles = 0
for root, dirs, files in os.walk(thisFolder.parent / "psychopy/demos/builder"):
    for filename in files:
        if filename.endswith('.psyexp'):

            filepath = os.path.join(root, filename)
            exp = experiment.Experiment()
            exp.loadFromXML(filepath)
            origVersion = exp.psychopyVersion
            exp.psychopyVersion = __version__
            exp.saveToXML(filepath)
            print("switching {} from {} to {}".format(filepath, origVersion,
                                                      __version__))
示例#25
0
 def __init__(self, rtClass):
     self.exp = experiment.Experiment()
     self.rt = rtClass(exp=self.exp, name=f"test{rtClass.__name__}")
示例#26
0
def test_flip_before_shutdown_in_settings_component():
    exp = experiment.Experiment()
    script = exp.writeScript()

    assert 'Flip one final time' in script
示例#27
0
 def setup(self):
     # Create experiment
     self.exp = experiment.Experiment()
     self.exp.addRoutine(
         "testRoutine", experiment.routines.Routine("testRoutine",
                                                    self.exp))
示例#28
0
 def setup_class(cls):
     cls.routines = experiment.getAllStandaloneRoutines()
     # Make basic experiments with one of each standalone routine
     cls.expPy = experiment.Experiment()
     cls.expJS = experiment.Experiment()
 def setup(self):
     self.exp = experiment.Experiment()
     self.rt = EyetrackerCalibrationRoutine(
         exp=self.exp, name="testEyetrackerCalibrationRoutine")
示例#30
0
    def test_add_routine(self):
        exp = experiment.Experiment()

        # Test adding a regular routine
        rt = exp.addRoutine(f"testRoutine")
        # Check that the routine name is present
        assert rt.name in exp.routines
        # Check that the routine is a Routine
        assert isinstance(
            exp.routines[rt.name], experiment.routines.Routine
        ), (f"Routine {rt.name} should be Routine but was {type(exp.routines[rt.name]).__name__}"
            )
        # Test adding standalone routines
        for rtName, rtClass in experiment.getAllStandaloneRoutines().items():
            # Make and add standalone routine of this type
            rt = rtClass(exp=exp, name=f"test{rtClass.__name__}")
            exp.addStandaloneRoutine(rt.name, rt)
            # Check that the routine name is present
            assert rt.name in exp.routines, f"Could not find {rtClass.__name__} in experiment after adding"
            # Check that the routine is a Routine
            assert isinstance(exp.routines[rt.name], rtClass), (
                f"Routine {rt.name} should be {rtClass.__name__} but was {type(exp.routines[rt.name]).__name__}"
            )

        # Check that none of these routines are in the flow yet
        for rtName, rt in exp.routines.items():
            assert rt not in exp.flow, (
                f"Routine {rtName} of type {type(rt).__name__} found in experiment flow before being added"
            )
        # Check that none of these routines appear in the compiled script yet
        pyScript = exp.writeScript(target="PsychoPy")
        jsScript = exp.writeScript(target="PsychoJS")
        for rtName, rt in exp.routines.items():
            if "PsychoPy" in type(rt).targets:
                assert rtName not in pyScript, (
                    f"Routine {rtName} of type {type(rt).__name__} found in Python script before being added to flow"
                )
            if "PsychoJS" in type(rt).targets:
                assert rtName not in jsScript, (
                    f"Routine {rtName} of type {type(rt).__name__} found in JS script before being added to flow"
                )

        # Add routines to flow
        for rtName, rt in exp.routines.items():
            exp.flow.addRoutine(rt, 0)
        # Check that they are in flow now
        for rtName, rt in exp.routines.items():
            assert rt in exp.flow, (
                f"Routine {rtName} of type {type(rt).__name__} not found in experiment flow after being added"
            )
        # Check that all of these routines appear in the compiled script yet
        pyScript = exp.writeScript(target="PsychoPy")
        jsScript = exp.writeScript(target="PsychoJS")
        for rtName, rt in exp.routines.items():
            if "PsychoPy" in type(rt).targets:
                assert rtName in pyScript, (
                    f"Routine {rtName} of type {type(rt).__name__} not found in Python script after being added to flow"
                )
            if "PsychoJS" in type(rt).targets:
                assert rtName in jsScript, (
                    f"Routine {rtName} of type {type(rt).__name__} not found in JS script after being added to flow"
                )