GithubHelp home page GithubHelp logo

csv23's Introduction

csv23

Latest PyPI Version License Supported Python Versions Wheel

Build Codecov Readthedocs stable Readthedocs latest

csv23 provides the unicode-based API of the Python 3 csv module for Python 2 and 3. Code that should run under both versions of Python can use it to hide the bytes vs. text difference between 2 and 3 and stick to the newer unicode-based interface.

It uses utf-8 as default encoding everywhere.

Improvements

csv23 works around for the following bugs in the stdlib csv module:

bpo-12178
broken round-trip with escapechar if your data contains a literal escape character (fixed in Python 3.10)
bpo-31590
broken round-trip with escapechar and embedded newlines under Python 2 (fixed in Python 3.4 but not backported): produce a warning

Links

Extras

The package also provides some convenience functionality such as the open_csv() context manager for opening a CSV file in the right mode and returning a csv.reader or csv.writer:

>>> import csv23

>>> with csv23.open_csv('spam.csv') as reader:  # doctest: +SKIP
...     for row in reader:
...         print(', '.join(row))
Spam!, Spam!, Spam!'
Spam!, Lovely Spam!, Lovely Spam!'

Python 3 Extras

The read_csv() and write_csv() functions (available on Python 3 only) are most useful if you want (or need to) open a file-like object in the calling code, e.g. when reading or writing directly to a binary stream such as a ZIP file controlled by the caller (emulated with a io.BytesIO below):

>>> import io
>>> buf = io.BytesIO()

>>> import zipfile
>>> with zipfile.ZipFile(buf, 'w') as z, z.open('spam.csv', 'w') as f:
...     csv23.write_csv(f, [[1, None]], header=['spam', 'eggs'])
<zipfile...>

>>> buf.seek(0)
0

>>> with zipfile.ZipFile(buf) as z, z.open('spam.csv') as f:
...     csv23.read_csv(f, as_list=True)
[['spam', 'eggs'], ['1', '']]

csv23 internally wraps the byte stream in a io.TextIOWrapper with the given encoding and newline='' (see csv module docs).

The write_csv()-function also supports updating objects with a .update(<bytes>)-method such as hashlib.new() instances, which allows to calculate a checksum over the binary CSV file output produced from the given rows without writing it to disk (note that the object is returned):

>>> import hashlib

>>> csv23.write_csv(hashlib.new('sha256'), [[1, None]], header=['spam', 'eggs']).hexdigest()
'aed6871f9ca7c047eb55a569e8337af03fee508521b5ddfe7ad0ad1e1139980a'

Both functions have an optional autocompress argument: Set it to True to transparently compress (or decompress) if the file argument is a path that ends in one of '.bz2', '.gz', and '.xz'.

Installation

This package runs under Python 2.7, and 3.8+, use pip to install:

$ pip install csv23

See also

License

This package is distributed under the MIT license.

csv23's People

Contributors

xflr6 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

csv23's Issues

0.3 PyPy3 compatibility issue?

We use pre-built PyPy3 binaries on Ubuntu VM images and test that PyPy3 via some custom test definitions mostly based on some old version of https://github.com/pypa/pip/tree/master/tests
Unfortunately, tests started to fail with the 0.3 update(rollback to 0.2 resolves the issue) with the following errors:


___________ ERROR collecting tests/functional/test_install_wheel.py ____________
ImportError while importing test module '/home/vsts/work/1/s/src/python/pip-repository/tests/functional/test_install_wheel.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/functional/test_install_wheel.py:10: in <module>
    from tests.lib.wheel import make_wheel
tests/lib/wheel.py:14: in <module>
    import csv23
.tox/py/site-packages/csv23/__init__.py:20: in <module>
    from .shortcuts import read_csv, write_csv
.tox/py/site-packages/csv23/shortcuts.py:58: in <module>
    import builtins, bz2, gzip, lzma
/opt/hostedtoolcache/PyPy/3.6.9/x64/lib-python/3/lzma.py:27: in <module>
    from _lzma import *
/opt/hostedtoolcache/PyPy/3.6.9/x64/lib_pypy/_lzma.py:15: in <module>
    from _lzma_cffi import ffi, lib as m
E   ImportError: /opt/hostedtoolcache/PyPy/3.6.9/x64/lib_pypy/_lzma_cffi.pypy36-pp73-x86_64-linux-gnu.so: undefined symbol: lzma_index_stream_padding
___________________ ERROR collecting tests/lib/test_wheel.py ___________________
ImportError while importing test module '/home/vsts/work/1/s/src/python/pip-repository/tests/lib/test_wheel.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/lib/test_wheel.py:8: in <module>
    from tests.lib.wheel import (
tests/lib/wheel.py:14: in <module>
    import csv23
.tox/py/site-packages/csv23/__init__.py:20: in <module>
    from .shortcuts import read_csv, write_csv
.tox/py/site-packages/csv23/shortcuts.py:58: in <module>
    import builtins, bz2, gzip, lzma
/opt/hostedtoolcache/PyPy/3.6.9/x64/lib-python/3/lzma.py:27: in <module>
    from _lzma import *
/opt/hostedtoolcache/PyPy/3.6.9/x64/lib_pypy/_lzma.py:15: in <module>
    from _lzma_cffi import ffi, lib as m
E   ImportError: /opt/hostedtoolcache/PyPy/3.6.9/x64/lib_pypy/_lzma_cffi.pypy36-pp73-x86_64-linux-gnu.so: undefined symbol: lzma_index_stream_padding

Could you please help us understanding the root cause?

Python 3.10.0beta test_writers.py failures: missing quoting

The tests are failing with Python 3.10.0b1. Tested with git master (1677f82 and 7f10b99), get the same results, so I'm wondering if the py3.10 fix works.

FAILED tests/test_stdlib_csv.py::test_csv_roundtrip[spam\\eggs-0-"-\\-True] - AssertionError: assert ['spam\\eggs'] != ['spam\\eggs']
FAILED tests/test_stdlib_csv.py::test_csv_roundtrip[spam\\eggs-0-"-\\-False] - AssertionError: assert ['spam\\eggs'] != ['spam\\eggs']
FAILED tests/test_writers.py::test_open_writer[utf-8-row5-fmtparams5-"spam\\\\eggs"\r\n] - assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\e...
FAILED tests/test_writers.py::test_open_writer[utf-16-row5-fmtparams5-"spam\\\\eggs"\r\n] - assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\...
FAILED tests/test_writers.py::test_open_writer[utf-8-sig-row5-fmtparams5-"spam\\\\eggs"\r\n] - assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\...
FAILED tests/test_writers.py::test_open_writer[latin9-row5-fmtparams5-"spam\\\\eggs"\r\n] - assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\...
FAILED tests/test_writers.py::test_writer[False-row5-fmtparams5-"spam\\\\eggs"\r\n] - AssertionError: assert False
FAILED tests/test_writers.py::test_writer[utf-8-row5-fmtparams5-"spam\\\\eggs"\r\n] - assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\egg......
FAILED tests/test_writers.py::test_writer[latin9-row5-fmtparams5-"spam\\\\eggs"\r\n] - assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\egg.....

Full output:

$ tox -e py310
GLOB sdist-make: /tmp/csv23/setup.py
py310 inst-nodeps: /tmp/csv23/.tox/.tmp/package/1/csv23-0.3.3.dev0.zip
py310 installed: attrs==21.2.0,coverage==5.5,csv23 @ file:///tmp/csv23/.tox/.tmp/package/1/csv23-0.3.3.dev0.zip,iniconfig==1.1.1,mock==4.0.3,packaging==20.9,pluggy==0.13.1,py==1.10.0,pyparsing==2.4.7,pytest==6.2.4,pytest-cov==2.12.0,pytest-mock==3.6.1,toml==0.10.2
py310 run-test-pre: PYTHONHASHSEED='3528200982'
py310 run-test: commands[0] | ./run-tests.py
============================================================== test session starts ===============================================================
platform linux -- Python 3.10.0b1, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
cachedir: .tox/py310/.pytest_cache
rootdir: /tmp/csv23, configfile: setup.cfg, testpaths: csv23, tests
plugins: cov-2.12.0, mock-3.6.1
collected 339 items                                                                                                                              

csv23/__init__.py s.                                                                                                                       [  0%]
csv23/_common.py .                                                                                                                         [  0%]
csv23/extras.py .                                                                                                                          [  1%]
csv23/openers.py ss                                                                                                                        [  1%]
csv23/readers.py .                                                                                                                         [  2%]
csv23/shortcuts.py ..                                                                                                                      [  2%]
csv23/writers.py .                                                                                                                         [  2%]
tests/test_common.py ........ssss.                                                                                                         [  6%]
tests/test_dialect.py ..............                                                                                                       [ 10%]
tests/test_encoding.py ......                                                                                                              [ 12%]
tests/test_extras.py ............                                                                                                          [ 16%]
tests/test_init.py .........                                                                                                               [ 18%]
tests/test_openers.py ...                                                                                                                  [ 19%]
tests/test_readers.py .......x.......x.......x.....s.x.......x.......x.....s.x                                                             [ 36%]
tests/test_rowtype.py ..........                                                                                                           [ 39%]
tests/test_shortcuts.py ss........................................                                                                         [ 51%]
tests/test_stdlib_csv.py ..................................................................................FF............                  [ 79%]
tests/test_stdlib_truncate.py s.                                                                                                           [ 80%]
tests/test_workarounds.py ..                                                                                                               [ 81%]
tests/test_writers.py .....F.......F.......F......sF...............F.......F......sF..                                                     [100%]

==================================================================== FAILURES ====================================================================
___________________________________________________ test_csv_roundtrip[spam\\eggs-0-"-\\-True] ___________________________________________________

py2 = False, quoting = 0, quotechar = '"', escapechar = '\\', doublequote = True, value = 'spam\\eggs'

    @pytest.mark.parametrize(', '.join(FORMATS[0]), FORMATS[1:])
    @pytest.mark.parametrize('value', VALUES)
    def test_csv_roundtrip(py2, quoting, quotechar, escapechar, doublequote, value):
        csv_kwargs = {'quoting': quoting, 'quotechar': quotechar,
                      'escapechar': escapechar, 'doublequote': doublequote}
        row = expected = [value]
    
        with io.BytesIO() if py2 else io.StringIO(newline='') as f:
            if quoting != csv.QUOTE_NONE and quotechar is None:
                with pytest.raises(TypeError, match=r'quotechar must be set'):
                    csv.writer(f, **csv_kwargs)
                return
    
            writer = csv.writer(f, **csv_kwargs)
    
            if escapechar is None and (quoting == csv.QUOTE_NONE or not doublequote):
                need_escape = [',', '\r', '\n'] if quoting == csv.QUOTE_NONE else []
                if quotechar is not None:
                    need_escape.append(quotechar)
                if any(n in value for n in need_escape):
                    with pytest.raises(Exception, match=r'need to escape'):
                        writer.writerow(row)
                    return
    
            writer.writerow(row)
            f.seek(0)
            row = next(csv.reader(f, **csv_kwargs))
    
        if quoting != csv.QUOTE_NONE and escapechar is not None and escapechar in value:
            # writer fails to escape escapechar
>           assert row != expected
E           AssertionError: assert ['spam\\eggs'] != ['spam\\eggs']

tests/test_stdlib_csv.py:67: AssertionError
__________________________________________________ test_csv_roundtrip[spam\\eggs-0-"-\\-False] ___________________________________________________

py2 = False, quoting = 0, quotechar = '"', escapechar = '\\', doublequote = False, value = 'spam\\eggs'

    @pytest.mark.parametrize(', '.join(FORMATS[0]), FORMATS[1:])
    @pytest.mark.parametrize('value', VALUES)
    def test_csv_roundtrip(py2, quoting, quotechar, escapechar, doublequote, value):
        csv_kwargs = {'quoting': quoting, 'quotechar': quotechar,
                      'escapechar': escapechar, 'doublequote': doublequote}
        row = expected = [value]
    
        with io.BytesIO() if py2 else io.StringIO(newline='') as f:
            if quoting != csv.QUOTE_NONE and quotechar is None:
                with pytest.raises(TypeError, match=r'quotechar must be set'):
                    csv.writer(f, **csv_kwargs)
                return
    
            writer = csv.writer(f, **csv_kwargs)
    
            if escapechar is None and (quoting == csv.QUOTE_NONE or not doublequote):
                need_escape = [',', '\r', '\n'] if quoting == csv.QUOTE_NONE else []
                if quotechar is not None:
                    need_escape.append(quotechar)
                if any(n in value for n in need_escape):
                    with pytest.raises(Exception, match=r'need to escape'):
                        writer.writerow(row)
                    return
    
            writer.writerow(row)
            f.seek(0)
            row = next(csv.reader(f, **csv_kwargs))
    
        if quoting != csv.QUOTE_NONE and escapechar is not None and escapechar in value:
            # writer fails to escape escapechar
>           assert row != expected
E           AssertionError: assert ['spam\\eggs'] != ['spam\\eggs']

tests/test_stdlib_csv.py:67: AssertionError
___________________________________________ test_open_writer[utf-8-row5-fmtparams5-"spam\\\\eggs"\r\n] ___________________________________________

py2 = False, filepath = PosixPath('/tmp/pytest-of-mgorny/pytest-8/test_open_writer_utf_8_row5_fm0/spam.csv'), encoding = 'utf-8'
row = ['spam\\eggs'], fmtparams = {'escapechar': '\\', 'quoting': 0}, expected = '"spam\\\\eggs"\r\n', n = 12

    @pytest.mark.parametrize('row, fmtparams, expected', ROW_FORMAT_LINE)
    def test_open_writer(py2, filepath, encoding, row, fmtparams, expected, n=12):
        try:
            expected.encode(encoding)
        except UnicodeEncodeError:
            pytest.skip('impossible combination of row and encoding')
    
        write_n = len(expected.encode(encoding) if py2 and is_8bit_clean(encoding) else expected)
    
        filename = str(filepath)
    
        with open_writer(filename, encoding=encoding, **fmtparams) as w:
            written = w.writerow(row)
            w.writerows([row] * (n - 1))
    
        with io.open(filename, encoding=encoding, newline='') as f:
            line = f.read()
    
>       assert line == expected * n
E       assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\egg...\\\\eggs"\r\n'
E         - "spam\\eggs"
E         ? -          -
E         + spam\\eggs
E         - "spam\\eggs"
E         ? -          -
E         + spam\\eggs
...       - "spam\\eggs"
E         
E         ...Full output truncated (30 lines hidden), use '-vv' to show

tests/test_writers.py:55: AssertionError
__________________________________________ test_open_writer[utf-16-row5-fmtparams5-"spam\\\\eggs"\r\n] ___________________________________________

py2 = False, filepath = PosixPath('/tmp/pytest-of-mgorny/pytest-8/test_open_writer_utf_16_row5_f0/spam.csv'), encoding = 'utf-16'
row = ['spam\\eggs'], fmtparams = {'escapechar': '\\', 'quoting': 0}, expected = '"spam\\\\eggs"\r\n', n = 12

    @pytest.mark.parametrize('row, fmtparams, expected', ROW_FORMAT_LINE)
    def test_open_writer(py2, filepath, encoding, row, fmtparams, expected, n=12):
        try:
            expected.encode(encoding)
        except UnicodeEncodeError:
            pytest.skip('impossible combination of row and encoding')
    
        write_n = len(expected.encode(encoding) if py2 and is_8bit_clean(encoding) else expected)
    
        filename = str(filepath)
    
        with open_writer(filename, encoding=encoding, **fmtparams) as w:
            written = w.writerow(row)
            w.writerows([row] * (n - 1))
    
        with io.open(filename, encoding=encoding, newline='') as f:
            line = f.read()
    
>       assert line == expected * n
E       assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\egg...\\\\eggs"\r\n'
E         - "spam\\eggs"
E         ? -          -
E         + spam\\eggs
E         - "spam\\eggs"
E         ? -          -
E         + spam\\eggs
...       - "spam\\eggs"
E         
E         ...Full output truncated (30 lines hidden), use '-vv' to show

tests/test_writers.py:55: AssertionError
_________________________________________ test_open_writer[utf-8-sig-row5-fmtparams5-"spam\\\\eggs"\r\n] _________________________________________

py2 = False, filepath = PosixPath('/tmp/pytest-of-mgorny/pytest-8/test_open_writer_utf_8_sig_row5/spam.csv'), encoding = 'utf-8-sig'
row = ['spam\\eggs'], fmtparams = {'escapechar': '\\', 'quoting': 0}, expected = '"spam\\\\eggs"\r\n', n = 12

    @pytest.mark.parametrize('row, fmtparams, expected', ROW_FORMAT_LINE)
    def test_open_writer(py2, filepath, encoding, row, fmtparams, expected, n=12):
        try:
            expected.encode(encoding)
        except UnicodeEncodeError:
            pytest.skip('impossible combination of row and encoding')
    
        write_n = len(expected.encode(encoding) if py2 and is_8bit_clean(encoding) else expected)
    
        filename = str(filepath)
    
        with open_writer(filename, encoding=encoding, **fmtparams) as w:
            written = w.writerow(row)
            w.writerows([row] * (n - 1))
    
        with io.open(filename, encoding=encoding, newline='') as f:
            line = f.read()
    
>       assert line == expected * n
E       assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\egg...\\\\eggs"\r\n'
E         - "spam\\eggs"
E         ? -          -
E         + spam\\eggs
E         - "spam\\eggs"
E         ? -          -
E         + spam\\eggs
...       - "spam\\eggs"
E         
E         ...Full output truncated (30 lines hidden), use '-vv' to show

tests/test_writers.py:55: AssertionError
__________________________________________ test_open_writer[latin9-row5-fmtparams5-"spam\\\\eggs"\r\n] ___________________________________________

py2 = False, filepath = PosixPath('/tmp/pytest-of-mgorny/pytest-8/test_open_writer_latin9_row5_f0/spam.csv'), encoding = 'latin9'
row = ['spam\\eggs'], fmtparams = {'escapechar': '\\', 'quoting': 0}, expected = '"spam\\\\eggs"\r\n', n = 12

    @pytest.mark.parametrize('row, fmtparams, expected', ROW_FORMAT_LINE)
    def test_open_writer(py2, filepath, encoding, row, fmtparams, expected, n=12):
        try:
            expected.encode(encoding)
        except UnicodeEncodeError:
            pytest.skip('impossible combination of row and encoding')
    
        write_n = len(expected.encode(encoding) if py2 and is_8bit_clean(encoding) else expected)
    
        filename = str(filepath)
    
        with open_writer(filename, encoding=encoding, **fmtparams) as w:
            written = w.writerow(row)
            w.writerows([row] * (n - 1))
    
        with io.open(filename, encoding=encoding, newline='') as f:
            line = f.read()
    
>       assert line == expected * n
E       assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\egg...\\\\eggs"\r\n'
E         - "spam\\eggs"
E         ? -          -
E         + spam\\eggs
E         - "spam\\eggs"
E         ? -          -
E         + spam\\eggs
...       - "spam\\eggs"
E         
E         ...Full output truncated (30 lines hidden), use '-vv' to show

tests/test_writers.py:55: AssertionError
_____________________________________________ test_writer[False-row5-fmtparams5-"spam\\\\eggs"\r\n] ______________________________________________

mocker = <pytest_mock.plugin.MockerFixture object at 0x7ff8b28362c0>, py2 = False
filepath = PosixPath('/tmp/pytest-of-mgorny/pytest-8/test_writer_False_row5_fmtpara0/spam.csv'), inner_encoding = False, row = ['spam\\eggs']
fmtparams = {'escapechar': '\\', 'quoting': 0}, expected = '"spam\\\\eggs"\r\n', n = 12

    @pytest.mark.parametrize('row, fmtparams, expected', ROW_FORMAT_LINE)
    def test_writer(mocker, py2, filepath, inner_encoding,
                    row, fmtparams, expected, n=12):
        encoding = inner_encoding
        if encoding is False:
            if py2:
                expected_type = UnicodeTextWriter
            elif (fmtparams.get('escapechar')
                  and fmtparams.get('quoting', csv.QUOTE_MINIMAL) != csv.QUOTE_NONE):
                expected_type = _UnicodeTextWriter
            else:
                expected_type = type(csv.writer(mocker.mock_open()()))
            write_n = len(expected)
            file_encoding = 'utf-8'
            open_kwargs = {'mode': 'w', 'encoding': file_encoding, 'newline': ''}
        else:
            expected_type = UnicodeBytesWriter
            try:
                write_n = len(expected.encode(encoding))
            except UnicodeEncodeError:
                pytest.skip('impossible combination of row and encoding')
            file_encoding = encoding
            open_kwargs = {'mode': 'wb'}
    
        filename = str(filepath)
    
        with io.open(filename, **open_kwargs) as f:
            w = writer(f, encoding=encoding, **fmtparams)
>           assert isinstance(w, expected_type)
E           AssertionError: assert False
E            +  where False = isinstance(<_csv.writer object at 0x7ff8b2697b20>, <class 'csv23.writers._UnicodeTextWriter'>)

tests/test_writers.py:99: AssertionError
_____________________________________________ test_writer[utf-8-row5-fmtparams5-"spam\\\\eggs"\r\n] ______________________________________________

mocker = <pytest_mock.plugin.MockerFixture object at 0x7ff8b23e1a20>, py2 = False
filepath = PosixPath('/tmp/pytest-of-mgorny/pytest-8/test_writer_utf_8_row5_fmtpara0/spam.csv'), inner_encoding = 'utf-8', row = ['spam\\eggs']
fmtparams = {'escapechar': '\\', 'quoting': 0}, expected = '"spam\\\\eggs"\r\n', n = 12

    @pytest.mark.parametrize('row, fmtparams, expected', ROW_FORMAT_LINE)
    def test_writer(mocker, py2, filepath, inner_encoding,
                    row, fmtparams, expected, n=12):
        encoding = inner_encoding
        if encoding is False:
            if py2:
                expected_type = UnicodeTextWriter
            elif (fmtparams.get('escapechar')
                  and fmtparams.get('quoting', csv.QUOTE_MINIMAL) != csv.QUOTE_NONE):
                expected_type = _UnicodeTextWriter
            else:
                expected_type = type(csv.writer(mocker.mock_open()()))
            write_n = len(expected)
            file_encoding = 'utf-8'
            open_kwargs = {'mode': 'w', 'encoding': file_encoding, 'newline': ''}
        else:
            expected_type = UnicodeBytesWriter
            try:
                write_n = len(expected.encode(encoding))
            except UnicodeEncodeError:
                pytest.skip('impossible combination of row and encoding')
            file_encoding = encoding
            open_kwargs = {'mode': 'wb'}
    
        filename = str(filepath)
    
        with io.open(filename, **open_kwargs) as f:
            w = writer(f, encoding=encoding, **fmtparams)
            assert isinstance(w, expected_type)
            written = w.writerow(row)
            w.writerows([row] * (n - 1))
    
        with io.open(filename, encoding=file_encoding, newline='') as f:
            line = f.read()
    
>       assert line == expected * n
E       assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\egg...\\\\eggs"\r\n'
E         - "spam\\eggs"
E         ? -          -
E         + spam\\eggs
E         - "spam\\eggs"
E         ? -          -
E         + spam\\eggs
...       - "spam\\eggs"
E         
E         ...Full output truncated (30 lines hidden), use '-vv' to show

tests/test_writers.py:106: AssertionError
_____________________________________________ test_writer[latin9-row5-fmtparams5-"spam\\\\eggs"\r\n] _____________________________________________

mocker = <pytest_mock.plugin.MockerFixture object at 0x7ff8b23e22f0>, py2 = False
filepath = PosixPath('/tmp/pytest-of-mgorny/pytest-8/test_writer_latin9_row5_fmtpar0/spam.csv'), inner_encoding = 'latin9', row = ['spam\\eggs']
fmtparams = {'escapechar': '\\', 'quoting': 0}, expected = '"spam\\\\eggs"\r\n', n = 12

    @pytest.mark.parametrize('row, fmtparams, expected', ROW_FORMAT_LINE)
    def test_writer(mocker, py2, filepath, inner_encoding,
                    row, fmtparams, expected, n=12):
        encoding = inner_encoding
        if encoding is False:
            if py2:
                expected_type = UnicodeTextWriter
            elif (fmtparams.get('escapechar')
                  and fmtparams.get('quoting', csv.QUOTE_MINIMAL) != csv.QUOTE_NONE):
                expected_type = _UnicodeTextWriter
            else:
                expected_type = type(csv.writer(mocker.mock_open()()))
            write_n = len(expected)
            file_encoding = 'utf-8'
            open_kwargs = {'mode': 'w', 'encoding': file_encoding, 'newline': ''}
        else:
            expected_type = UnicodeBytesWriter
            try:
                write_n = len(expected.encode(encoding))
            except UnicodeEncodeError:
                pytest.skip('impossible combination of row and encoding')
            file_encoding = encoding
            open_kwargs = {'mode': 'wb'}
    
        filename = str(filepath)
    
        with io.open(filename, **open_kwargs) as f:
            w = writer(f, encoding=encoding, **fmtparams)
            assert isinstance(w, expected_type)
            written = w.writerow(row)
            w.writerows([row] * (n - 1))
    
        with io.open(filename, encoding=file_encoding, newline='') as f:
            line = f.read()
    
>       assert line == expected * n
E       assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\egg...\\\\eggs"\r\n'
E         - "spam\\eggs"
E         ? -          -
E         + spam\\eggs
E         - "spam\\eggs"
E         ? -          -
E         + spam\\eggs
...       - "spam\\eggs"
E         
E         ...Full output truncated (30 lines hidden), use '-vv' to show

tests/test_writers.py:106: AssertionError

----------- coverage: platform linux, python 3.10.0-beta-1 -----------
Name                    Stmts   Miss  Cover
-------------------------------------------
csv23/__init__.py          28      0   100%
csv23/_common.py           33      6    82%
csv23/_dispatch.py         29      0   100%
csv23/_workarounds.py      22      1    95%
csv23/dialects.py          28      8    71%
csv23/extras.py            59      2    97%
csv23/openers.py           35      6    83%
csv23/readers.py           59     16    73%
csv23/shortcuts.py        107      8    93%
csv23/writers.py           90     33    63%
-------------------------------------------
TOTAL                     490     80    84%
Coverage HTML written to dir htmlcov

============================================================ short test summary info =============================================================
FAILED tests/test_stdlib_csv.py::test_csv_roundtrip[spam\\eggs-0-"-\\-True] - AssertionError: assert ['spam\\eggs'] != ['spam\\eggs']
FAILED tests/test_stdlib_csv.py::test_csv_roundtrip[spam\\eggs-0-"-\\-False] - AssertionError: assert ['spam\\eggs'] != ['spam\\eggs']
FAILED tests/test_writers.py::test_open_writer[utf-8-row5-fmtparams5-"spam\\\\eggs"\r\n] - assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\e...
FAILED tests/test_writers.py::test_open_writer[utf-16-row5-fmtparams5-"spam\\\\eggs"\r\n] - assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\...
FAILED tests/test_writers.py::test_open_writer[utf-8-sig-row5-fmtparams5-"spam\\\\eggs"\r\n] - assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\...
FAILED tests/test_writers.py::test_open_writer[latin9-row5-fmtparams5-"spam\\\\eggs"\r\n] - assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\...
FAILED tests/test_writers.py::test_writer[False-row5-fmtparams5-"spam\\\\eggs"\r\n] - AssertionError: assert False
FAILED tests/test_writers.py::test_writer[utf-8-row5-fmtparams5-"spam\\\\eggs"\r\n] - assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\egg......
FAILED tests/test_writers.py::test_writer[latin9-row5-fmtparams5-"spam\\\\eggs"\r\n] - assert 'spam\\\\eggs...m\\\\eggs\r\n' == '"spam\\\\egg.....
============================================== 9 failed, 309 passed, 14 skipped, 7 xfailed in 1.47s ==============================================
ERROR: InvocationError for command /tmp/csv23/run-tests.py (exited with code 1)
____________________________________________________________________ summary _____________________________________________________________________
ERROR:   py310: commands failed

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.