def Deserializer(stream_or_string, **options):
    """
    Deserialize a stream or string of CSV data.
    """
    def process_item(item):
        m = _LIST_RE.match(item)
        if m:
            contents = m.group(1)
            if not contents:
                item = []
            else:
                item = process_m2m(contents)
        else:
            if item == 'TRUE':
                item = True
            elif item == 'FALSE':
                item = False
            elif item == 'NULL':
                item = None
            elif (item in _QUOTED_BOOL_NULL or
                  _QUOTED_LIST_RE.match(item)):
                item = item.strip('\'"')
        return item

    def process_m2m(contents):
        li = []
        if _NK_LIST_RE.match(contents):
            for item in _NK_SPLIT_RE.split(contents):
                li.append(process_item(item))
        else:
            li = _SPLIT_RE.split(contents)
        return li

    if isinstance(stream_or_string, six.string_types):
        stream = StringIO(stream_or_string)
    else:
        stream = stream_or_string

    reader = UnicodeReader(stream)
    header = next(reader)  # first line must be a header

    data = []
    for row in reader:
        # Need to account for the presence of multiple headers in
        # the stream since serialized data can contain them.
        if row[:2] == ['pk', 'model']:
            # Not the best check. Perhaps csv.Sniffer.has_header
            # would be better?
            header = row
            continue
        d = dict(zip(header[:2], row[:2]))
        d['fields'] = dict(zip(header[2:], map(process_item, row[2:])))
        data.append(d)

    for obj in PythonDeserializer(data, **options):
        yield obj
Deserialize a stream or string of CSV data.