1
|
# CSV I/O
|
2
|
|
3
|
import csv
|
4
|
import StringIO
|
5
|
|
6
|
import util
|
7
|
|
8
|
delimiters = ',\t`'
|
9
|
|
10
|
def stream_info(stream):
|
11
|
'''Automatically detects the dialect based on the header line
|
12
|
@return NamedTuple {header_line, dialect}'''
|
13
|
info = util.NamedTuple()
|
14
|
info.header_line = stream.readline()
|
15
|
sniffer = csv.Sniffer()
|
16
|
info.dialect = sniffer.sniff(info.header_line, delimiters)
|
17
|
info.dialect.doublequote = True # Sniffer doesn't turn this on by default
|
18
|
return info
|
19
|
|
20
|
def reader_and_header(stream):
|
21
|
'''Automatically detects the dialect based on the header line
|
22
|
@return tuple (reader, header)'''
|
23
|
info = stream_info(stream)
|
24
|
header = csv.reader(StringIO.StringIO(info.header_line),
|
25
|
info.dialect).next()
|
26
|
return (csv.reader(stream, info.dialect), header)
|
27
|
|
28
|
##### csv modifications
|
29
|
|
30
|
# Note that these methods only work on *instances* of Dialect classes
|
31
|
csv.Dialect.__eq__ = lambda self, other: self.__dict__ == other.__dict__
|
32
|
csv.Dialect.__ne__ = lambda self, other: not (self == other)
|