@@ -1699,6 +1699,39 @@ def test_sniff_crlf_lineterminator(self):
16991699 dialect = sniffer .sniff (sample )
17001700 self .assertEqual (dialect .delimiter , ',' )
17011701 self .assertEqual (dialect .quotechar , '"' )
1702+ self .assertEqual (dialect .lineterminator , '\r \n ' )
1703+
1704+ def test_sniff_lineterminator (self ):
1705+ sniffer = csv .Sniffer ()
1706+ for lineterminator in '\r \n ' , '\n ' , '\r ' :
1707+ with self .subTest (lineterminator = lineterminator ):
1708+ sample = lineterminator .join (['a,b,c' , 'd,e,f' , 'g,h,i' , '' ])
1709+ dialect = sniffer .sniff (sample )
1710+ self .assertEqual (dialect .lineterminator , lineterminator )
1711+ self .assertEqual (dialect .delimiter , ',' )
1712+ # The majority wins.
1713+ sample = 'a,b,c\n d,e,f\r \n g,h,i\n '
1714+ self .assertEqual (sniffer .sniff (sample ).lineterminator , '\n ' )
1715+ sample = 'a,b,c\r \n d,e,f\n g,h,i\r \n '
1716+ self .assertEqual (sniffer .sniff (sample ).lineterminator , '\r \n ' )
1717+ # A line break inside a quoted field is counted too, but it is
1718+ # outvoted by the real ones.
1719+ sample = 'a,"x\n y",c\r \n d,e,f\r \n g,h,i\r \n '
1720+ self .assertEqual (sniffer .sniff (sample ).lineterminator , '\r \n ' )
1721+
1722+ def test_sniff_lineterminator_tie (self ):
1723+ # A tie is broken in the order '\r\n', '\n', '\r'.
1724+ sniffer = csv .Sniffer ()
1725+ for sample , lineterminator in (
1726+ ('a,b,c\n d,e,f\r \n ' , '\r \n ' ),
1727+ ('a,b,c\r \n d,e,f\n g,h,i\r j,k,l' , '\r \n ' ),
1728+ ('a,b,c\n d,e,f\r g,h,i' , '\n ' ),
1729+ # A sample without a complete line is a tie of zeros.
1730+ ('a,b,c' , '\r \n ' ),
1731+ ):
1732+ with self .subTest (sample = sample ):
1733+ self .assertEqual (sniffer .sniff (sample ).lineterminator ,
1734+ lineterminator )
17021735
17031736 def test_sniff_excel_tab_with_quotes (self ):
17041737 # gh-62029: tab-delimited data with a quoted field containing
0 commit comments