@@ -64,8 +64,7 @@ def _test_arg_valid(self, ctor, arg):
6464 ctor (arg , delimiter = '\t ' , skipinitialspace = True )
6565 ctor (arg , escapechar = '\t ' , skipinitialspace = True )
6666 ctor (arg , quotechar = '\t ' , skipinitialspace = True )
67- self .assertRaises (ValueError , ctor , arg ,
68- delimiter = ' ' , skipinitialspace = True )
67+ ctor (arg , delimiter = ' ' , skipinitialspace = True )
6968 self .assertRaises (ValueError , ctor , arg ,
7069 escapechar = ' ' , skipinitialspace = True )
7170 self .assertRaises (ValueError , ctor , arg ,
@@ -192,9 +191,6 @@ def _write_error_test(self, exc, fields, **kwargs):
192191
193192 def test_write_arg_valid (self ):
194193 self ._write_error_test (csv .Error , None )
195- self ._write_test ((), '' )
196- self ._write_test ([None ], '""' )
197- self ._write_error_test (csv .Error , [None ], quoting = csv .QUOTE_NONE )
198194 # Check that exceptions are passed up the chain
199195 self ._write_error_test (OSError , BadIterable ())
200196 class BadList :
@@ -208,7 +204,6 @@ class BadItem:
208204 def __str__ (self ):
209205 raise OSError
210206 self ._write_error_test (OSError , [BadItem ()])
211-
212207 def test_write_bigfield (self ):
213208 # This exercises the buffer realloc functionality
214209 bigstring = 'X' * 50000
@@ -315,6 +310,49 @@ def test_writerows_with_none(self):
315310 fileobj .seek (0 )
316311 self .assertEqual (fileobj .read (), 'a\r \n ""\r \n ' )
317312
313+
314+ def test_write_empty_fields (self ):
315+ self ._write_test ((), '' )
316+ self ._write_test (['' ], '""' )
317+ self ._write_error_test (csv .Error , ['' ], quoting = csv .QUOTE_NONE )
318+ self ._write_test (['' ], '""' , quoting = csv .QUOTE_STRINGS )
319+ self ._write_test (['' ], '""' , quoting = csv .QUOTE_NOTNULL )
320+ self ._write_test ([None ], '""' )
321+ self ._write_error_test (csv .Error , [None ], quoting = csv .QUOTE_NONE )
322+ self ._write_error_test (csv .Error , [None ], quoting = csv .QUOTE_STRINGS )
323+ self ._write_error_test (csv .Error , [None ], quoting = csv .QUOTE_NOTNULL )
324+ self ._write_test (['' , '' ], ',' )
325+ self ._write_test ([None , None ], ',' )
326+
327+ def test_write_empty_fields_space_delimiter (self ):
328+ self ._write_test (['' ], '""' , delimiter = ' ' , skipinitialspace = False )
329+ self ._write_test (['' ], '""' , delimiter = ' ' , skipinitialspace = True )
330+ self ._write_test ([None ], '""' , delimiter = ' ' , skipinitialspace = False )
331+ self ._write_test ([None ], '""' , delimiter = ' ' , skipinitialspace = True )
332+
333+ self ._write_test (['' , '' ], ' ' , delimiter = ' ' , skipinitialspace = False )
334+ self ._write_test (['' , '' ], '"" ""' , delimiter = ' ' , skipinitialspace = True )
335+ self ._write_test ([None , None ], ' ' , delimiter = ' ' , skipinitialspace = False )
336+ self ._write_test ([None , None ], '"" ""' , delimiter = ' ' , skipinitialspace = True )
337+
338+ self ._write_test (['' , '' ], ' ' , delimiter = ' ' , skipinitialspace = False ,
339+ quoting = csv .QUOTE_NONE )
340+ self ._write_error_test (csv .Error , ['' , '' ],
341+ delimiter = ' ' , skipinitialspace = True ,
342+ quoting = csv .QUOTE_NONE )
343+ for quoting in csv .QUOTE_STRINGS , csv .QUOTE_NOTNULL :
344+ self ._write_test (['' , '' ], '"" ""' , delimiter = ' ' , skipinitialspace = False ,
345+ quoting = quoting )
346+ self ._write_test (['' , '' ], '"" ""' , delimiter = ' ' , skipinitialspace = True ,
347+ quoting = quoting )
348+
349+ for quoting in csv .QUOTE_NONE , csv .QUOTE_STRINGS , csv .QUOTE_NOTNULL :
350+ self ._write_test ([None , None ], ' ' , delimiter = ' ' , skipinitialspace = False ,
351+ quoting = quoting )
352+ self ._write_error_test (csv .Error , [None , None ],
353+ delimiter = ' ' , skipinitialspace = True ,
354+ quoting = quoting )
355+
318356 def test_writerows_errors (self ):
319357 with TemporaryFile ("w+" , encoding = "utf-8" , newline = '' ) as fileobj :
320358 writer = csv .writer (fileobj )
@@ -429,6 +467,14 @@ def test_read_skipinitialspace(self):
429467 [[None , None , None ]],
430468 skipinitialspace = True , quoting = csv .QUOTE_STRINGS )
431469
470+ def test_read_space_delimiter (self ):
471+ self ._read_test (['a b' , ' a ' , ' ' , '' ],
472+ [['a' , '' , '' , 'b' ], ['' , '' , 'a' , '' , '' ], ['' , '' , '' ], []],
473+ delimiter = ' ' , skipinitialspace = False )
474+ self ._read_test (['a b' , ' a ' , ' ' , '' ],
475+ [['a' , 'b' ], ['a' , '' ], ['' ], []],
476+ delimiter = ' ' , skipinitialspace = True )
477+
432478 def test_read_bigfield (self ):
433479 # This exercises the buffer realloc functionality and field size
434480 # limits.
@@ -555,10 +601,10 @@ class space(csv.excel):
555601 escapechar = "\\ "
556602
557603 with TemporaryFile ("w+" , encoding = "utf-8" ) as fileobj :
558- fileobj .write ("abc def\n c1ccccc1 benzene\n " )
604+ fileobj .write ("abc def\n c1ccccc1 benzene\n " )
559605 fileobj .seek (0 )
560606 reader = csv .reader (fileobj , dialect = space ())
561- self .assertEqual (next (reader ), ["abc" , "def" ])
607+ self .assertEqual (next (reader ), ["abc" , "" , "" , " def" ])
562608 self .assertEqual (next (reader ), ["c1ccccc1" , "benzene" ])
563609
564610 def compare_dialect_123 (self , expected , * writeargs , ** kwwriteargs ):
@@ -1164,8 +1210,9 @@ class mydialect(csv.Dialect):
11641210 self .assertRaises (csv .Error , create_invalid , field_name , 5 )
11651211 self .assertRaises (ValueError , create_invalid , field_name , "\n " )
11661212 self .assertRaises (ValueError , create_invalid , field_name , "\r " )
1167- self .assertRaises (ValueError , create_invalid , field_name , " " ,
1168- skipinitialspace = True )
1213+ if field_name != "delimiter" :
1214+ self .assertRaises (ValueError , create_invalid , field_name , " " ,
1215+ skipinitialspace = True )
11691216
11701217
11711218class TestSniffer (unittest .TestCase ):
0 commit comments