summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/csv.py2
-rw-r--r--Lib/test/test_csv.py123
2 files changed, 100 insertions, 25 deletions
diff --git a/Lib/csv.py b/Lib/csv.py
index 78b6759..d08a86b 100644
--- a/Lib/csv.py
+++ b/Lib/csv.py
@@ -68,7 +68,7 @@ class Dialect:
elif not isinstance(self.lineterminator, str):
errors.append("lineterminator must be a string")
- if self.doublequote not in (True, False):
+ if self.doublequote not in (True, False) and self.quoting != QUOTE_NONE:
errors.append("doublequote parameter must be True or False")
if self.skipinitialspace not in (True, False):
diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py
index aaebabc..a671d7e 100644
--- a/Lib/test/test_csv.py
+++ b/Lib/test/test_csv.py
@@ -17,44 +17,112 @@ class Test_Csv(unittest.TestCase):
from the high level interface. Further tests of this nature are done
in TestDialectRegistry.
"""
- def test_reader_arg_valid(self):
- self.assertRaises(TypeError, csv.reader)
- self.assertRaises(TypeError, csv.reader, None)
- self.assertRaises(AttributeError, csv.reader, [], bad_attr = 0)
- self.assertRaises(csv.Error, csv.reader, [], 'foo')
+ def _test_arg_valid(self, ctor, arg):
+ self.assertRaises(TypeError, ctor)
+ self.assertRaises(TypeError, ctor, None)
+ self.assertRaises(TypeError, ctor, arg, bad_attr = 0)
+ self.assertRaises(TypeError, ctor, arg, delimiter = 0)
+ self.assertRaises(TypeError, ctor, arg, delimiter = 'XX')
+ self.assertRaises(csv.Error, ctor, arg, 'foo')
+ self.assertRaises(TypeError, ctor, arg, None)
+ self.assertRaises(TypeError, ctor, arg, delimiter=None)
+ self.assertRaises(TypeError, ctor, arg, delimiter=1)
+ self.assertRaises(TypeError, ctor, arg, quotechar=1)
+ self.assertRaises(TypeError, ctor, arg, lineterminator=None)
+ self.assertRaises(TypeError, ctor, arg, lineterminator=1)
+ self.assertRaises(TypeError, ctor, arg, quoting=None)
+# We now allow this, only raising an exception if quoting is needed.
+# self.assertRaises(TypeError, ctor, arg, quotechar=None)
+# self.assertRaises(TypeError, ctor, arg,
+# quoting=csv.QUOTE_NONE, escapechar=None)
+# No longer complains about dialects with invalid attributes [AM]
+# class BadDialect:
+# bad_attr = 0
+# self.assertRaises(AttributeError, csv.reader, [], BadDialect)
class BadClass:
def __init__(self):
raise IOError
self.assertRaises(IOError, csv.reader, [], BadClass)
- self.assertRaises(TypeError, csv.reader, [], None)
- class BadDialect:
- bad_attr = 0
- self.assertRaises(AttributeError, csv.reader, [], BadDialect)
+
+ def test_reader_arg_valid(self):
+ self._test_arg_valid(csv.reader, [])
def test_writer_arg_valid(self):
- self.assertRaises(TypeError, csv.writer)
- self.assertRaises(TypeError, csv.writer, None)
- self.assertRaises(AttributeError, csv.writer, StringIO(), bad_attr = 0)
+ self._test_arg_valid(csv.writer, StringIO())
- def _test_attrs(self, obj):
+ def _test_default_attrs(self, ctor, *args):
+ obj = ctor(*args)
+ # Check defaults
self.assertEqual(obj.dialect.delimiter, ',')
- obj.dialect.delimiter = '\t'
- self.assertEqual(obj.dialect.delimiter, '\t')
- self.assertRaises(TypeError, delattr, obj.dialect, 'delimiter')
- self.assertRaises(TypeError, setattr, obj.dialect,
- 'lineterminator', None)
- obj.dialect.escapechar = None
+ self.assertEqual(obj.dialect.doublequote, True)
self.assertEqual(obj.dialect.escapechar, None)
+ self.assertEqual(obj.dialect.lineterminator, "\r\n")
+ self.assertEqual(obj.dialect.quotechar, '"')
+ self.assertEqual(obj.dialect.quoting, csv.QUOTE_MINIMAL)
+ self.assertEqual(obj.dialect.skipinitialspace, False)
+ self.assertEqual(obj.dialect.strict, False)
+ # Try deleting or changing attributes (they are read-only)
+ self.assertRaises(TypeError, delattr, obj.dialect, 'delimiter')
+ self.assertRaises(TypeError, setattr, obj.dialect, 'delimiter', ':')
self.assertRaises(TypeError, delattr, obj.dialect, 'quoting')
self.assertRaises(TypeError, setattr, obj.dialect, 'quoting', None)
- obj.dialect.quoting = csv.QUOTE_MINIMAL
- self.assertEqual(obj.dialect.quoting, csv.QUOTE_MINIMAL)
def test_reader_attrs(self):
- self._test_attrs(csv.reader([]))
+ self._test_default_attrs(csv.reader, [])
def test_writer_attrs(self):
- self._test_attrs(csv.writer(StringIO()))
+ self._test_default_attrs(csv.writer, StringIO())
+
+ def _test_kw_attrs(self, ctor, *args):
+ # Now try with alternate options
+ kwargs = dict(delimiter=':', doublequote=False, escapechar='\\',
+ lineterminator='\r', quotechar='*',
+ quoting=csv.QUOTE_NONE, skipinitialspace=True,
+ strict=True)
+ obj = ctor(*args, **kwargs)
+ self.assertEqual(obj.dialect.delimiter, ':')
+ self.assertEqual(obj.dialect.doublequote, False)
+ self.assertEqual(obj.dialect.escapechar, '\\')
+ self.assertEqual(obj.dialect.lineterminator, "\r")
+ self.assertEqual(obj.dialect.quotechar, '*')
+ self.assertEqual(obj.dialect.quoting, csv.QUOTE_NONE)
+ self.assertEqual(obj.dialect.skipinitialspace, True)
+ self.assertEqual(obj.dialect.strict, True)
+
+ def test_reader_kw_attrs(self):
+ self._test_kw_attrs(csv.reader, [])
+
+ def test_writer_kw_attrs(self):
+ self._test_kw_attrs(csv.writer, StringIO())
+
+ def _test_dialect_attrs(self, ctor, *args):
+ # Now try with dialect-derived options
+ class dialect:
+ delimiter='-'
+ doublequote=False
+ escapechar='^'
+ lineterminator='$'
+ quotechar='#'
+ quoting=csv.QUOTE_ALL
+ skipinitialspace=True
+ strict=False
+ args = args + (dialect,)
+ obj = ctor(*args)
+ self.assertEqual(obj.dialect.delimiter, '-')
+ self.assertEqual(obj.dialect.doublequote, False)
+ self.assertEqual(obj.dialect.escapechar, '^')
+ self.assertEqual(obj.dialect.lineterminator, "$")
+ self.assertEqual(obj.dialect.quotechar, '#')
+ self.assertEqual(obj.dialect.quoting, csv.QUOTE_ALL)
+ self.assertEqual(obj.dialect.skipinitialspace, True)
+ self.assertEqual(obj.dialect.strict, False)
+
+ def test_reader_dialect_attrs(self):
+ self._test_dialect_attrs(csv.reader, [])
+
+ def test_writer_dialect_attrs(self):
+ self._test_dialect_attrs(csv.writer, StringIO())
+
def _write_test(self, fields, expect, **kwargs):
fd, name = tempfile.mkstemp()
@@ -166,6 +234,13 @@ class Test_Csv(unittest.TestCase):
self._read_test(['a,"b,c\\""'], [['a', 'b,c"']], escapechar='\\')
self._read_test(['a,"b,c"\\'], [['a', 'b,c\\']], escapechar='\\')
+ def test_read_quoting(self):
+ self._read_test(['1,",3,",5'], [['1', ',3,', '5']])
+ self._read_test(['1,",3,",5'], [['1', '"', '3', '"', '5']],
+ quotechar=None, escapechar='\\')
+ self._read_test(['1,",3,",5'], [['1', '"', '3', '"', '5']],
+ quoting=csv.QUOTE_NONE, escapechar='\\')
+
def test_read_bigfield(self):
# This exercises the buffer realloc functionality
bigstring = 'X' * 50000
@@ -297,7 +372,7 @@ class TestDialectRegistry(unittest.TestCase):
def test_bad_dialect(self):
# Unknown parameter
- self.assertRaises(AttributeError, csv.reader, [], bad_attr = 0)
+ self.assertRaises(TypeError, csv.reader, [], bad_attr = 0)
# Bad values
self.assertRaises(TypeError, csv.reader, [], delimiter = None)
self.assertRaises(TypeError, csv.reader, [], quoting = -1)