Esempio n. 1
0
def openOutputFile(fileName=None, append=False, fileCollisionMethod='rename',
                   encoding='utf-8-sig'):
    """Open an output file (or standard output) for writing.

    :Parameters:

    fileName : None, 'stdout', or str
        The desired output file name. If `None` or `stdout`, return
        `sys.stdout`. Any other string will be considered a filename.
    append : bool, optional
        If ``True``, append data to an existing file; otherwise, overwrite
        it with new data.
        Defaults to ``True``, i.e. appending.
    fileCollisionMethod : string, optional
        How to handle filename collisions. Valid values are `'rename'`,
        `'overwrite'`, and `'fail'`.
        This parameter is ignored if ``append``  is set to ``True``.
        Defaults to `rename`.
    encoding : string, optional
        The encoding to use when writing the file. This parameter will be
        ignored if `append` is `False` and `fileName` ends with `.psydat`
        or `.npy` (i.e. if a binary file is to be written).
        Defaults to ``'utf-8'``.

    :Returns:

    f : file
        A writable file handle.

    """
    fileName = pathToString(fileName)
    if (fileName is None) or (fileName == 'stdout'):
        return sys.stdout

    if append:
        mode = 'a'
    else:
        if fileName.endswith(('.psydat', '.npy')):
            mode = 'wb'
        else:
            mode = 'w'

        # Rename the output file if a file of that name already exists
        # and it should not be appended.
        if os.path.exists(fileName) and not append:
            fileName = handleFileCollision(
                fileName,
                fileCollisionMethod=fileCollisionMethod)

    # Do not use encoding when writing a binary file.
    if 'b' in mode:
        encoding = None

    if os.path.exists(fileName) and mode in ['w', 'wb']:
        logging.warning('Data file %s will be overwritten!' % fileName)

    # The file wil always be opened in binary writing mode,
    # see https://docs.python.org/2/library/codecs.html#codecs.open
    f = codecs.open(fileName, mode=mode, encoding=encoding)
    return f
Esempio n. 2
0
def test_handleFileCollision_rename_file_does_not_exist():
    temp_dir = mkdtemp()

    # Create temporary file and close it (to destroy it). We simply use this
    # procedure to grab a unique file name.
    with NamedTemporaryFile(dir=temp_dir) as f:
        path = f.name

    handled_path = handleFileCollision(fileName=path,
                                       fileCollisionMethod='rename')
    assert path == handled_path
Esempio n. 3
0
def test_handleFileCollision_rename_file_does_not_exist():
    temp_dir = mkdtemp()

    # Create temporary file and close it (to destroy it). We simply use this
    # procedure to grab a unique file name.
    with NamedTemporaryFile(dir=temp_dir) as f:
        path = f.name

    handled_path = handleFileCollision(fileName=path,
                                       fileCollisionMethod='rename')
    assert path == handled_path
Esempio n. 4
0
def test_handleFileCollision_rename_file_exists():
    temp_dir = mkdtemp()

    # Create temporary file and close it (to destroy it). We simply use this
    # procedure to grab a unique file name.
    with NamedTemporaryFile(dir=temp_dir, suffix='.xyz') as f:
        path = f.name

        handled_path = handleFileCollision(fileName=path,
                                           fileCollisionMethod='rename')
    filename, suffix = os.path.splitext(path)
    expected_path = '%s_1%s' % (filename, suffix)

    assert handled_path == expected_path
    os.rmdir(temp_dir)
Esempio n. 5
0
def test_handleFileCollision_rename_file_exists():
    temp_dir = mkdtemp()

    # Create temporary file and close it (to destroy it). We simply use this
    # procedure to grab a unique file name.
    with NamedTemporaryFile(dir=temp_dir, suffix='.xyz') as f:
        path = f.name

        handled_path = handleFileCollision(fileName=path,
                                           fileCollisionMethod='rename')
    filename, suffix = os.path.splitext(path)
    expected_path = '%s_1%s' % (filename, suffix)

    assert handled_path == expected_path
    os.rmdir(temp_dir)
Esempio n. 6
0
def test_handleFileCollision_rename_multiple_files_exists():
    temp_dir = mkdtemp()
    path = os.path.join(temp_dir, 'test.txt')

    filename, suffix = os.path.splitext(path)

    # Create a file to start with.
    with open(path, 'w') as f:
        f.write('foo')

    # Now handle collisions of files with the same name.
    for i, _ in enumerate(range(10), start=1):
        handled_path = handleFileCollision(fileName=path,
                                           fileCollisionMethod='rename')

        expected_path = '%s_%i%s' % (filename, i, suffix)
        assert handled_path == expected_path

        # We need to write something to the file to create it.
        with open(handled_path, 'w') as f:
            f.write('foo')

    shutil.rmtree(temp_dir)
Esempio n. 7
0
def test_handleFileCollision_rename_multiple_files_exists():
    temp_dir = mkdtemp()
    path = os.path.join(temp_dir, 'test.txt')

    filename, suffix = os.path.splitext(path)

    # Create a file to start with.
    with open(path, 'w') as f:
        f.write('foo')

    # Now handle collisions of files with the same name.
    for i, _ in enumerate(range(10), start=1):
        handled_path = handleFileCollision(fileName=path,
                                           fileCollisionMethod='rename')

        expected_path = '%s_%i%s' % (filename, i, suffix)
        assert handled_path == expected_path

        # We need to write something to the file to create it.
        with open(handled_path, 'w') as f:
            f.write('foo')

    shutil.rmtree(temp_dir)
Esempio n. 8
0
def test_handleFileCollision_fail():
    _, path = mkstemp()

    with pytest.raises(IOError):
        handleFileCollision(fileName=path, fileCollisionMethod='fail')
Esempio n. 9
0
def test_handleFileCollision_overwrite():
    _, path = mkstemp()
    handled_path = handleFileCollision(fileName=path,
                                       fileCollisionMethod='overwrite')

    assert path == handled_path
Esempio n. 10
0
def test_handleFileCollision_fail():
    _, path = mkstemp()

    with pytest.raises(IOError):
        handleFileCollision(fileName=path,
                            fileCollisionMethod='fail')
Esempio n. 11
0
    def saveAsExcel(self, fileName, sheetName='rawData',
                    stimOut=None,
                    dataOut=('n', 'all_mean', 'all_std', 'all_raw'),
                    matrixOnly=False,
                    appendFile=True,
                    fileCollisionMethod='rename'):
        """
        Save a summary data file in Excel OpenXML format workbook
        (:term:`xlsx`) for processing in most spreadsheet packages.
        This format is compatible with versions of Excel (2007 or greater)
        and and with OpenOffice (>=3.0).

        It has the advantage over the simpler text files (see
        :func:`TrialHandler.saveAsText()` )
        that data can be stored in multiple named sheets within the file.
        So you could have a single file named after your experiment and
        then have one worksheet for each participant. Or you could have
        one file for each participant and then multiple sheets for
        repeated sessions etc.

        The file extension `.xlsx` will be added if not given already.

        :Parameters:

            fileName: string
                the name of the file to create or append. Can include
                relative or absolute path

            sheetName: string
                the name of the worksheet within the file

            stimOut: list of strings
                the attributes of the trial characteristics to be output.
                To use this you need to have provided a list of dictionaries
                specifying to trialList parameter of the TrialHandler and
                give here the names of strings specifying entries in that
                dictionary

            dataOut: list of strings
                specifying the dataType and the analysis to
                be performed, in the form `dataType_analysis`. The data
                can be any of the types that you added using
                trialHandler.data.add() and the analysis can be either
                'raw' or most things in the numpy library, including
                'mean','std','median','max','min'. e.g. `rt_max` will give
                a column of max reaction times across the trials assuming
                that `rt` values have been stored. The default values will
                output the raw, mean and std of all datatypes found.

            appendFile: True or False
                If False any existing file with this name will be
                overwritten. If True then a new worksheet will be appended.
                If a worksheet already exists with that name a number will
                be added to make it unique.

            fileCollisionMethod: string
                Collision method passed to
                :func:`~psychopy.tools.fileerrortools.handleFileCollision`
                This is ignored if ``append`` is ``True``.

        """
        if stimOut is None:
            stimOut = []

        if self.thisTrialN < 1 and self.thisRepN < 1:
            # if both are < 1 we haven't started
            if self.autoLog:
                logging.info('TrialHandler.saveAsExcel called but no '
                             'trials completed. Nothing saved')
            return -1

        # NB this was based on the limited documentation (1 page wiki) for
        # openpyxl v1.0
        if not haveOpenpyxl:
            raise ImportError('openpyxl is required for saving files in'
                              ' Excel (xlsx) format, but was not found.')
            # return -1

        # create the data array to be sent to the Excel file
        dataArray = self._createOutputArray(stimOut=stimOut,
                                            dataOut=dataOut,
                                            matrixOnly=matrixOnly)

        if not fileName.endswith('.xlsx'):
            fileName += '.xlsx'
        # create or load the file
        if appendFile and os.path.isfile(fileName):
            wb = load_workbook(fileName)
            newWorkbook = False
        else:
            if not appendFile:
                # the file exists but we're not appending, will be overwritten
                fileName = handleFileCollision(fileName,
                                               fileCollisionMethod)
            wb = Workbook()  # create new workbook
            wb.properties.creator = 'PsychoPy' + psychopy.__version__
            newWorkbook = True

        if newWorkbook:
            ws = wb.worksheets[0]
            ws.title = sheetName
        else:
            ws = wb.create_sheet()
            ws.title = sheetName

        # loop through lines in the data matrix
        for lineN, line in enumerate(dataArray):
            if line is None:
                continue
            for colN, entry in enumerate(line):
                if entry is None:
                    entry = ''
                try:
                    # if it can convert to a number (from numpy) then do it
                    val = float(entry)
                except Exception:
                    val = str(entry)
                _cell = _getExcelCellName(col=colN, row=lineN)
                ws.cell(_cell).value = val

        wb.save(filename=fileName)
Esempio n. 12
0
def openOutputFile(fileName, append=False, delim=None,
                   fileCollisionMethod='rename', encoding='utf-8'):
    """Open an output file (or standard output) for writing.

    :Parameters:

    fileName : string
        The desired output file name.
    append : bool, optional
        If ``True``, append data to an existing file; otherwise, overwrite
        it with new data.
        Defaults to ``True``, i.e. appending.
    delim : string, optional
        The delimiting character(s) between values. For a CSV file, this
        would be a comma. For a TSV file, it would be ``\t``.
        Defaults to ``None``.
    fileCollisionMethod : string, optional
        How to handle filename collisions. This is ignored if ``append``
        is set to ``True``.
        Defaults to `rename`.
    encoding : string, optional
        The encoding to use when writing the file. This parameter will be
        ignored if `append` is `False` and `fileName` ends with `.psydat`
        or `.npy` (i.e. if a binary file is to be written).
        Defaults to ``'utf-8'``.

    :Returns:

    f : file
        A writable file handle.

    :Notes:

    If no known filename extension is given, and the delimiter is a comma,
    the extension ``.csv`` will be chosen automatically. If the extension
    is unknown and the delimiter is a tab, the extension will be
    ``.tsv``. ``.txt`` will be chosen otherwise.
    """

    if fileName == 'stdout':
        f = sys.stdout
        return f

    if delim is None:
        genDelimiter(fileName)

    if not fileName.endswith(('.dlm', '.DLM', '.tsv', '.TSV', '.txt',
                              '.TXT', '.csv', '.CSV', '.psydat', '.npy',
                              '.json')):
        if delim == ',':
            fileName += '.csv'
        elif delim == '\t':
            fileName += '.tsv'
        else:
            fileName += '.txt'

    if append:
        writeFormat = 'a'
    else:
        if fileName.endswith(('.psydat', '.npy')):
            writeFormat = 'wb'
        else:
            writeFormat = 'w'

        # Rename the output file if a file of that name already exists
        #  and it should not be appended.
        if os.path.exists(fileName) and not append:
            fileName = handleFileCollision(
                fileName,
                fileCollisionMethod=fileCollisionMethod
            )

    # Do not use encoding when writing a binary file.
    if 'b' in writeFormat:
        encoding = None

    if os.path.exists(fileName) and writeFormat in ['w', 'wb']:
        logging.warning('Data file, %s will be overwritten!' % fileName)

    f = codecs.open(fileName, writeFormat, encoding=encoding)
    return f
Esempio n. 13
0
def test_handleFileCollision_invalid_method():
    _, path = mkstemp()

    with pytest.raises(ValueError):
        handleFileCollision(fileName=path,
                            fileCollisionMethod='invalid_value')
Esempio n. 14
0
def test_handleFileCollision_invalid_method():
    _, path = mkstemp()

    with pytest.raises(ValueError):
        handleFileCollision(fileName=path, fileCollisionMethod='invalid_value')
Esempio n. 15
0
def openOutputFile(fileName, append=False, delim=None,
                   fileCollisionMethod='rename', encoding='utf-8'):
    """Open an output file (or standard output) for writing.

    :Parameters:

    fileName : string
        The desired output file name.
    append : bool, optional
        If ``True``, append data to an existing file; otherwise, overwrite
        it with new data.
        Defaults to ``True``, i.e. appending.
    delim : string, optional
        The delimiting character(s) between values. For a CSV file, this
        would be a comma. For a TSV file, it would be ``\t``.
        Defaults to ``None``.
    fileCollisionMethod : string, optional
        How to handle filename collisions. This is ignored if ``append``
        is set to ``True``.
        Defaults to `rename`.
    encoding : string, optional
        The encoding to use when writing the file. This parameter will be
        ignored if `append` is `False` and `fileName` ends with `.psydat`
        or `.npy` (i.e. if a binary file is to be written).
        Defaults to ``'utf-8'``.

    :Returns:

    f : file
        A writable file handle.

    :Notes:

    If no known filename extension is given, and the delimiter is a comma,
    the extension ``.csv`` will be chosen automatically. If the extension
    is unknown and the delimiter is a tab, the extension will be
    ``.tsv``. ``.txt`` will be chosen otherwise.
    """

    if fileName == 'stdout':
        f = sys.stdout
        return f

    if delim is None:
        genDelimiter(fileName)

    if not fileName.endswith(('.dlm', '.DLM', '.tsv', '.TSV', '.txt',
                              '.TXT', '.csv', '.CSV', '.psydat', '.npy',
                              '.json')):
        if delim == ',':
            fileName += '.csv'
        elif delim == '\t':
            fileName += '.tsv'
        else:
            fileName += '.txt'

    if append:
        writeFormat = 'a'
    else:
        if fileName.endswith(('.psydat', '.npy')):
            writeFormat = 'wb'
        else:
            writeFormat = 'w'

        # Rename the output file if a file of that name already exists
        #  and it should not be appended.
        if os.path.exists(fileName) and not append:
            fileName = handleFileCollision(
                fileName,
                fileCollisionMethod=fileCollisionMethod
            )

    # Do not use encoding when writing a binary file.
    if 'b' in writeFormat:
        encoding = None

    if os.path.exists(fileName) and writeFormat in ['w', 'wb']:
        logging.warning('Data file, %s will be overwritten!' % fileName)

    f = codecs.open(fileName, writeFormat, encoding=encoding)
    return f
Esempio n. 16
0
    def saveAsExcel(self,
                    fileName,
                    sheetName='rawData',
                    stimOut=None,
                    dataOut=('n', 'all_mean', 'all_std', 'all_raw'),
                    matrixOnly=False,
                    appendFile=True,
                    fileCollisionMethod='rename'):
        """
        Save a summary data file in Excel OpenXML format workbook
        (:term:`xlsx`) for processing in most spreadsheet packages.
        This format is compatible with versions of Excel (2007 or greater)
        and and with OpenOffice (>=3.0).

        It has the advantage over the simpler text files (see
        :func:`TrialHandler.saveAsText()` )
        that data can be stored in multiple named sheets within the file.
        So you could have a single file named after your experiment and
        then have one worksheet for each participant. Or you could have
        one file for each participant and then multiple sheets for
        repeated sessions etc.

        The file extension `.xlsx` will be added if not given already.

        :Parameters:

            fileName: string
                the name of the file to create or append. Can include
                relative or absolute path

            sheetName: string
                the name of the worksheet within the file

            stimOut: list of strings
                the attributes of the trial characteristics to be output.
                To use this you need to have provided a list of dictionaries
                specifying to trialList parameter of the TrialHandler and
                give here the names of strings specifying entries in that
                dictionary

            dataOut: list of strings
                specifying the dataType and the analysis to
                be performed, in the form `dataType_analysis`. The data
                can be any of the types that you added using
                trialHandler.data.add() and the analysis can be either
                'raw' or most things in the numpy library, including
                'mean','std','median','max','min'. e.g. `rt_max` will give
                a column of max reaction times across the trials assuming
                that `rt` values have been stored. The default values will
                output the raw, mean and std of all datatypes found.

            appendFile: True or False
                If False any existing file with this name will be
                overwritten. If True then a new worksheet will be appended.
                If a worksheet already exists with that name a number will
                be added to make it unique.

            fileCollisionMethod: string
                Collision method passed to
                :func:`~psychopy.tools.fileerrortools.handleFileCollision`
                This is ignored if ``append`` is ``True``.

        """
        fileName = pathToString(fileName)

        if stimOut is None:
            stimOut = []

        if self.thisTrialN < 1 and self.thisRepN < 1:
            # if both are < 1 we haven't started
            if self.autoLog:
                logging.info('TrialHandler.saveAsExcel called but no '
                             'trials completed. Nothing saved')
            return -1

        # NB this was based on the limited documentation (1 page wiki) for
        # openpyxl v1.0
        if not haveOpenpyxl:
            raise ImportError('openpyxl is required for saving files in'
                              ' Excel (xlsx) format, but was not found.')
            # return -1

        # create the data array to be sent to the Excel file
        dataArray = self._createOutputArray(stimOut=stimOut,
                                            dataOut=dataOut,
                                            matrixOnly=matrixOnly)

        if not fileName.endswith('.xlsx'):
            fileName += '.xlsx'
        # create or load the file
        if appendFile and os.path.isfile(fileName):
            wb = load_workbook(fileName)
            newWorkbook = False
        else:
            if not appendFile:
                # the file exists but we're not appending, will be overwritten
                fileName = handleFileCollision(fileName, fileCollisionMethod)
            wb = Workbook()  # create new workbook
            wb.properties.creator = 'PsychoPy' + psychopy.__version__
            newWorkbook = True

        if newWorkbook:
            ws = wb.worksheets[0]
            ws.title = sheetName
        else:
            ws = wb.create_sheet()
            ws.title = sheetName

        # loop through lines in the data matrix
        for lineN, line in enumerate(dataArray):
            if line is None:
                continue
            for colN, entry in enumerate(line):
                if entry is None:
                    entry = ''
                try:
                    # if it can convert to a number (from numpy) then do it
                    val = float(entry)
                except Exception:
                    val = u"{}".format(entry)
                ws.cell(column=colN + 1, row=lineN + 1, value=val)

        wb.save(filename=fileName)
Esempio n. 17
0
def test_handleFileCollision_overwrite():
    _, path = mkstemp()
    handled_path = handleFileCollision(fileName=path,
                                       fileCollisionMethod='overwrite')

    assert path == handled_path